diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
28 files changed, 384 insertions, 223 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 406228f4a2a0..b14c81110575 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c | |||
@@ -31,6 +31,7 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/backlight.h> | 33 | #include <linux/backlight.h> |
34 | #include <linux/acpi.h> | ||
34 | 35 | ||
35 | #include "drmP.h" | 36 | #include "drmP.h" |
36 | #include "nouveau_drv.h" | 37 | #include "nouveau_drv.h" |
@@ -136,6 +137,14 @@ int nouveau_backlight_init(struct drm_device *dev) | |||
136 | { | 137 | { |
137 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 138 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
138 | 139 | ||
140 | #ifdef CONFIG_ACPI | ||
141 | if (acpi_video_backlight_support()) { | ||
142 | NV_INFO(dev, "ACPI backlight interface available, " | ||
143 | "not registering our own\n"); | ||
144 | return 0; | ||
145 | } | ||
146 | #endif | ||
147 | |||
139 | switch (dev_priv->card_type) { | 148 | switch (dev_priv->card_type) { |
140 | case NV_40: | 149 | case NV_40: |
141 | return nouveau_nv40_backlight_init(dev); | 150 | return nouveau_nv40_backlight_init(dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 5f21030a293b..b2293576f278 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -6829,7 +6829,7 @@ nouveau_bios_posted(struct drm_device *dev) | |||
6829 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 6829 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
6830 | unsigned htotal; | 6830 | unsigned htotal; |
6831 | 6831 | ||
6832 | if (dev_priv->chipset >= NV_50) { | 6832 | if (dev_priv->card_type >= NV_50) { |
6833 | if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && | 6833 | if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && |
6834 | NVReadVgaCrtc(dev, 0, 0x1a) == 0) | 6834 | NVReadVgaCrtc(dev, 0, 0x1a) == 0) |
6835 | return false; | 6835 | return false; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 80353e2b8409..c41e1c200ef5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -143,8 +143,10 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
143 | nvbo->no_vm = no_vm; | 143 | nvbo->no_vm = no_vm; |
144 | nvbo->tile_mode = tile_mode; | 144 | nvbo->tile_mode = tile_mode; |
145 | nvbo->tile_flags = tile_flags; | 145 | nvbo->tile_flags = tile_flags; |
146 | nvbo->bo.bdev = &dev_priv->ttm.bdev; | ||
146 | 147 | ||
147 | nouveau_bo_fixup_align(dev, tile_mode, tile_flags, &align, &size); | 148 | nouveau_bo_fixup_align(dev, tile_mode, nouveau_bo_tile_layout(nvbo), |
149 | &align, &size); | ||
148 | align >>= PAGE_SHIFT; | 150 | align >>= PAGE_SHIFT; |
149 | 151 | ||
150 | nouveau_bo_placement_set(nvbo, flags, 0); | 152 | nouveau_bo_placement_set(nvbo, flags, 0); |
@@ -176,6 +178,31 @@ set_placement_list(uint32_t *pl, unsigned *n, uint32_t type, uint32_t flags) | |||
176 | pl[(*n)++] = TTM_PL_FLAG_SYSTEM | flags; | 178 | pl[(*n)++] = TTM_PL_FLAG_SYSTEM | flags; |
177 | } | 179 | } |
178 | 180 | ||
181 | static void | ||
182 | set_placement_range(struct nouveau_bo *nvbo, uint32_t type) | ||
183 | { | ||
184 | struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev); | ||
185 | |||
186 | if (dev_priv->card_type == NV_10 && | ||
187 | nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM)) { | ||
188 | /* | ||
189 | * Make sure that the color and depth buffers are handled | ||
190 | * by independent memory controller units. Up to a 9x | ||
191 | * speed up when alpha-blending and depth-test are enabled | ||
192 | * at the same time. | ||
193 | */ | ||
194 | int vram_pages = dev_priv->vram_size >> PAGE_SHIFT; | ||
195 | |||
196 | if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { | ||
197 | nvbo->placement.fpfn = vram_pages / 2; | ||
198 | nvbo->placement.lpfn = ~0; | ||
199 | } else { | ||
200 | nvbo->placement.fpfn = 0; | ||
201 | nvbo->placement.lpfn = vram_pages / 2; | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
179 | void | 206 | void |
180 | nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) | 207 | nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) |
181 | { | 208 | { |
@@ -190,6 +217,8 @@ nouveau_bo_placement_set(struct nouveau_bo *nvbo, uint32_t type, uint32_t busy) | |||
190 | pl->busy_placement = nvbo->busy_placements; | 217 | pl->busy_placement = nvbo->busy_placements; |
191 | set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, | 218 | set_placement_list(nvbo->busy_placements, &pl->num_busy_placement, |
192 | type | busy, flags); | 219 | type | busy, flags); |
220 | |||
221 | set_placement_range(nvbo, type); | ||
193 | } | 222 | } |
194 | 223 | ||
195 | int | 224 | int |
@@ -525,7 +554,8 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | |||
525 | stride = 16 * 4; | 554 | stride = 16 * 4; |
526 | height = amount / stride; | 555 | height = amount / stride; |
527 | 556 | ||
528 | if (new_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { | 557 | if (new_mem->mem_type == TTM_PL_VRAM && |
558 | nouveau_bo_tile_layout(nvbo)) { | ||
529 | ret = RING_SPACE(chan, 8); | 559 | ret = RING_SPACE(chan, 8); |
530 | if (ret) | 560 | if (ret) |
531 | return ret; | 561 | return ret; |
@@ -546,7 +576,8 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | |||
546 | BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); | 576 | BEGIN_RING(chan, NvSubM2MF, 0x0200, 1); |
547 | OUT_RING (chan, 1); | 577 | OUT_RING (chan, 1); |
548 | } | 578 | } |
549 | if (old_mem->mem_type == TTM_PL_VRAM && nvbo->tile_flags) { | 579 | if (old_mem->mem_type == TTM_PL_VRAM && |
580 | nouveau_bo_tile_layout(nvbo)) { | ||
550 | ret = RING_SPACE(chan, 8); | 581 | ret = RING_SPACE(chan, 8); |
551 | if (ret) | 582 | if (ret) |
552 | return ret; | 583 | return ret; |
@@ -753,7 +784,8 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem, | |||
753 | if (dev_priv->card_type == NV_50) { | 784 | if (dev_priv->card_type == NV_50) { |
754 | ret = nv50_mem_vm_bind_linear(dev, | 785 | ret = nv50_mem_vm_bind_linear(dev, |
755 | offset + dev_priv->vm_vram_base, | 786 | offset + dev_priv->vm_vram_base, |
756 | new_mem->size, nvbo->tile_flags, | 787 | new_mem->size, |
788 | nouveau_bo_tile_layout(nvbo), | ||
757 | offset); | 789 | offset); |
758 | if (ret) | 790 | if (ret) |
759 | return ret; | 791 | return ret; |
@@ -894,7 +926,8 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) | |||
894 | * nothing to do here. | 926 | * nothing to do here. |
895 | */ | 927 | */ |
896 | if (bo->mem.mem_type != TTM_PL_VRAM) { | 928 | if (bo->mem.mem_type != TTM_PL_VRAM) { |
897 | if (dev_priv->card_type < NV_50 || !nvbo->tile_flags) | 929 | if (dev_priv->card_type < NV_50 || |
930 | !nouveau_bo_tile_layout(nvbo)) | ||
898 | return 0; | 931 | return 0; |
899 | } | 932 | } |
900 | 933 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 0871495096fa..52c356e9a3d1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -281,7 +281,7 @@ detect_analog: | |||
281 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); | 281 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); |
282 | if (!nv_encoder && !nouveau_tv_disable) | 282 | if (!nv_encoder && !nouveau_tv_disable) |
283 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); | 283 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); |
284 | if (nv_encoder) { | 284 | if (nv_encoder && force) { |
285 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 285 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
286 | struct drm_encoder_helper_funcs *helper = | 286 | struct drm_encoder_helper_funcs *helper = |
287 | encoder->helper_private; | 287 | encoder->helper_private; |
@@ -641,11 +641,28 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
641 | return ret; | 641 | return ret; |
642 | } | 642 | } |
643 | 643 | ||
644 | static unsigned | ||
645 | get_tmds_link_bandwidth(struct drm_connector *connector) | ||
646 | { | ||
647 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
648 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | ||
649 | struct dcb_entry *dcb = nv_connector->detected_encoder->dcb; | ||
650 | |||
651 | if (dcb->location != DCB_LOC_ON_CHIP || | ||
652 | dev_priv->chipset >= 0x46) | ||
653 | return 165000; | ||
654 | else if (dev_priv->chipset >= 0x40) | ||
655 | return 155000; | ||
656 | else if (dev_priv->chipset >= 0x18) | ||
657 | return 135000; | ||
658 | else | ||
659 | return 112000; | ||
660 | } | ||
661 | |||
644 | static int | 662 | static int |
645 | nouveau_connector_mode_valid(struct drm_connector *connector, | 663 | nouveau_connector_mode_valid(struct drm_connector *connector, |
646 | struct drm_display_mode *mode) | 664 | struct drm_display_mode *mode) |
647 | { | 665 | { |
648 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | ||
649 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 666 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
650 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 667 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
651 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 668 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
@@ -663,11 +680,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
663 | max_clock = 400000; | 680 | max_clock = 400000; |
664 | break; | 681 | break; |
665 | case OUTPUT_TMDS: | 682 | case OUTPUT_TMDS: |
666 | if ((dev_priv->card_type >= NV_50 && !nouveau_duallink) || | 683 | max_clock = get_tmds_link_bandwidth(connector); |
667 | !nv_encoder->dcb->duallink_possible) | 684 | if (nouveau_duallink && nv_encoder->dcb->duallink_possible) |
668 | max_clock = 165000; | 685 | max_clock *= 2; |
669 | else | ||
670 | max_clock = 330000; | ||
671 | break; | 686 | break; |
672 | case OUTPUT_ANALOG: | 687 | case OUTPUT_ANALOG: |
673 | max_clock = nv_encoder->dcb->crtconf.maxfreq; | 688 | max_clock = nv_encoder->dcb->crtconf.maxfreq; |
@@ -709,44 +724,6 @@ nouveau_connector_best_encoder(struct drm_connector *connector) | |||
709 | return NULL; | 724 | return NULL; |
710 | } | 725 | } |
711 | 726 | ||
712 | void | ||
713 | nouveau_connector_set_polling(struct drm_connector *connector) | ||
714 | { | ||
715 | struct drm_device *dev = connector->dev; | ||
716 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
717 | struct drm_crtc *crtc; | ||
718 | bool spare_crtc = false; | ||
719 | |||
720 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
721 | spare_crtc |= !crtc->enabled; | ||
722 | |||
723 | connector->polled = 0; | ||
724 | |||
725 | switch (connector->connector_type) { | ||
726 | case DRM_MODE_CONNECTOR_VGA: | ||
727 | case DRM_MODE_CONNECTOR_TV: | ||
728 | if (dev_priv->card_type >= NV_50 || | ||
729 | (nv_gf4_disp_arch(dev) && spare_crtc)) | ||
730 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
731 | break; | ||
732 | |||
733 | case DRM_MODE_CONNECTOR_DVII: | ||
734 | case DRM_MODE_CONNECTOR_DVID: | ||
735 | case DRM_MODE_CONNECTOR_HDMIA: | ||
736 | case DRM_MODE_CONNECTOR_DisplayPort: | ||
737 | case DRM_MODE_CONNECTOR_eDP: | ||
738 | if (dev_priv->card_type >= NV_50) | ||
739 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
740 | else if (connector->connector_type == DRM_MODE_CONNECTOR_DVID || | ||
741 | spare_crtc) | ||
742 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
743 | break; | ||
744 | |||
745 | default: | ||
746 | break; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | static const struct drm_connector_helper_funcs | 727 | static const struct drm_connector_helper_funcs |
751 | nouveau_connector_helper_funcs = { | 728 | nouveau_connector_helper_funcs = { |
752 | .get_modes = nouveau_connector_get_modes, | 729 | .get_modes = nouveau_connector_get_modes, |
@@ -872,6 +849,7 @@ nouveau_connector_create(struct drm_device *dev, int index) | |||
872 | dev->mode_config.scaling_mode_property, | 849 | dev->mode_config.scaling_mode_property, |
873 | nv_connector->scaling_mode); | 850 | nv_connector->scaling_mode); |
874 | } | 851 | } |
852 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
875 | /* fall-through */ | 853 | /* fall-through */ |
876 | case DCB_CONNECTOR_TV_0: | 854 | case DCB_CONNECTOR_TV_0: |
877 | case DCB_CONNECTOR_TV_1: | 855 | case DCB_CONNECTOR_TV_1: |
@@ -888,11 +866,16 @@ nouveau_connector_create(struct drm_device *dev, int index) | |||
888 | dev->mode_config.dithering_mode_property, | 866 | dev->mode_config.dithering_mode_property, |
889 | nv_connector->use_dithering ? | 867 | nv_connector->use_dithering ? |
890 | DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); | 868 | DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); |
869 | |||
870 | if (dcb->type != DCB_CONNECTOR_LVDS) { | ||
871 | if (dev_priv->card_type >= NV_50) | ||
872 | connector->polled = DRM_CONNECTOR_POLL_HPD; | ||
873 | else | ||
874 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||
875 | } | ||
891 | break; | 876 | break; |
892 | } | 877 | } |
893 | 878 | ||
894 | nouveau_connector_set_polling(connector); | ||
895 | |||
896 | drm_sysfs_connector_add(connector); | 879 | drm_sysfs_connector_add(connector); |
897 | dcb->drm = connector; | 880 | dcb->drm = connector; |
898 | return dcb->drm; | 881 | return dcb->drm; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index c21ed6b16f88..711b1e9203af 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h | |||
@@ -52,9 +52,6 @@ static inline struct nouveau_connector *nouveau_connector( | |||
52 | struct drm_connector * | 52 | struct drm_connector * |
53 | nouveau_connector_create(struct drm_device *, int index); | 53 | nouveau_connector_create(struct drm_device *, int index); |
54 | 54 | ||
55 | void | ||
56 | nouveau_connector_set_polling(struct drm_connector *); | ||
57 | |||
58 | int | 55 | int |
59 | nouveau_connector_bpp(struct drm_connector *); | 56 | nouveau_connector_bpp(struct drm_connector *); |
60 | 57 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 3a07e580d27a..1c7db64c03bf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -100,6 +100,9 @@ struct nouveau_bo { | |||
100 | int pin_refcnt; | 100 | int pin_refcnt; |
101 | }; | 101 | }; |
102 | 102 | ||
103 | #define nouveau_bo_tile_layout(nvbo) \ | ||
104 | ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) | ||
105 | |||
103 | static inline struct nouveau_bo * | 106 | static inline struct nouveau_bo * |
104 | nouveau_bo(struct ttm_buffer_object *bo) | 107 | nouveau_bo(struct ttm_buffer_object *bo) |
105 | { | 108 | { |
@@ -304,6 +307,7 @@ struct nouveau_fifo_engine { | |||
304 | void (*destroy_context)(struct nouveau_channel *); | 307 | void (*destroy_context)(struct nouveau_channel *); |
305 | int (*load_context)(struct nouveau_channel *); | 308 | int (*load_context)(struct nouveau_channel *); |
306 | int (*unload_context)(struct drm_device *); | 309 | int (*unload_context)(struct drm_device *); |
310 | void (*tlb_flush)(struct drm_device *dev); | ||
307 | }; | 311 | }; |
308 | 312 | ||
309 | struct nouveau_pgraph_object_method { | 313 | struct nouveau_pgraph_object_method { |
@@ -336,6 +340,7 @@ struct nouveau_pgraph_engine { | |||
336 | void (*destroy_context)(struct nouveau_channel *); | 340 | void (*destroy_context)(struct nouveau_channel *); |
337 | int (*load_context)(struct nouveau_channel *); | 341 | int (*load_context)(struct nouveau_channel *); |
338 | int (*unload_context)(struct drm_device *); | 342 | int (*unload_context)(struct drm_device *); |
343 | void (*tlb_flush)(struct drm_device *dev); | ||
339 | 344 | ||
340 | void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, | 345 | void (*set_region_tiling)(struct drm_device *dev, int i, uint32_t addr, |
341 | uint32_t size, uint32_t pitch); | 346 | uint32_t size, uint32_t pitch); |
@@ -485,13 +490,13 @@ enum nv04_fp_display_regs { | |||
485 | }; | 490 | }; |
486 | 491 | ||
487 | struct nv04_crtc_reg { | 492 | struct nv04_crtc_reg { |
488 | unsigned char MiscOutReg; /* */ | 493 | unsigned char MiscOutReg; |
489 | uint8_t CRTC[0xa0]; | 494 | uint8_t CRTC[0xa0]; |
490 | uint8_t CR58[0x10]; | 495 | uint8_t CR58[0x10]; |
491 | uint8_t Sequencer[5]; | 496 | uint8_t Sequencer[5]; |
492 | uint8_t Graphics[9]; | 497 | uint8_t Graphics[9]; |
493 | uint8_t Attribute[21]; | 498 | uint8_t Attribute[21]; |
494 | unsigned char DAC[768]; /* Internal Colorlookuptable */ | 499 | unsigned char DAC[768]; |
495 | 500 | ||
496 | /* PCRTC regs */ | 501 | /* PCRTC regs */ |
497 | uint32_t fb_start; | 502 | uint32_t fb_start; |
@@ -539,43 +544,9 @@ struct nv04_output_reg { | |||
539 | }; | 544 | }; |
540 | 545 | ||
541 | struct nv04_mode_state { | 546 | struct nv04_mode_state { |
542 | uint32_t bpp; | 547 | struct nv04_crtc_reg crtc_reg[2]; |
543 | uint32_t width; | ||
544 | uint32_t height; | ||
545 | uint32_t interlace; | ||
546 | uint32_t repaint0; | ||
547 | uint32_t repaint1; | ||
548 | uint32_t screen; | ||
549 | uint32_t scale; | ||
550 | uint32_t dither; | ||
551 | uint32_t extra; | ||
552 | uint32_t fifo; | ||
553 | uint32_t pixel; | ||
554 | uint32_t horiz; | ||
555 | int arbitration0; | ||
556 | int arbitration1; | ||
557 | uint32_t pll; | ||
558 | uint32_t pllB; | ||
559 | uint32_t vpll; | ||
560 | uint32_t vpll2; | ||
561 | uint32_t vpllB; | ||
562 | uint32_t vpll2B; | ||
563 | uint32_t pllsel; | 548 | uint32_t pllsel; |
564 | uint32_t sel_clk; | 549 | uint32_t sel_clk; |
565 | uint32_t general; | ||
566 | uint32_t crtcOwner; | ||
567 | uint32_t head; | ||
568 | uint32_t head2; | ||
569 | uint32_t cursorConfig; | ||
570 | uint32_t cursor0; | ||
571 | uint32_t cursor1; | ||
572 | uint32_t cursor2; | ||
573 | uint32_t timingH; | ||
574 | uint32_t timingV; | ||
575 | uint32_t displayV; | ||
576 | uint32_t crtcSync; | ||
577 | |||
578 | struct nv04_crtc_reg crtc_reg[2]; | ||
579 | }; | 550 | }; |
580 | 551 | ||
581 | enum nouveau_card_type { | 552 | enum nouveau_card_type { |
@@ -613,6 +584,12 @@ struct drm_nouveau_private { | |||
613 | struct work_struct irq_work; | 584 | struct work_struct irq_work; |
614 | struct work_struct hpd_work; | 585 | struct work_struct hpd_work; |
615 | 586 | ||
587 | struct { | ||
588 | spinlock_t lock; | ||
589 | uint32_t hpd0_bits; | ||
590 | uint32_t hpd1_bits; | ||
591 | } hpd_state; | ||
592 | |||
616 | struct list_head vbl_waiting; | 593 | struct list_head vbl_waiting; |
617 | 594 | ||
618 | struct { | 595 | struct { |
@@ -1045,6 +1022,7 @@ extern int nv50_fifo_create_context(struct nouveau_channel *); | |||
1045 | extern void nv50_fifo_destroy_context(struct nouveau_channel *); | 1022 | extern void nv50_fifo_destroy_context(struct nouveau_channel *); |
1046 | extern int nv50_fifo_load_context(struct nouveau_channel *); | 1023 | extern int nv50_fifo_load_context(struct nouveau_channel *); |
1047 | extern int nv50_fifo_unload_context(struct drm_device *); | 1024 | extern int nv50_fifo_unload_context(struct drm_device *); |
1025 | extern void nv50_fifo_tlb_flush(struct drm_device *dev); | ||
1048 | 1026 | ||
1049 | /* nvc0_fifo.c */ | 1027 | /* nvc0_fifo.c */ |
1050 | extern int nvc0_fifo_init(struct drm_device *); | 1028 | extern int nvc0_fifo_init(struct drm_device *); |
@@ -1122,6 +1100,8 @@ extern int nv50_graph_load_context(struct nouveau_channel *); | |||
1122 | extern int nv50_graph_unload_context(struct drm_device *); | 1100 | extern int nv50_graph_unload_context(struct drm_device *); |
1123 | extern void nv50_graph_context_switch(struct drm_device *); | 1101 | extern void nv50_graph_context_switch(struct drm_device *); |
1124 | extern int nv50_grctx_init(struct nouveau_grctx *); | 1102 | extern int nv50_grctx_init(struct nouveau_grctx *); |
1103 | extern void nv50_graph_tlb_flush(struct drm_device *dev); | ||
1104 | extern void nv86_graph_tlb_flush(struct drm_device *dev); | ||
1125 | 1105 | ||
1126 | /* nvc0_graph.c */ | 1106 | /* nvc0_graph.c */ |
1127 | extern int nvc0_graph_init(struct drm_device *); | 1107 | extern int nvc0_graph_init(struct drm_device *); |
@@ -1239,7 +1219,6 @@ extern u16 nouveau_bo_rd16(struct nouveau_bo *nvbo, unsigned index); | |||
1239 | extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); | 1219 | extern void nouveau_bo_wr16(struct nouveau_bo *nvbo, unsigned index, u16 val); |
1240 | extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); | 1220 | extern u32 nouveau_bo_rd32(struct nouveau_bo *nvbo, unsigned index); |
1241 | extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); | 1221 | extern void nouveau_bo_wr32(struct nouveau_bo *nvbo, unsigned index, u32 val); |
1242 | extern int nouveau_bo_sync_gpu(struct nouveau_bo *, struct nouveau_channel *); | ||
1243 | 1222 | ||
1244 | /* nouveau_fence.c */ | 1223 | /* nouveau_fence.c */ |
1245 | struct nouveau_fence; | 1224 | struct nouveau_fence; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 441b12420bb1..ab1bbfbf266e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c | |||
@@ -249,6 +249,7 @@ alloc_semaphore(struct drm_device *dev) | |||
249 | { | 249 | { |
250 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 250 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
251 | struct nouveau_semaphore *sema; | 251 | struct nouveau_semaphore *sema; |
252 | int ret; | ||
252 | 253 | ||
253 | if (!USE_SEMA(dev)) | 254 | if (!USE_SEMA(dev)) |
254 | return NULL; | 255 | return NULL; |
@@ -257,10 +258,14 @@ alloc_semaphore(struct drm_device *dev) | |||
257 | if (!sema) | 258 | if (!sema) |
258 | goto fail; | 259 | goto fail; |
259 | 260 | ||
261 | ret = drm_mm_pre_get(&dev_priv->fence.heap); | ||
262 | if (ret) | ||
263 | goto fail; | ||
264 | |||
260 | spin_lock(&dev_priv->fence.lock); | 265 | spin_lock(&dev_priv->fence.lock); |
261 | sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); | 266 | sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0); |
262 | if (sema->mem) | 267 | if (sema->mem) |
263 | sema->mem = drm_mm_get_block(sema->mem, 4, 0); | 268 | sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0); |
264 | spin_unlock(&dev_priv->fence.lock); | 269 | spin_unlock(&dev_priv->fence.lock); |
265 | 270 | ||
266 | if (!sema->mem) | 271 | if (!sema->mem) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 5c4c929d7f74..9a1fdcf400c2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -107,23 +107,29 @@ nouveau_gem_info(struct drm_gem_object *gem, struct drm_nouveau_gem_info *rep) | |||
107 | } | 107 | } |
108 | 108 | ||
109 | static bool | 109 | static bool |
110 | nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) { | 110 | nouveau_gem_tile_flags_valid(struct drm_device *dev, uint32_t tile_flags) |
111 | switch (tile_flags) { | 111 | { |
112 | case 0x0000: | 112 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
113 | case 0x1800: | 113 | |
114 | case 0x2800: | 114 | if (dev_priv->card_type >= NV_50) { |
115 | case 0x4800: | 115 | switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) { |
116 | case 0x7000: | 116 | case 0x0000: |
117 | case 0x7400: | 117 | case 0x1800: |
118 | case 0x7a00: | 118 | case 0x2800: |
119 | case 0xe000: | 119 | case 0x4800: |
120 | break; | 120 | case 0x7000: |
121 | default: | 121 | case 0x7400: |
122 | NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); | 122 | case 0x7a00: |
123 | return false; | 123 | case 0xe000: |
124 | return true; | ||
125 | } | ||
126 | } else { | ||
127 | if (!(tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK)) | ||
128 | return true; | ||
124 | } | 129 | } |
125 | 130 | ||
126 | return true; | 131 | NV_ERROR(dev, "bad page flags: 0x%08x\n", tile_flags); |
132 | return false; | ||
127 | } | 133 | } |
128 | 134 | ||
129 | int | 135 | int |
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index bed669a54a2d..b9672a05c411 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c | |||
@@ -519,11 +519,11 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | |||
519 | 519 | ||
520 | struct pll_lims pll_lim; | 520 | struct pll_lims pll_lim; |
521 | struct nouveau_pll_vals pv; | 521 | struct nouveau_pll_vals pv; |
522 | uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; | 522 | enum pll_types pll = head ? PLL_VPLL1 : PLL_VPLL0; |
523 | 523 | ||
524 | if (get_pll_limits(dev, pllreg, &pll_lim)) | 524 | if (get_pll_limits(dev, pll, &pll_lim)) |
525 | return; | 525 | return; |
526 | nouveau_hw_get_pllvals(dev, pllreg, &pv); | 526 | nouveau_hw_get_pllvals(dev, pll, &pv); |
527 | 527 | ||
528 | if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && | 528 | if (pv.M1 >= pll_lim.vco1.min_m && pv.M1 <= pll_lim.vco1.max_m && |
529 | pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && | 529 | pv.N1 >= pll_lim.vco1.min_n && pv.N1 <= pll_lim.vco1.max_n && |
@@ -536,7 +536,7 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | |||
536 | pv.M1 = pll_lim.vco1.max_m; | 536 | pv.M1 = pll_lim.vco1.max_m; |
537 | pv.N1 = pll_lim.vco1.min_n; | 537 | pv.N1 = pll_lim.vco1.min_n; |
538 | pv.log2P = pll_lim.max_usable_log2p; | 538 | pv.log2P = pll_lim.max_usable_log2p; |
539 | nouveau_hw_setpll(dev, pllreg, &pv); | 539 | nouveau_hw_setpll(dev, pll_lim.reg, &pv); |
540 | } | 540 | } |
541 | 541 | ||
542 | /* | 542 | /* |
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.h b/drivers/gpu/drm/nouveau/nouveau_hw.h index 869130f83602..2989090b9434 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.h +++ b/drivers/gpu/drm/nouveau/nouveau_hw.h | |||
@@ -416,6 +416,25 @@ nv_fix_nv40_hw_cursor(struct drm_device *dev, int head) | |||
416 | } | 416 | } |
417 | 417 | ||
418 | static inline void | 418 | static inline void |
419 | nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) | ||
420 | { | ||
421 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
422 | |||
423 | NVWriteCRTC(dev, head, NV_PCRTC_START, offset); | ||
424 | |||
425 | if (dev_priv->card_type == NV_04) { | ||
426 | /* | ||
427 | * Hilarious, the 24th bit doesn't want to stick to | ||
428 | * PCRTC_START... | ||
429 | */ | ||
430 | int cre_heb = NVReadVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX); | ||
431 | |||
432 | NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HEB__INDEX, | ||
433 | (cre_heb & ~0x40) | ((offset >> 18) & 0x40)); | ||
434 | } | ||
435 | } | ||
436 | |||
437 | static inline void | ||
419 | nv_show_cursor(struct drm_device *dev, int head, bool show) | 438 | nv_show_cursor(struct drm_device *dev, int head, bool show) |
420 | { | 439 | { |
421 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 440 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index fdd7e3de79c8..cb389d014326 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -256,7 +256,7 @@ nouveau_i2c_find(struct drm_device *dev, int index) | |||
256 | if (index >= DCB_MAX_NUM_I2C_ENTRIES) | 256 | if (index >= DCB_MAX_NUM_I2C_ENTRIES) |
257 | return NULL; | 257 | return NULL; |
258 | 258 | ||
259 | if (dev_priv->chipset >= NV_50 && (i2c->entry & 0x00000100)) { | 259 | if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) { |
260 | uint32_t reg = 0xe500, val; | 260 | uint32_t reg = 0xe500, val; |
261 | 261 | ||
262 | if (i2c->port_type == 6) { | 262 | if (i2c->port_type == 6) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 6fd51a51c608..7bfd9e6c9d67 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -42,6 +42,13 @@ | |||
42 | #include "nouveau_connector.h" | 42 | #include "nouveau_connector.h" |
43 | #include "nv50_display.h" | 43 | #include "nv50_display.h" |
44 | 44 | ||
45 | static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); | ||
46 | |||
47 | static int nouveau_ratelimit(void) | ||
48 | { | ||
49 | return __ratelimit(&nouveau_ratelimit_state); | ||
50 | } | ||
51 | |||
45 | void | 52 | void |
46 | nouveau_irq_preinstall(struct drm_device *dev) | 53 | nouveau_irq_preinstall(struct drm_device *dev) |
47 | { | 54 | { |
@@ -53,6 +60,7 @@ nouveau_irq_preinstall(struct drm_device *dev) | |||
53 | if (dev_priv->card_type >= NV_50) { | 60 | if (dev_priv->card_type >= NV_50) { |
54 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); | 61 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); |
55 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); | 62 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); |
63 | spin_lock_init(&dev_priv->hpd_state.lock); | ||
56 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); | 64 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); |
57 | } | 65 | } |
58 | } | 66 | } |
@@ -202,8 +210,8 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
202 | } | 210 | } |
203 | 211 | ||
204 | if (status & NV_PFIFO_INTR_DMA_PUSHER) { | 212 | if (status & NV_PFIFO_INTR_DMA_PUSHER) { |
205 | u32 get = nv_rd32(dev, 0x003244); | 213 | u32 dma_get = nv_rd32(dev, 0x003244); |
206 | u32 put = nv_rd32(dev, 0x003240); | 214 | u32 dma_put = nv_rd32(dev, 0x003240); |
207 | u32 push = nv_rd32(dev, 0x003220); | 215 | u32 push = nv_rd32(dev, 0x003220); |
208 | u32 state = nv_rd32(dev, 0x003228); | 216 | u32 state = nv_rd32(dev, 0x003228); |
209 | 217 | ||
@@ -213,16 +221,18 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
213 | u32 ib_get = nv_rd32(dev, 0x003334); | 221 | u32 ib_get = nv_rd32(dev, 0x003334); |
214 | u32 ib_put = nv_rd32(dev, 0x003330); | 222 | u32 ib_put = nv_rd32(dev, 0x003330); |
215 | 223 | ||
216 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " | 224 | if (nouveau_ratelimit()) |
225 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x " | ||
217 | "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " | 226 | "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " |
218 | "State 0x%08x Push 0x%08x\n", | 227 | "State 0x%08x Push 0x%08x\n", |
219 | chid, ho_get, get, ho_put, put, ib_get, ib_put, | 228 | chid, ho_get, dma_get, ho_put, |
220 | state, push); | 229 | dma_put, ib_get, ib_put, state, |
230 | push); | ||
221 | 231 | ||
222 | /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ | 232 | /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ |
223 | nv_wr32(dev, 0x003364, 0x00000000); | 233 | nv_wr32(dev, 0x003364, 0x00000000); |
224 | if (get != put || ho_get != ho_put) { | 234 | if (dma_get != dma_put || ho_get != ho_put) { |
225 | nv_wr32(dev, 0x003244, put); | 235 | nv_wr32(dev, 0x003244, dma_put); |
226 | nv_wr32(dev, 0x003328, ho_put); | 236 | nv_wr32(dev, 0x003328, ho_put); |
227 | } else | 237 | } else |
228 | if (ib_get != ib_put) { | 238 | if (ib_get != ib_put) { |
@@ -231,10 +241,10 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
231 | } else { | 241 | } else { |
232 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " | 242 | NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x " |
233 | "Put 0x%08x State 0x%08x Push 0x%08x\n", | 243 | "Put 0x%08x State 0x%08x Push 0x%08x\n", |
234 | chid, get, put, state, push); | 244 | chid, dma_get, dma_put, state, push); |
235 | 245 | ||
236 | if (get != put) | 246 | if (dma_get != dma_put) |
237 | nv_wr32(dev, 0x003244, put); | 247 | nv_wr32(dev, 0x003244, dma_put); |
238 | } | 248 | } |
239 | 249 | ||
240 | nv_wr32(dev, 0x003228, 0x00000000); | 250 | nv_wr32(dev, 0x003228, 0x00000000); |
@@ -266,8 +276,9 @@ nouveau_fifo_irq_handler(struct drm_device *dev) | |||
266 | } | 276 | } |
267 | 277 | ||
268 | if (status) { | 278 | if (status) { |
269 | NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", | 279 | if (nouveau_ratelimit()) |
270 | status, chid); | 280 | NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", |
281 | status, chid); | ||
271 | nv_wr32(dev, NV03_PFIFO_INTR_0, status); | 282 | nv_wr32(dev, NV03_PFIFO_INTR_0, status); |
272 | status = 0; | 283 | status = 0; |
273 | } | 284 | } |
@@ -544,13 +555,6 @@ nouveau_pgraph_intr_notify(struct drm_device *dev, uint32_t nsource) | |||
544 | nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); | 555 | nouveau_graph_dump_trap_info(dev, "PGRAPH_NOTIFY", &trap); |
545 | } | 556 | } |
546 | 557 | ||
547 | static DEFINE_RATELIMIT_STATE(nouveau_ratelimit_state, 3 * HZ, 20); | ||
548 | |||
549 | static int nouveau_ratelimit(void) | ||
550 | { | ||
551 | return __ratelimit(&nouveau_ratelimit_state); | ||
552 | } | ||
553 | |||
554 | 558 | ||
555 | static inline void | 559 | static inline void |
556 | nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) | 560 | nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index a163c7c612e7..fe4a30dc4b42 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -33,9 +33,9 @@ | |||
33 | #include "drmP.h" | 33 | #include "drmP.h" |
34 | #include "drm.h" | 34 | #include "drm.h" |
35 | #include "drm_sarea.h" | 35 | #include "drm_sarea.h" |
36 | #include "nouveau_drv.h" | ||
37 | 36 | ||
38 | #define MIN(a,b) a < b ? a : b | 37 | #include "nouveau_drv.h" |
38 | #include "nouveau_pm.h" | ||
39 | 39 | ||
40 | /* | 40 | /* |
41 | * NV10-NV40 tiling helpers | 41 | * NV10-NV40 tiling helpers |
@@ -175,11 +175,10 @@ nv50_mem_vm_bind_linear(struct drm_device *dev, uint64_t virt, uint32_t size, | |||
175 | } | 175 | } |
176 | } | 176 | } |
177 | } | 177 | } |
178 | dev_priv->engine.instmem.flush(dev); | ||
179 | 178 | ||
180 | nv50_vm_flush(dev, 5); | 179 | dev_priv->engine.instmem.flush(dev); |
181 | nv50_vm_flush(dev, 0); | 180 | dev_priv->engine.fifo.tlb_flush(dev); |
182 | nv50_vm_flush(dev, 4); | 181 | dev_priv->engine.graph.tlb_flush(dev); |
183 | nv50_vm_flush(dev, 6); | 182 | nv50_vm_flush(dev, 6); |
184 | return 0; | 183 | return 0; |
185 | } | 184 | } |
@@ -209,11 +208,10 @@ nv50_mem_vm_unbind(struct drm_device *dev, uint64_t virt, uint32_t size) | |||
209 | pte++; | 208 | pte++; |
210 | } | 209 | } |
211 | } | 210 | } |
212 | dev_priv->engine.instmem.flush(dev); | ||
213 | 211 | ||
214 | nv50_vm_flush(dev, 5); | 212 | dev_priv->engine.instmem.flush(dev); |
215 | nv50_vm_flush(dev, 0); | 213 | dev_priv->engine.fifo.tlb_flush(dev); |
216 | nv50_vm_flush(dev, 4); | 214 | dev_priv->engine.graph.tlb_flush(dev); |
217 | nv50_vm_flush(dev, 6); | 215 | nv50_vm_flush(dev, 6); |
218 | } | 216 | } |
219 | 217 | ||
@@ -653,6 +651,7 @@ nouveau_mem_gart_init(struct drm_device *dev) | |||
653 | void | 651 | void |
654 | nouveau_mem_timing_init(struct drm_device *dev) | 652 | nouveau_mem_timing_init(struct drm_device *dev) |
655 | { | 653 | { |
654 | /* cards < NVC0 only */ | ||
656 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 655 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
657 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 656 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |
658 | struct nouveau_pm_memtimings *memtimings = &pm->memtimings; | 657 | struct nouveau_pm_memtimings *memtimings = &pm->memtimings; |
@@ -719,14 +718,14 @@ nouveau_mem_timing_init(struct drm_device *dev) | |||
719 | tUNK_19 = 1; | 718 | tUNK_19 = 1; |
720 | tUNK_20 = 0; | 719 | tUNK_20 = 0; |
721 | tUNK_21 = 0; | 720 | tUNK_21 = 0; |
722 | switch (MIN(recordlen,21)) { | 721 | switch (min(recordlen, 22)) { |
723 | case 21: | 722 | case 22: |
724 | tUNK_21 = entry[21]; | 723 | tUNK_21 = entry[21]; |
725 | case 20: | 724 | case 21: |
726 | tUNK_20 = entry[20]; | 725 | tUNK_20 = entry[20]; |
727 | case 19: | 726 | case 20: |
728 | tUNK_19 = entry[19]; | 727 | tUNK_19 = entry[19]; |
729 | case 18: | 728 | case 19: |
730 | tUNK_18 = entry[18]; | 729 | tUNK_18 = entry[18]; |
731 | default: | 730 | default: |
732 | tUNK_0 = entry[0]; | 731 | tUNK_0 = entry[0]; |
@@ -756,24 +755,30 @@ nouveau_mem_timing_init(struct drm_device *dev) | |||
756 | timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); | 755 | timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10); |
757 | if(recordlen > 19) { | 756 | if(recordlen > 19) { |
758 | timing->reg_100228 += (tUNK_19 - 1) << 24; | 757 | timing->reg_100228 += (tUNK_19 - 1) << 24; |
759 | } else { | 758 | }/* I cannot back-up this else-statement right now |
759 | else { | ||
760 | timing->reg_100228 += tUNK_12 << 24; | 760 | timing->reg_100228 += tUNK_12 << 24; |
761 | } | 761 | }*/ |
762 | 762 | ||
763 | /* XXX: reg_10022c */ | 763 | /* XXX: reg_10022c */ |
764 | timing->reg_10022c = tUNK_2 - 1; | ||
764 | 765 | ||
765 | timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | | 766 | timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 | |
766 | tUNK_13 << 8 | tUNK_13); | 767 | tUNK_13 << 8 | tUNK_13); |
767 | 768 | ||
768 | /* XXX: +6? */ | 769 | /* XXX: +6? */ |
769 | timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); | 770 | timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC); |
770 | if(tUNK_10 > tUNK_11) { | 771 | timing->reg_100234 += max(tUNK_10,tUNK_11) << 16; |
771 | timing->reg_100234 += tUNK_10 << 16; | 772 | |
772 | } else { | 773 | /* XXX; reg_100238, reg_10023c |
773 | timing->reg_100234 += tUNK_11 << 16; | 774 | * reg: 0x00?????? |
775 | * reg_10023c: | ||
776 | * 0 for pre-NV50 cards | ||
777 | * 0x????0202 for NV50+ cards (empirical evidence) */ | ||
778 | if(dev_priv->card_type >= NV_50) { | ||
779 | timing->reg_10023c = 0x202; | ||
774 | } | 780 | } |
775 | 781 | ||
776 | /* XXX; reg_100238, reg_10023c */ | ||
777 | NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, | 782 | NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i, |
778 | timing->reg_100220, timing->reg_100224, | 783 | timing->reg_100220, timing->reg_100224, |
779 | timing->reg_100228, timing->reg_10022c); | 784 | timing->reg_100228, timing->reg_10022c); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_object.c b/drivers/gpu/drm/nouveau/nouveau_object.c index 896cf8634144..dd572adca02a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/drivers/gpu/drm/nouveau/nouveau_object.c | |||
@@ -129,7 +129,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
129 | if (ramin == NULL) { | 129 | if (ramin == NULL) { |
130 | spin_unlock(&dev_priv->ramin_lock); | 130 | spin_unlock(&dev_priv->ramin_lock); |
131 | nouveau_gpuobj_ref(NULL, &gpuobj); | 131 | nouveau_gpuobj_ref(NULL, &gpuobj); |
132 | return ret; | 132 | return -ENOMEM; |
133 | } | 133 | } |
134 | 134 | ||
135 | ramin = drm_mm_get_block_atomic(ramin, size, align); | 135 | ramin = drm_mm_get_block_atomic(ramin, size, align); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index 1c99c55d6d46..9f7b158f5825 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -284,6 +284,7 @@ nouveau_sysfs_fini(struct drm_device *dev) | |||
284 | } | 284 | } |
285 | } | 285 | } |
286 | 286 | ||
287 | #ifdef CONFIG_HWMON | ||
287 | static ssize_t | 288 | static ssize_t |
288 | nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | 289 | nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) |
289 | { | 290 | { |
@@ -395,10 +396,12 @@ static struct attribute *hwmon_attributes[] = { | |||
395 | static const struct attribute_group hwmon_attrgroup = { | 396 | static const struct attribute_group hwmon_attrgroup = { |
396 | .attrs = hwmon_attributes, | 397 | .attrs = hwmon_attributes, |
397 | }; | 398 | }; |
399 | #endif | ||
398 | 400 | ||
399 | static int | 401 | static int |
400 | nouveau_hwmon_init(struct drm_device *dev) | 402 | nouveau_hwmon_init(struct drm_device *dev) |
401 | { | 403 | { |
404 | #ifdef CONFIG_HWMON | ||
402 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 405 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
403 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 406 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |
404 | struct device *hwmon_dev; | 407 | struct device *hwmon_dev; |
@@ -425,13 +428,14 @@ nouveau_hwmon_init(struct drm_device *dev) | |||
425 | } | 428 | } |
426 | 429 | ||
427 | pm->hwmon = hwmon_dev; | 430 | pm->hwmon = hwmon_dev; |
428 | 431 | #endif | |
429 | return 0; | 432 | return 0; |
430 | } | 433 | } |
431 | 434 | ||
432 | static void | 435 | static void |
433 | nouveau_hwmon_fini(struct drm_device *dev) | 436 | nouveau_hwmon_fini(struct drm_device *dev) |
434 | { | 437 | { |
438 | #ifdef CONFIG_HWMON | ||
435 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 439 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
436 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 440 | struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |
437 | 441 | ||
@@ -439,6 +443,7 @@ nouveau_hwmon_fini(struct drm_device *dev) | |||
439 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); | 443 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); |
440 | hwmon_device_unregister(pm->hwmon); | 444 | hwmon_device_unregister(pm->hwmon); |
441 | } | 445 | } |
446 | #endif | ||
442 | } | 447 | } |
443 | 448 | ||
444 | int | 449 | int |
diff --git a/drivers/gpu/drm/nouveau/nouveau_ramht.c b/drivers/gpu/drm/nouveau/nouveau_ramht.c index 7f16697cc96c..2d8580927ca4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ramht.c +++ b/drivers/gpu/drm/nouveau/nouveau_ramht.c | |||
@@ -153,26 +153,42 @@ nouveau_ramht_insert(struct nouveau_channel *chan, u32 handle, | |||
153 | return -ENOMEM; | 153 | return -ENOMEM; |
154 | } | 154 | } |
155 | 155 | ||
156 | static struct nouveau_ramht_entry * | ||
157 | nouveau_ramht_remove_entry(struct nouveau_channel *chan, u32 handle) | ||
158 | { | ||
159 | struct nouveau_ramht *ramht = chan ? chan->ramht : NULL; | ||
160 | struct nouveau_ramht_entry *entry; | ||
161 | unsigned long flags; | ||
162 | |||
163 | if (!ramht) | ||
164 | return NULL; | ||
165 | |||
166 | spin_lock_irqsave(&ramht->lock, flags); | ||
167 | list_for_each_entry(entry, &ramht->entries, head) { | ||
168 | if (entry->channel == chan && | ||
169 | (!handle || entry->handle == handle)) { | ||
170 | list_del(&entry->head); | ||
171 | spin_unlock_irqrestore(&ramht->lock, flags); | ||
172 | |||
173 | return entry; | ||
174 | } | ||
175 | } | ||
176 | spin_unlock_irqrestore(&ramht->lock, flags); | ||
177 | |||
178 | return NULL; | ||
179 | } | ||
180 | |||
156 | static void | 181 | static void |
157 | nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle) | 182 | nouveau_ramht_remove_hash(struct nouveau_channel *chan, u32 handle) |
158 | { | 183 | { |
159 | struct drm_device *dev = chan->dev; | 184 | struct drm_device *dev = chan->dev; |
160 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 185 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
161 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; | 186 | struct nouveau_instmem_engine *instmem = &dev_priv->engine.instmem; |
162 | struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; | 187 | struct nouveau_gpuobj *ramht = chan->ramht->gpuobj; |
163 | struct nouveau_ramht_entry *entry, *tmp; | 188 | unsigned long flags; |
164 | u32 co, ho; | 189 | u32 co, ho; |
165 | 190 | ||
166 | list_for_each_entry_safe(entry, tmp, &chan->ramht->entries, head) { | 191 | spin_lock_irqsave(&chan->ramht->lock, flags); |
167 | if (entry->channel != chan || entry->handle != handle) | ||
168 | continue; | ||
169 | |||
170 | nouveau_gpuobj_ref(NULL, &entry->gpuobj); | ||
171 | list_del(&entry->head); | ||
172 | kfree(entry); | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | co = ho = nouveau_ramht_hash_handle(chan, handle); | 192 | co = ho = nouveau_ramht_hash_handle(chan, handle); |
177 | do { | 193 | do { |
178 | if (nouveau_ramht_entry_valid(dev, ramht, co) && | 194 | if (nouveau_ramht_entry_valid(dev, ramht, co) && |
@@ -184,7 +200,7 @@ nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle) | |||
184 | nv_wo32(ramht, co + 0, 0x00000000); | 200 | nv_wo32(ramht, co + 0, 0x00000000); |
185 | nv_wo32(ramht, co + 4, 0x00000000); | 201 | nv_wo32(ramht, co + 4, 0x00000000); |
186 | instmem->flush(dev); | 202 | instmem->flush(dev); |
187 | return; | 203 | goto out; |
188 | } | 204 | } |
189 | 205 | ||
190 | co += 8; | 206 | co += 8; |
@@ -194,17 +210,22 @@ nouveau_ramht_remove_locked(struct nouveau_channel *chan, u32 handle) | |||
194 | 210 | ||
195 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", | 211 | NV_ERROR(dev, "RAMHT entry not found. ch=%d, handle=0x%08x\n", |
196 | chan->id, handle); | 212 | chan->id, handle); |
213 | out: | ||
214 | spin_unlock_irqrestore(&chan->ramht->lock, flags); | ||
197 | } | 215 | } |
198 | 216 | ||
199 | void | 217 | void |
200 | nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) | 218 | nouveau_ramht_remove(struct nouveau_channel *chan, u32 handle) |
201 | { | 219 | { |
202 | struct nouveau_ramht *ramht = chan->ramht; | 220 | struct nouveau_ramht_entry *entry; |
203 | unsigned long flags; | ||
204 | 221 | ||
205 | spin_lock_irqsave(&ramht->lock, flags); | 222 | entry = nouveau_ramht_remove_entry(chan, handle); |
206 | nouveau_ramht_remove_locked(chan, handle); | 223 | if (!entry) |
207 | spin_unlock_irqrestore(&ramht->lock, flags); | 224 | return; |
225 | |||
226 | nouveau_ramht_remove_hash(chan, entry->handle); | ||
227 | nouveau_gpuobj_ref(NULL, &entry->gpuobj); | ||
228 | kfree(entry); | ||
208 | } | 229 | } |
209 | 230 | ||
210 | struct nouveau_gpuobj * | 231 | struct nouveau_gpuobj * |
@@ -265,23 +286,19 @@ void | |||
265 | nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, | 286 | nouveau_ramht_ref(struct nouveau_ramht *ref, struct nouveau_ramht **ptr, |
266 | struct nouveau_channel *chan) | 287 | struct nouveau_channel *chan) |
267 | { | 288 | { |
268 | struct nouveau_ramht_entry *entry, *tmp; | 289 | struct nouveau_ramht_entry *entry; |
269 | struct nouveau_ramht *ramht; | 290 | struct nouveau_ramht *ramht; |
270 | unsigned long flags; | ||
271 | 291 | ||
272 | if (ref) | 292 | if (ref) |
273 | kref_get(&ref->refcount); | 293 | kref_get(&ref->refcount); |
274 | 294 | ||
275 | ramht = *ptr; | 295 | ramht = *ptr; |
276 | if (ramht) { | 296 | if (ramht) { |
277 | spin_lock_irqsave(&ramht->lock, flags); | 297 | while ((entry = nouveau_ramht_remove_entry(chan, 0))) { |
278 | list_for_each_entry_safe(entry, tmp, &ramht->entries, head) { | 298 | nouveau_ramht_remove_hash(chan, entry->handle); |
279 | if (entry->channel != chan) | 299 | nouveau_gpuobj_ref(NULL, &entry->gpuobj); |
280 | continue; | 300 | kfree(entry); |
281 | |||
282 | nouveau_ramht_remove_locked(chan, entry->handle); | ||
283 | } | 301 | } |
284 | spin_unlock_irqrestore(&ramht->lock, flags); | ||
285 | 302 | ||
286 | kref_put(&ramht->refcount, nouveau_ramht_del); | 303 | kref_put(&ramht->refcount, nouveau_ramht_del); |
287 | } | 304 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index 288bacac7e5a..d4ac97007038 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c | |||
@@ -120,8 +120,8 @@ nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem) | |||
120 | dev_priv->engine.instmem.flush(nvbe->dev); | 120 | dev_priv->engine.instmem.flush(nvbe->dev); |
121 | 121 | ||
122 | if (dev_priv->card_type == NV_50) { | 122 | if (dev_priv->card_type == NV_50) { |
123 | nv50_vm_flush(dev, 5); /* PGRAPH */ | 123 | dev_priv->engine.fifo.tlb_flush(dev); |
124 | nv50_vm_flush(dev, 0); /* PFIFO */ | 124 | dev_priv->engine.graph.tlb_flush(dev); |
125 | } | 125 | } |
126 | 126 | ||
127 | nvbe->bound = true; | 127 | nvbe->bound = true; |
@@ -162,8 +162,8 @@ nouveau_sgdma_unbind(struct ttm_backend *be) | |||
162 | dev_priv->engine.instmem.flush(nvbe->dev); | 162 | dev_priv->engine.instmem.flush(nvbe->dev); |
163 | 163 | ||
164 | if (dev_priv->card_type == NV_50) { | 164 | if (dev_priv->card_type == NV_50) { |
165 | nv50_vm_flush(dev, 5); | 165 | dev_priv->engine.fifo.tlb_flush(dev); |
166 | nv50_vm_flush(dev, 0); | 166 | dev_priv->engine.graph.tlb_flush(dev); |
167 | } | 167 | } |
168 | 168 | ||
169 | nvbe->bound = false; | 169 | nvbe->bound = false; |
@@ -224,7 +224,11 @@ nouveau_sgdma_init(struct drm_device *dev) | |||
224 | int i, ret; | 224 | int i, ret; |
225 | 225 | ||
226 | if (dev_priv->card_type < NV_50) { | 226 | if (dev_priv->card_type < NV_50) { |
227 | aper_size = (64 * 1024 * 1024); | 227 | if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024) |
228 | aper_size = 64 * 1024 * 1024; | ||
229 | else | ||
230 | aper_size = 512 * 1024 * 1024; | ||
231 | |||
228 | obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; | 232 | obj_size = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4; |
229 | obj_size += 8; /* ctxdma header */ | 233 | obj_size += 8; /* ctxdma header */ |
230 | } else { | 234 | } else { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index ed7757f14083..049f755567e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -354,6 +354,15 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
354 | engine->graph.destroy_context = nv50_graph_destroy_context; | 354 | engine->graph.destroy_context = nv50_graph_destroy_context; |
355 | engine->graph.load_context = nv50_graph_load_context; | 355 | engine->graph.load_context = nv50_graph_load_context; |
356 | engine->graph.unload_context = nv50_graph_unload_context; | 356 | engine->graph.unload_context = nv50_graph_unload_context; |
357 | if (dev_priv->chipset != 0x86) | ||
358 | engine->graph.tlb_flush = nv50_graph_tlb_flush; | ||
359 | else { | ||
360 | /* from what i can see nvidia do this on every | ||
361 | * pre-NVA3 board except NVAC, but, we've only | ||
362 | * ever seen problems on NV86 | ||
363 | */ | ||
364 | engine->graph.tlb_flush = nv86_graph_tlb_flush; | ||
365 | } | ||
357 | engine->fifo.channels = 128; | 366 | engine->fifo.channels = 128; |
358 | engine->fifo.init = nv50_fifo_init; | 367 | engine->fifo.init = nv50_fifo_init; |
359 | engine->fifo.takedown = nv50_fifo_takedown; | 368 | engine->fifo.takedown = nv50_fifo_takedown; |
@@ -365,6 +374,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
365 | engine->fifo.destroy_context = nv50_fifo_destroy_context; | 374 | engine->fifo.destroy_context = nv50_fifo_destroy_context; |
366 | engine->fifo.load_context = nv50_fifo_load_context; | 375 | engine->fifo.load_context = nv50_fifo_load_context; |
367 | engine->fifo.unload_context = nv50_fifo_unload_context; | 376 | engine->fifo.unload_context = nv50_fifo_unload_context; |
377 | engine->fifo.tlb_flush = nv50_fifo_tlb_flush; | ||
368 | engine->display.early_init = nv50_display_early_init; | 378 | engine->display.early_init = nv50_display_early_init; |
369 | engine->display.late_takedown = nv50_display_late_takedown; | 379 | engine->display.late_takedown = nv50_display_late_takedown; |
370 | engine->display.create = nv50_display_create; | 380 | engine->display.create = nv50_display_create; |
@@ -1041,6 +1051,9 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
1041 | case NOUVEAU_GETPARAM_PTIMER_TIME: | 1051 | case NOUVEAU_GETPARAM_PTIMER_TIME: |
1042 | getparam->value = dev_priv->engine.timer.read(dev); | 1052 | getparam->value = dev_priv->engine.timer.read(dev); |
1043 | break; | 1053 | break; |
1054 | case NOUVEAU_GETPARAM_HAS_BO_USAGE: | ||
1055 | getparam->value = 1; | ||
1056 | break; | ||
1044 | case NOUVEAU_GETPARAM_GRAPH_UNITS: | 1057 | case NOUVEAU_GETPARAM_GRAPH_UNITS: |
1045 | /* NV40 and NV50 versions are quite different, but register | 1058 | /* NV40 and NV50 versions are quite different, but register |
1046 | * address is the same. User is supposed to know the card | 1059 | * address is the same. User is supposed to know the card |
@@ -1051,7 +1064,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, | |||
1051 | } | 1064 | } |
1052 | /* FALLTHRU */ | 1065 | /* FALLTHRU */ |
1053 | default: | 1066 | default: |
1054 | NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); | 1067 | NV_DEBUG(dev, "unknown parameter %lld\n", getparam->param); |
1055 | return -EINVAL; | 1068 | return -EINVAL; |
1056 | } | 1069 | } |
1057 | 1070 | ||
@@ -1066,7 +1079,7 @@ nouveau_ioctl_setparam(struct drm_device *dev, void *data, | |||
1066 | 1079 | ||
1067 | switch (setparam->param) { | 1080 | switch (setparam->param) { |
1068 | default: | 1081 | default: |
1069 | NV_ERROR(dev, "unknown parameter %lld\n", setparam->param); | 1082 | NV_DEBUG(dev, "unknown parameter %lld\n", setparam->param); |
1070 | return -EINVAL; | 1083 | return -EINVAL; |
1071 | } | 1084 | } |
1072 | 1085 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 16bbbf1eff63..7ecc4adc1e45 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c | |||
@@ -191,7 +191,7 @@ nv40_temp_get(struct drm_device *dev) | |||
191 | int offset = sensor->offset_mult / sensor->offset_div; | 191 | int offset = sensor->offset_mult / sensor->offset_div; |
192 | int core_temp; | 192 | int core_temp; |
193 | 193 | ||
194 | if (dev_priv->chipset >= 0x50) { | 194 | if (dev_priv->card_type >= NV_50) { |
195 | core_temp = nv_rd32(dev, 0x20008); | 195 | core_temp = nv_rd32(dev, 0x20008); |
196 | } else { | 196 | } else { |
197 | core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; | 197 | core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index c71abc2a34d5..40e180741629 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -158,7 +158,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
158 | { | 158 | { |
159 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 159 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
160 | struct drm_device *dev = crtc->dev; | 160 | struct drm_device *dev = crtc->dev; |
161 | struct drm_connector *connector; | ||
162 | unsigned char seq1 = 0, crtc17 = 0; | 161 | unsigned char seq1 = 0, crtc17 = 0; |
163 | unsigned char crtc1A; | 162 | unsigned char crtc1A; |
164 | 163 | ||
@@ -213,10 +212,6 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
213 | NVVgaSeqReset(dev, nv_crtc->index, false); | 212 | NVVgaSeqReset(dev, nv_crtc->index, false); |
214 | 213 | ||
215 | NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); | 214 | NVWriteVgaCrtc(dev, nv_crtc->index, NV_CIO_CRE_RPC1_INDEX, crtc1A); |
216 | |||
217 | /* Update connector polling modes */ | ||
218 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
219 | nouveau_connector_set_polling(connector); | ||
220 | } | 215 | } |
221 | 216 | ||
222 | static bool | 217 | static bool |
@@ -831,7 +826,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
831 | /* Update the framebuffer location. */ | 826 | /* Update the framebuffer location. */ |
832 | regp->fb_start = nv_crtc->fb.offset & ~3; | 827 | regp->fb_start = nv_crtc->fb.offset & ~3; |
833 | regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); | 828 | regp->fb_start += (y * drm_fb->pitch) + (x * drm_fb->bits_per_pixel / 8); |
834 | NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_START, regp->fb_start); | 829 | nv_set_crtc_base(dev, nv_crtc->index, regp->fb_start); |
835 | 830 | ||
836 | /* Update the arbitration parameters. */ | 831 | /* Update the arbitration parameters. */ |
837 | nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, | 832 | nouveau_calc_arb(dev, crtc->mode.clock, drm_fb->bits_per_pixel, |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index c936403b26e2..ef23550407b5 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -185,14 +185,15 @@ static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, | |||
185 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 185 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
186 | struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); | 186 | struct nouveau_connector *nv_connector = nouveau_encoder_connector_get(nv_encoder); |
187 | 187 | ||
188 | /* For internal panels and gpu scaling on DVI we need the native mode */ | 188 | if (!nv_connector->native_mode || |
189 | if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { | 189 | nv_connector->scaling_mode == DRM_MODE_SCALE_NONE || |
190 | if (!nv_connector->native_mode) | 190 | mode->hdisplay > nv_connector->native_mode->hdisplay || |
191 | return false; | 191 | mode->vdisplay > nv_connector->native_mode->vdisplay) { |
192 | nv_encoder->mode = *adjusted_mode; | ||
193 | |||
194 | } else { | ||
192 | nv_encoder->mode = *nv_connector->native_mode; | 195 | nv_encoder->mode = *nv_connector->native_mode; |
193 | adjusted_mode->clock = nv_connector->native_mode->clock; | 196 | adjusted_mode->clock = nv_connector->native_mode->clock; |
194 | } else { | ||
195 | nv_encoder->mode = *adjusted_mode; | ||
196 | } | 197 | } |
197 | 198 | ||
198 | return true; | 199 | return true; |
diff --git a/drivers/gpu/drm/nouveau/nv04_pm.c b/drivers/gpu/drm/nouveau/nv04_pm.c index 6a6eb697d38e..eb1c70dd82ed 100644 --- a/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/drivers/gpu/drm/nouveau/nv04_pm.c | |||
@@ -76,6 +76,15 @@ nv04_pm_clock_set(struct drm_device *dev, void *pre_state) | |||
76 | reg += 4; | 76 | reg += 4; |
77 | 77 | ||
78 | nouveau_hw_setpll(dev, reg, &state->calc); | 78 | nouveau_hw_setpll(dev, reg, &state->calc); |
79 | |||
80 | if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) { | ||
81 | if (dev_priv->card_type == NV_20) | ||
82 | nv_mask(dev, 0x1002c4, 0, 1 << 20); | ||
83 | |||
84 | /* Reset the DLLs */ | ||
85 | nv_mask(dev, 0x1002c0, 0, 1 << 8); | ||
86 | } | ||
87 | |||
79 | kfree(state); | 88 | kfree(state); |
80 | } | 89 | } |
81 | 90 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_calc.c b/drivers/gpu/drm/nouveau/nv50_calc.c index 2cdc2bfe7179..de81151648f8 100644 --- a/drivers/gpu/drm/nouveau/nv50_calc.c +++ b/drivers/gpu/drm/nouveau/nv50_calc.c | |||
@@ -51,24 +51,28 @@ nv50_calc_pll2(struct drm_device *dev, struct pll_lims *pll, int clk, | |||
51 | int *N, int *fN, int *M, int *P) | 51 | int *N, int *fN, int *M, int *P) |
52 | { | 52 | { |
53 | fixed20_12 fb_div, a, b; | 53 | fixed20_12 fb_div, a, b; |
54 | u32 refclk = pll->refclk / 10; | ||
55 | u32 max_vco_freq = pll->vco1.maxfreq / 10; | ||
56 | u32 max_vco_inputfreq = pll->vco1.max_inputfreq / 10; | ||
57 | clk /= 10; | ||
54 | 58 | ||
55 | *P = pll->vco1.maxfreq / clk; | 59 | *P = max_vco_freq / clk; |
56 | if (*P > pll->max_p) | 60 | if (*P > pll->max_p) |
57 | *P = pll->max_p; | 61 | *P = pll->max_p; |
58 | if (*P < pll->min_p) | 62 | if (*P < pll->min_p) |
59 | *P = pll->min_p; | 63 | *P = pll->min_p; |
60 | 64 | ||
61 | /* *M = ceil(refclk / pll->vco.max_inputfreq); */ | 65 | /* *M = floor((refclk + max_vco_inputfreq) / max_vco_inputfreq); */ |
62 | a.full = dfixed_const(pll->refclk); | 66 | a.full = dfixed_const(refclk + max_vco_inputfreq); |
63 | b.full = dfixed_const(pll->vco1.max_inputfreq); | 67 | b.full = dfixed_const(max_vco_inputfreq); |
64 | a.full = dfixed_div(a, b); | 68 | a.full = dfixed_div(a, b); |
65 | a.full = dfixed_ceil(a); | 69 | a.full = dfixed_floor(a); |
66 | *M = dfixed_trunc(a); | 70 | *M = dfixed_trunc(a); |
67 | 71 | ||
68 | /* fb_div = (vco * *M) / refclk; */ | 72 | /* fb_div = (vco * *M) / refclk; */ |
69 | fb_div.full = dfixed_const(clk * *P); | 73 | fb_div.full = dfixed_const(clk * *P); |
70 | fb_div.full = dfixed_mul(fb_div, a); | 74 | fb_div.full = dfixed_mul(fb_div, a); |
71 | a.full = dfixed_const(pll->refclk); | 75 | a.full = dfixed_const(refclk); |
72 | fb_div.full = dfixed_div(fb_div, a); | 76 | fb_div.full = dfixed_div(fb_div, a); |
73 | 77 | ||
74 | /* *N = floor(fb_div); */ | 78 | /* *N = floor(fb_div); */ |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 16380d52cd88..56476d0c6de8 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -546,7 +546,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
546 | } | 546 | } |
547 | 547 | ||
548 | nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; | 548 | nv_crtc->fb.offset = fb->nvbo->bo.offset - dev_priv->vm_vram_base; |
549 | nv_crtc->fb.tile_flags = fb->nvbo->tile_flags; | 549 | nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); |
550 | nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; | 550 | nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; |
551 | if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { | 551 | if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { |
552 | ret = RING_SPACE(evo, 2); | 552 | ret = RING_SPACE(evo, 2); |
@@ -578,7 +578,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | |||
578 | fb->nvbo->tile_mode); | 578 | fb->nvbo->tile_mode); |
579 | } | 579 | } |
580 | if (dev_priv->chipset == 0x50) | 580 | if (dev_priv->chipset == 0x50) |
581 | OUT_RING(evo, (fb->nvbo->tile_flags << 8) | format); | 581 | OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format); |
582 | else | 582 | else |
583 | OUT_RING(evo, format); | 583 | OUT_RING(evo, format); |
584 | 584 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 55c9663ef2bf..f624c611ddea 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -1032,11 +1032,18 @@ nv50_display_irq_hotplug_bh(struct work_struct *work) | |||
1032 | struct drm_connector *connector; | 1032 | struct drm_connector *connector; |
1033 | const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; | 1033 | const uint32_t gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; |
1034 | uint32_t unplug_mask, plug_mask, change_mask; | 1034 | uint32_t unplug_mask, plug_mask, change_mask; |
1035 | uint32_t hpd0, hpd1 = 0; | 1035 | uint32_t hpd0, hpd1; |
1036 | 1036 | ||
1037 | hpd0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); | 1037 | spin_lock_irq(&dev_priv->hpd_state.lock); |
1038 | hpd0 = dev_priv->hpd_state.hpd0_bits; | ||
1039 | dev_priv->hpd_state.hpd0_bits = 0; | ||
1040 | hpd1 = dev_priv->hpd_state.hpd1_bits; | ||
1041 | dev_priv->hpd_state.hpd1_bits = 0; | ||
1042 | spin_unlock_irq(&dev_priv->hpd_state.lock); | ||
1043 | |||
1044 | hpd0 &= nv_rd32(dev, 0xe050); | ||
1038 | if (dev_priv->chipset >= 0x90) | 1045 | if (dev_priv->chipset >= 0x90) |
1039 | hpd1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); | 1046 | hpd1 &= nv_rd32(dev, 0xe070); |
1040 | 1047 | ||
1041 | plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); | 1048 | plug_mask = (hpd0 & 0x0000ffff) | (hpd1 << 16); |
1042 | unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); | 1049 | unplug_mask = (hpd0 >> 16) | (hpd1 & 0xffff0000); |
@@ -1078,10 +1085,6 @@ nv50_display_irq_hotplug_bh(struct work_struct *work) | |||
1078 | helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); | 1085 | helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF); |
1079 | } | 1086 | } |
1080 | 1087 | ||
1081 | nv_wr32(dev, 0xe054, nv_rd32(dev, 0xe054)); | ||
1082 | if (dev_priv->chipset >= 0x90) | ||
1083 | nv_wr32(dev, 0xe074, nv_rd32(dev, 0xe074)); | ||
1084 | |||
1085 | drm_helper_hpd_irq_event(dev); | 1088 | drm_helper_hpd_irq_event(dev); |
1086 | } | 1089 | } |
1087 | 1090 | ||
@@ -1092,8 +1095,22 @@ nv50_display_irq_handler(struct drm_device *dev) | |||
1092 | uint32_t delayed = 0; | 1095 | uint32_t delayed = 0; |
1093 | 1096 | ||
1094 | if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { | 1097 | if (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_HOTPLUG) { |
1095 | if (!work_pending(&dev_priv->hpd_work)) | 1098 | uint32_t hpd0_bits, hpd1_bits = 0; |
1096 | queue_work(dev_priv->wq, &dev_priv->hpd_work); | 1099 | |
1100 | hpd0_bits = nv_rd32(dev, 0xe054); | ||
1101 | nv_wr32(dev, 0xe054, hpd0_bits); | ||
1102 | |||
1103 | if (dev_priv->chipset >= 0x90) { | ||
1104 | hpd1_bits = nv_rd32(dev, 0xe074); | ||
1105 | nv_wr32(dev, 0xe074, hpd1_bits); | ||
1106 | } | ||
1107 | |||
1108 | spin_lock(&dev_priv->hpd_state.lock); | ||
1109 | dev_priv->hpd_state.hpd0_bits |= hpd0_bits; | ||
1110 | dev_priv->hpd_state.hpd1_bits |= hpd1_bits; | ||
1111 | spin_unlock(&dev_priv->hpd_state.lock); | ||
1112 | |||
1113 | queue_work(dev_priv->wq, &dev_priv->hpd_work); | ||
1097 | } | 1114 | } |
1098 | 1115 | ||
1099 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { | 1116 | while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { |
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index a46a961102f3..1da65bd60c10 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
@@ -464,3 +464,8 @@ nv50_fifo_unload_context(struct drm_device *dev) | |||
464 | return 0; | 464 | return 0; |
465 | } | 465 | } |
466 | 466 | ||
467 | void | ||
468 | nv50_fifo_tlb_flush(struct drm_device *dev) | ||
469 | { | ||
470 | nv50_vm_flush(dev, 5); | ||
471 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index cbf5ae2f67d4..8b669d0af610 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -402,3 +402,55 @@ struct nouveau_pgraph_object_class nv50_graph_grclass[] = { | |||
402 | { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ | 402 | { 0x8597, false, NULL }, /* tesla (nva3, nva5, nva8) */ |
403 | {} | 403 | {} |
404 | }; | 404 | }; |
405 | |||
406 | void | ||
407 | nv50_graph_tlb_flush(struct drm_device *dev) | ||
408 | { | ||
409 | nv50_vm_flush(dev, 0); | ||
410 | } | ||
411 | |||
412 | void | ||
413 | nv86_graph_tlb_flush(struct drm_device *dev) | ||
414 | { | ||
415 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
416 | struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; | ||
417 | bool idle, timeout = false; | ||
418 | unsigned long flags; | ||
419 | u64 start; | ||
420 | u32 tmp; | ||
421 | |||
422 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | ||
423 | nv_mask(dev, 0x400500, 0x00000001, 0x00000000); | ||
424 | |||
425 | start = ptimer->read(dev); | ||
426 | do { | ||
427 | idle = true; | ||
428 | |||
429 | for (tmp = nv_rd32(dev, 0x400380); tmp && idle; tmp >>= 3) { | ||
430 | if ((tmp & 7) == 1) | ||
431 | idle = false; | ||
432 | } | ||
433 | |||
434 | for (tmp = nv_rd32(dev, 0x400384); tmp && idle; tmp >>= 3) { | ||
435 | if ((tmp & 7) == 1) | ||
436 | idle = false; | ||
437 | } | ||
438 | |||
439 | for (tmp = nv_rd32(dev, 0x400388); tmp && idle; tmp >>= 3) { | ||
440 | if ((tmp & 7) == 1) | ||
441 | idle = false; | ||
442 | } | ||
443 | } while (!idle && !(timeout = ptimer->read(dev) - start > 2000000000)); | ||
444 | |||
445 | if (timeout) { | ||
446 | NV_ERROR(dev, "PGRAPH TLB flush idle timeout fail: " | ||
447 | "0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
448 | nv_rd32(dev, 0x400700), nv_rd32(dev, 0x400380), | ||
449 | nv_rd32(dev, 0x400384), nv_rd32(dev, 0x400388)); | ||
450 | } | ||
451 | |||
452 | nv50_vm_flush(dev, 0); | ||
453 | |||
454 | nv_mask(dev, 0x400500, 0x00000001, 0x00000001); | ||
455 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | ||
456 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_instmem.c b/drivers/gpu/drm/nouveau/nv50_instmem.c index a53fc974332b..b773229b7647 100644 --- a/drivers/gpu/drm/nouveau/nv50_instmem.c +++ b/drivers/gpu/drm/nouveau/nv50_instmem.c | |||
@@ -402,7 +402,6 @@ nv50_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | |||
402 | } | 402 | } |
403 | dev_priv->engine.instmem.flush(dev); | 403 | dev_priv->engine.instmem.flush(dev); |
404 | 404 | ||
405 | nv50_vm_flush(dev, 4); | ||
406 | nv50_vm_flush(dev, 6); | 405 | nv50_vm_flush(dev, 6); |
407 | 406 | ||
408 | gpuobj->im_bound = 1; | 407 | gpuobj->im_bound = 1; |