diff options
Diffstat (limited to 'shared-core')
-rw-r--r-- | shared-core/drm.h | 86 | ||||
-rw-r--r-- | shared-core/nouveau_dma.h | 5 | ||||
-rw-r--r-- | shared-core/nouveau_drm.h | 4 | ||||
-rw-r--r-- | shared-core/nouveau_drv.h | 28 | ||||
-rw-r--r-- | shared-core/nouveau_irq.c | 80 | ||||
-rw-r--r-- | shared-core/nouveau_mem.c | 95 | ||||
-rw-r--r-- | shared-core/nouveau_notifier.c | 2 | ||||
-rw-r--r-- | shared-core/nouveau_object.c | 2 | ||||
-rw-r--r-- | shared-core/nouveau_reg.h | 238 | ||||
-rw-r--r-- | shared-core/nouveau_state.c | 57 | ||||
-rw-r--r-- | shared-core/nv50_fifo.c | 4 |
11 files changed, 546 insertions, 55 deletions
diff --git a/shared-core/drm.h b/shared-core/drm.h index 382e3fa1..017c012b 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1034,6 +1034,30 @@ struct drm_gem_open { #define DRM_MODE_TYPE_USERDEF (1<<5) #define DRM_MODE_TYPE_DRIVER (1<<6) +/* Video mode flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_FLAG_PHSYNC (1<<0) +#define DRM_MODE_FLAG_NHSYNC (1<<1) +#define DRM_MODE_FLAG_PVSYNC (1<<2) +#define DRM_MODE_FLAG_NVSYNC (1<<3) +#define DRM_MODE_FLAG_INTERLACE (1<<4) +#define DRM_MODE_FLAG_DBLSCAN (1<<5) +#define DRM_MODE_FLAG_CSYNC (1<<6) +#define DRM_MODE_FLAG_PCSYNC (1<<7) +#define DRM_MODE_FLAG_NCSYNC (1<<8) +#define DRM_MODE_FLAG_HSKEW (1<<9) /* hskew provided */ +#define DRM_MODE_FLAG_BCAST (1<<10) +#define DRM_MODE_FLAG_PIXMUX (1<<11) +#define DRM_MODE_FLAG_DBLCLK (1<<12) +#define DRM_MODE_FLAG_CLKDIV2 (1<<13) + +/* DPMS flags */ +/* bit compatible with the xorg definitions. */ +#define DRM_MODE_DPMS_ON 0 +#define DRM_MODE_DPMS_STANDBY 1 +#define DRM_MODE_DPMS_SUSPEND 2 +#define DRM_MODE_DPMS_OFF 3 + struct drm_mode_modeinfo { unsigned int clock; unsigned short hdisplay, hsync_start, hsync_end, htotal, hskew; @@ -1057,47 +1081,63 @@ struct drm_mode_card_res { int count_encoders; int min_width, max_width; int min_height, max_height; - uint32_t generation; }; struct drm_mode_crtc { uint64_t set_connectors_ptr; + int count_connectors; unsigned int crtc_id; /**< Id */ unsigned int fb_id; /**< Id of framebuffer */ int x, y; /**< Position on the frameuffer */ - uint32_t generation; - - int count_connectors; - unsigned int connectors; /**< Connectors that are connected */ - - int count_possibles; - unsigned int possibles; /**< Connectors that can be connected */ uint32_t gamma_size; int mode_valid; struct drm_mode_modeinfo mode; }; -struct drm_mode_get_encoder { - - uint32_t generation; - - uint32_t encoder_type; - uint32_t encoder_id; - - unsigned int crtc; /**< Id of crtc */ - uint32_t crtcs; - uint32_t clones; -}; - #define DRM_MODE_ENCODER_NONE 0 #define DRM_MODE_ENCODER_DAC 1 #define DRM_MODE_ENCODER_TMDS 2 #define DRM_MODE_ENCODER_LVDS 3 #define DRM_MODE_ENCODER_TVDAC 4 +struct drm_mode_get_encoder { + + unsigned int encoder_type; + unsigned int encoder_id; + + unsigned int crtc_id; /**< Id of crtc */ + + uint32_t possible_crtcs; + uint32_t possible_clones; +}; + +/* This is for connectors with multiple signal types. */ +/* Try to match DRM_MODE_CONNECTOR_X as closely as possible. */ +#define DRM_MODE_SUBCONNECTOR_Automatic 0 +#define DRM_MODE_SUBCONNECTOR_Unknown 0 +#define DRM_MODE_SUBCONNECTOR_DVID 3 +#define DRM_MODE_SUBCONNECTOR_DVIA 4 +#define DRM_MODE_SUBCONNECTOR_Composite 5 +#define DRM_MODE_SUBCONNECTOR_SVIDEO 6 +#define DRM_MODE_SUBCONNECTOR_Component 8 + +#define DRM_MODE_CONNECTOR_Unknown 0 +#define DRM_MODE_CONNECTOR_VGA 1 +#define DRM_MODE_CONNECTOR_DVII 2 +#define DRM_MODE_CONNECTOR_DVID 3 +#define DRM_MODE_CONNECTOR_DVIA 4 +#define DRM_MODE_CONNECTOR_Composite 5 +#define DRM_MODE_CONNECTOR_SVIDEO 6 +#define DRM_MODE_CONNECTOR_LVDS 7 +#define DRM_MODE_CONNECTOR_Component 8 +#define DRM_MODE_CONNECTOR_9PinDIN 9 +#define DRM_MODE_CONNECTOR_DisplayPort 10 +#define DRM_MODE_CONNECTOR_HDMIA 11 +#define DRM_MODE_CONNECTOR_HDMIB 12 + struct drm_mode_get_connector { uint64_t encoders_ptr; @@ -1109,13 +1149,11 @@ struct drm_mode_get_connector { int count_props; int count_encoders; - unsigned int encoder; /**< Current Encoder */ - unsigned int connector; /**< Id */ + unsigned int encoder_id; /**< Current Encoder */ + unsigned int connector_id; /**< Id */ unsigned int connector_type; unsigned int connector_type_id; - uint32_t generation; - unsigned int connection; unsigned int mm_width, mm_height; /**< HxW in millimeters */ unsigned int subpixel; diff --git a/shared-core/nouveau_dma.h b/shared-core/nouveau_dma.h index ce3c58cb..07652c2b 100644 --- a/shared-core/nouveau_dma.h +++ b/shared-core/nouveau_dma.h @@ -93,4 +93,9 @@ typedef enum { } \ } while(0) +/* This should allow easy switching to a real fifo in the future. */ +#define OUT_MODE(mthd, val) do { \ + nv50_display_command(dev_priv, mthd, val); \ +} while(0) + #endif diff --git a/shared-core/nouveau_drm.h b/shared-core/nouveau_drm.h index cf762052..bbb51bc4 100644 --- a/shared-core/nouveau_drm.h +++ b/shared-core/nouveau_drm.h @@ -88,9 +88,11 @@ struct drm_nouveau_gpuobj_free { #define NOUVEAU_MEM_INSTANCE 0x00000200 /* internal */ #define NOUVEAU_MEM_NOTIFIER 0x00000400 /* internal */ #define NOUVEAU_MEM_NOVM 0x00000800 /* internal */ +#define NOUVEAU_MEM_USER 0x00001000 /* internal */ #define NOUVEAU_MEM_INTERNAL (NOUVEAU_MEM_INSTANCE | \ NOUVEAU_MEM_NOTIFIER | \ - NOUVEAU_MEM_NOVM) + NOUVEAU_MEM_NOVM | \ + NOUVEAU_MEM_USER) struct drm_nouveau_mem_alloc { int flags; diff --git a/shared-core/nouveau_drv.h b/shared-core/nouveau_drv.h index a51e552c..33e2a5b6 100644 --- a/shared-core/nouveau_drv.h +++ b/shared-core/nouveau_drv.h @@ -41,6 +41,9 @@ #include "nouveau_drm.h" #include "nouveau_reg.h" +#include "nouveau_bios.h" + +#define MAX_NUM_DCB_ENTRIES 16 struct mem_block { struct mem_block *next; @@ -310,6 +313,28 @@ struct drm_nouveau_private { struct nouveau_config config; struct list_head gpuobj_list; + + void *display_priv; /* internal modesetting */ + void *kms_priv; /* related to public interface */ + + /* Hook these up to the "public interface" to accomodate a certain allocation style. */ + /* This is to avoid polluting the internal interface. */ + void *(*alloc_crtc) (struct drm_device *dev); + void *(*alloc_output) (struct drm_device *dev); + void *(*alloc_connector) (struct drm_device *dev); + + void (*free_crtc) (void *crtc); + void (*free_output) (void *output); + void (*free_connector) (void *connector); + + struct bios bios; + + struct { + int entries; + struct dcb_entry entry[MAX_NUM_DCB_ENTRIES]; + unsigned char i2c_read[MAX_NUM_DCB_ENTRIES]; + unsigned char i2c_write[MAX_NUM_DCB_ENTRIES]; + } dcb_table; }; #define NOUVEAU_CHECK_INITIALISED_WITH_RETURN do { \ @@ -350,9 +375,10 @@ extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start, uint64_t size); extern struct mem_block *nouveau_mem_alloc_block(struct mem_block *, uint64_t size, int align2, - struct drm_file *); + struct drm_file *, int tail); extern void nouveau_mem_takedown(struct mem_block **heap); extern void nouveau_mem_free_block(struct mem_block *); +extern struct mem_block* find_block_by_handle(struct mem_block *heap, drm_handle_t handle); extern uint64_t nouveau_mem_fb_amount(struct drm_device *); extern void nouveau_mem_release(struct drm_file *, struct mem_block *heap); extern int nouveau_ioctl_mem_alloc(struct drm_device *, void *data, diff --git a/shared-core/nouveau_irq.c b/shared-core/nouveau_irq.c index 2a3d8a0b..4c46da8d 100644 --- a/shared-core/nouveau_irq.c +++ b/shared-core/nouveau_irq.c @@ -37,6 +37,11 @@ #include "nouveau_reg.h" #include "nouveau_swmthd.h" +/* needed for interrupt based vpll changes */ +#include "nv50_display.h" +#include "nv50_crtc.h" +#include "nv50_output.h" + void nouveau_irq_preinstall(struct drm_device *dev) { @@ -503,11 +508,82 @@ static void nouveau_nv50_display_irq_handler(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t val = NV_READ(NV50_DISPLAY_SUPERVISOR); + uint32_t val = NV_READ(NV50_PDISPLAY_SUPERVISOR); DRM_INFO("NV50_DISPLAY_INTR - 0x%08X\n", val); - NV_WRITE(NV50_DISPLAY_SUPERVISOR, val); + /* vblank interrupts */ + if (val & NV50_PDISPLAY_SUPERVISOR_CRTCn) { + NV_WRITE(NV50_PDISPLAY_SUPERVISOR, val & NV50_PDISPLAY_SUPERVISOR_CRTCn); + val &= ~NV50_PDISPLAY_SUPERVISOR_CRTCn; + } + + /* clock setting amongst other things. */ + if (val & NV50_PDISPLAY_SUPERVISOR_CLK_MASK) { + uint32_t state = (val & NV50_PDISPLAY_SUPERVISOR_CLK_MASK) >> NV50_PDISPLAY_SUPERVISOR_CLK_MASK__SHIFT; + + NV50_DEBUG("state %d\n", state); + + /* Set pll */ + if (state == 2) { + struct nv50_display *display = nv50_get_display(dev); + struct nv50_output *output = NULL; + struct nv50_crtc *crtc = NULL; + int crtc_index; + + uint32_t unk30 = NV_READ(NV50_PDISPLAY_UNK30_CTRL); + + for (crtc_index = 0; crtc_index < 2; crtc_index++) { + bool clock_change = false; + bool clock_ack = false; + + if (crtc_index == 0 && (unk30 & NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0)) + clock_change = true; + + if (crtc_index == 1 && (unk30 & NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1)) + clock_change = true; + + if (clock_change) + clock_ack = true; + + if (display->last_crtc == crtc_index) + clock_ack = true; + + list_for_each_entry(crtc, &display->crtcs, item) { + if (crtc->index == crtc_index) + break; + } + + if (clock_change) + crtc->set_clock(crtc); + + NV50_DEBUG("index %d clock_change %d clock_ack %d\n", crtc_index, clock_change, clock_ack); + + if (!clock_ack) + continue; + + crtc->set_clock_mode(crtc); + + list_for_each_entry(output, &display->outputs, item) { + if (!output->crtc) + continue; + + if (output->crtc == crtc) + output->set_clock_mode(output); + } + } + } + + NV_WRITE(NV50_PDISPLAY_UNK30_CTRL, NV50_PDISPLAY_UNK30_CTRL_PENDING); + NV_WRITE(NV50_PDISPLAY_SUPERVISOR, val & NV50_PDISPLAY_SUPERVISOR_CLK_MASK); + + val &= ~NV50_PDISPLAY_SUPERVISOR_CLK_MASK; + } + + if (val) + DRM_ERROR("unsupported NV50_DISPLAY_INTR - 0x%08X\n", val); + + NV_WRITE(NV50_PDISPLAY_SUPERVISOR, val); } static void diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 2cf8807d..861d699f 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -34,9 +34,12 @@ #include "drm.h" #include "drm_sarea.h" #include "nouveau_drv.h" +#include "nv50_kms_wrapper.h" -static struct mem_block *split_block(struct mem_block *p, uint64_t start, uint64_t size, - struct drm_file *file_priv) + +static struct mem_block * +split_block(struct mem_block *p, uint64_t start, uint64_t size, + struct drm_file *file_priv) { /* Maybe cut off the start of an existing block */ if (start > p->start) { @@ -77,10 +80,9 @@ out: return p; } -struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap, - uint64_t size, - int align2, - struct drm_file *file_priv) +struct mem_block * +nouveau_mem_alloc_block(struct mem_block *heap, uint64_t size, + int align2, struct drm_file *file_priv, int tail) { struct mem_block *p; uint64_t mask = (1 << align2) - 1; @@ -88,10 +90,22 @@ struct mem_block *nouveau_mem_alloc_block(struct mem_block *heap, if (!heap) return NULL; - list_for_each(p, heap) { - uint64_t start = (p->start + mask) & ~mask; - if (p->file_priv == 0 && start + size <= p->start + p->size) - return split_block(p, start, size, file_priv); + if (tail) { + list_for_each_prev(p, heap) { + uint64_t start = ((p->start + p->size) - size) & ~mask; + + if (p->file_priv == 0 && start >= p->start && + start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); + } + } else { + list_for_each(p, heap) { + uint64_t start = (p->start + mask) & ~mask; + + if (p->file_priv == 0 && + start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); + } } return NULL; @@ -108,6 +122,17 @@ static struct mem_block *find_block(struct mem_block *heap, uint64_t start) return NULL; } +struct mem_block *find_block_by_handle(struct mem_block *heap, drm_handle_t handle) +{ + struct mem_block *p; + + list_for_each(p, heap) + if (p->map_handle == handle) + return p; + + return NULL; +} + void nouveau_mem_free_block(struct mem_block *p) { p->file_priv = NULL; @@ -563,13 +588,13 @@ int nouveau_mem_init(struct drm_device *dev) return 0; } -struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, - uint64_t size, int flags, - struct drm_file *file_priv) +struct mem_block * +nouveau_mem_alloc(struct drm_device *dev, int alignment, uint64_t size, + int flags, struct drm_file *file_priv) { - struct mem_block *block; - int type; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct mem_block *block; + int type, tail = !(flags & NOUVEAU_MEM_USER); /* * Make things easier on ourselves: all allocations are page-aligned. @@ -600,14 +625,14 @@ struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, #define NOUVEAU_MEM_ALLOC_AGP {\ type=NOUVEAU_MEM_AGP;\ block = nouveau_mem_alloc_block(dev_priv->agp_heap, size,\ - alignment, file_priv); \ + alignment, file_priv, tail); \ if (block) goto alloc_ok;\ } #define NOUVEAU_MEM_ALLOC_PCI {\ type = NOUVEAU_MEM_PCI;\ block = nouveau_mem_alloc_block(dev_priv->pci_heap, size, \ - alignment, file_priv); \ + alignment, file_priv, tail); \ if ( block ) goto alloc_ok;\ } @@ -616,11 +641,11 @@ struct mem_block* nouveau_mem_alloc(struct drm_device *dev, int alignment, if (!(flags&NOUVEAU_MEM_MAPPED)) {\ block = nouveau_mem_alloc_block(dev_priv->fb_nomap_heap,\ size, alignment, \ - file_priv); \ + file_priv, tail); \ if (block) goto alloc_ok;\ }\ block = nouveau_mem_alloc_block(dev_priv->fb_heap, size,\ - alignment, file_priv);\ + alignment, file_priv, tail);\ if (block) goto alloc_ok;\ } @@ -707,6 +732,30 @@ void nouveau_mem_free(struct drm_device* dev, struct mem_block* block) DRM_DEBUG("freeing 0x%llx type=0x%08x\n", block->start, block->flags); + /* Check if the deallocations cause problems for our modesetting system. */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + if (dev_priv->card_type >= NV_50) { + struct nv50_crtc *crtc = NULL; + struct nv50_display *display = nv50_get_display(dev); + + list_for_each_entry(crtc, &display->crtcs, item) { + if (crtc->fb->block == block) { + crtc->fb->block = NULL; + + if (!crtc->blanked) + crtc->blank(crtc, true); + } + + if (crtc->cursor->block == block) { + crtc->cursor->block = NULL; + + if (crtc->cursor->visible) + crtc->cursor->hide(crtc); + } + } + } + } + if (block->flags&NOUVEAU_MEM_MAPPED) drm_rmmap(dev, block->map); @@ -738,7 +787,9 @@ out_free: * Ioctls */ -int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +int +nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct drm_nouveau_mem_alloc *alloc = data; struct mem_block *block; @@ -748,8 +799,8 @@ int nouveau_ioctl_mem_alloc(struct drm_device *dev, void *data, struct drm_file if (alloc->flags & NOUVEAU_MEM_INTERNAL) return -EINVAL; - block=nouveau_mem_alloc(dev, alloc->alignment, alloc->size, - alloc->flags, file_priv); + block = nouveau_mem_alloc(dev, alloc->alignment, alloc->size, + alloc->flags | NOUVEAU_MEM_USER, file_priv); if (!block) return -ENOMEM; alloc->map_handle=block->map_handle; diff --git a/shared-core/nouveau_notifier.c b/shared-core/nouveau_notifier.c index 82c8ab7d..edece4da 100644 --- a/shared-core/nouveau_notifier.c +++ b/shared-core/nouveau_notifier.c @@ -94,7 +94,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, } mem = nouveau_mem_alloc_block(chan->notifier_heap, count*32, 0, - (struct drm_file *)-2); + (struct drm_file *)-2, 0); if (!mem) { DRM_ERROR("Channel %d notifier block full\n", chan->id); return -ENOMEM; diff --git a/shared-core/nouveau_object.c b/shared-core/nouveau_object.c index 09f9027a..5664bfc8 100644 --- a/shared-core/nouveau_object.c +++ b/shared-core/nouveau_object.c @@ -248,7 +248,7 @@ nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_channel *chan, /* Allocate a chunk of the PRAMIN aperture */ gpuobj->im_pramin = nouveau_mem_alloc_block(pramin, size, drm_order(align), - (struct drm_file *)-2); + (struct drm_file *)-2, 0); if (!gpuobj->im_pramin) { nouveau_gpuobj_del(dev, &gpuobj); return -ENOMEM; diff --git a/shared-core/nouveau_reg.h b/shared-core/nouveau_reg.h index 1ae0177c..6ed23e26 100644 --- a/shared-core/nouveau_reg.h +++ b/shared-core/nouveau_reg.h @@ -116,6 +116,9 @@ #define NV04_PBUS_PCI_NV_1 0x00001804 #define NV04_PBUS_PCI_NV_19 0x0000184C +#define NV04_PBUS_PCI_NV_20 0x00001850 +# define NV04_PBUS_PCI_NV_20_ROM_SHADOW_DISABLED (0 << 0) +# define NV04_PBUS_PCI_NV_20_ROM_SHADOW_ENABLED (1 << 0) #define NV04_PTIMER_INTR_0 0x00009100 #define NV04_PTIMER_INTR_EN_0 0x00009140 @@ -542,6 +545,8 @@ /* This name is a partial guess. */ #define NV50_DISPLAY_SUPERVISOR 0x00610024 +#define NV04_PRAMIN 0x00700000 + /* Fifo commands. These are not regs, neither masks */ #define NV03_FIFO_CMD_JUMP 0x20000000 #define NV03_FIFO_CMD_JUMP_OFFSET_MASK 0x1ffffffc @@ -591,3 +596,236 @@ #define NV40_RAMFC_UNK_48 0x48 #define NV40_RAMFC_UNK_4C 0x4C #define NV40_RAMFC_UNK_50 0x50 + +/* This is a partial import from rules-ng, a few things may be duplicated. + * Eventually we should completely import everything from rules-ng. + * For the moment check rules-ng for docs. + */ + +#define NV50_PMC 0x00000000 +#define NV50_PMC__LEN 0x1 +#define NV50_PMC__ESIZE 0x2000 +# define NV50_PMC_BOOT_0 0x00000000 +# define NV50_PMC_BOOT_0_REVISION 0x000000ff +# define NV50_PMC_BOOT_0_REVISION__SHIFT 0 +# define NV50_PMC_BOOT_0_ARCH 0x0ff00000 +# define NV50_PMC_BOOT_0_ARCH__SHIFT 20 +# define NV50_PMC_INTR_0 0x00000100 +# define NV50_PMC_INTR_0_PFIFO (1<<8) +# define NV50_PMC_INTR_0_PGRAPH (1<<12) +# define NV50_PMC_INTR_0_PTIMER (1<<20) +# define NV50_PMC_INTR_0_HOTPLUG (1<<21) +# define NV50_PMC_INTR_0_DISPLAY (1<<26) +# define NV50_PMC_INTR_EN_0 0x00000140 +# define NV50_PMC_INTR_EN_0_MASTER (1<<0) +# define NV50_PMC_INTR_EN_0_MASTER_DISABLED (0<<0) +# define NV50_PMC_INTR_EN_0_MASTER_ENABLED (1<<0) +# define NV50_PMC_ENABLE 0x00000200 +# define NV50_PMC_ENABLE_PFIFO (1<<8) +# define NV50_PMC_ENABLE_PGRAPH (1<<12) + +#define NV50_PCONNECTOR 0x0000e000 +#define NV50_PCONNECTOR__LEN 0x1 +#define NV50_PCONNECTOR__ESIZE 0x1000 +# define NV50_PCONNECTOR_HOTPLUG_INTR 0x0000e050 +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C0 (1<<0) +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C1 (1<<1) +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C2 (1<<2) +# define NV50_PCONNECTOR_HOTPLUG_INTR_PLUG_I2C3 (1<<3) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C0 (1<<16) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C1 (1<<17) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C2 (1<<18) +# define NV50_PCONNECTOR_HOTPLUG_INTR_UNPLUG_I2C3 (1<<19) +# define NV50_PCONNECTOR_HOTPLUG_CTRL 0x0000e054 +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C0 (1<<0) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C1 (1<<1) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C2 (1<<2) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_PLUG_I2C3 (1<<3) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C0 (1<<16) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C1 (1<<17) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C2 (1<<18) +# define NV50_PCONNECTOR_HOTPLUG_CTRL_UNPLUG_I2C3 (1<<19) +# define NV50_PCONNECTOR_HOTPLUG_STATE 0x0000e104 +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C0 (1<<2) +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C1 (1<<6) +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C2 (1<<10) +# define NV50_PCONNECTOR_HOTPLUG_STATE_PIN_CONNECTED_I2C3 (1<<14) +# define NV50_PCONNECTOR_I2C_PORT_0 0x0000e138 +# define NV50_PCONNECTOR_I2C_PORT_1 0x0000e150 +# define NV50_PCONNECTOR_I2C_PORT_2 0x0000e168 +# define NV50_PCONNECTOR_I2C_PORT_3 0x0000e180 +# define NV50_PCONNECTOR_I2C_PORT_4 0x0000e240 +# define NV50_PCONNECTOR_I2C_PORT_5 0x0000e258 + +#define NV50_PBUS 0x00088000 +#define NV50_PBUS__LEN 0x1 +#define NV50_PBUS__ESIZE 0x1000 +# define NV50_PBUS_PCI_ID 0x00088000 +# define NV50_PBUS_PCI_ID_VENDOR_ID 0x0000ffff +# define NV50_PBUS_PCI_ID_VENDOR_ID__SHIFT 0 +# define NV50_PBUS_PCI_ID_DEVICE_ID 0xffff0000 +# define NV50_PBUS_PCI_ID_DEVICE_ID__SHIFT 16 + +#define NV50_PFB 0x00100000 +#define NV50_PFB__LEN 0x1 +#define NV50_PFB__ESIZE 0x1000 + +#define NV50_PEXTDEV 0x00101000 +#define NV50_PEXTDEV__LEN 0x1 +#define NV50_PEXTDEV__ESIZE 0x1000 + +#define NV50_PROM 0x00300000 +#define NV50_PROM__LEN 0x1 +#define NV50_PROM__ESIZE 0x10000 + +#define NV50_PGRAPH 0x00400000 +#define NV50_PGRAPH__LEN 0x1 +#define NV50_PGRAPH__ESIZE 0x10000 + +#define NV50_PDISPLAY 0x00610000 +#define NV50_PDISPLAY__LEN 0x1 +#define NV50_PDISPLAY__ESIZE 0x10000 +# define NV50_PDISPLAY_SUPERVISOR 0x00610024 +# define NV50_PDISPLAY_SUPERVISOR_CRTCn 0x0000000c +# define NV50_PDISPLAY_SUPERVISOR_CRTCn__SHIFT 2 +# define NV50_PDISPLAY_SUPERVISOR_CRTC0 (1<<2) +# define NV50_PDISPLAY_SUPERVISOR_CRTC1 (1<<3) +# define NV50_PDISPLAY_SUPERVISOR_CLK_MASK 0x00000070 +# define NV50_PDISPLAY_SUPERVISOR_CLK_MASK__SHIFT 4 +# define NV50_PDISPLAY_SUPERVISOR_CLK_UPDATE (1<<5) +# define NV50_PDISPLAY_SUPERVISOR_INTR 0x0061002c +# define NV50_PDISPLAY_SUPERVISOR_INTR_VBLANK_CRTC0 (1<<2) +# define NV50_PDISPLAY_SUPERVISOR_INTR_VBLANK_CRTC1 (1<<3) +# define NV50_PDISPLAY_SUPERVISOR_INTR_UNK1 (1<<4) +# define NV50_PDISPLAY_SUPERVISOR_INTR_CLK_UPDATE (1<<5) +# define NV50_PDISPLAY_SUPERVISOR_INTR_UNK4 (1<<6) +# define NV50_PDISPLAY_UNK30_CTRL 0x00610030 +# define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK0 (1<<9) +# define NV50_PDISPLAY_UNK30_CTRL_UPDATE_VCLK1 (1<<10) +# define NV50_PDISPLAY_UNK30_CTRL_PENDING (1<<31) +# define NV50_PDISPLAY_UNK50_CTRL 0x00610050 +# define NV50_PDISPLAY_UNK50_CTRL_CRTC0_ACTIVE (1<<1) +# define NV50_PDISPLAY_UNK50_CTRL_CRTC0_ACTIVE_MASK 0x00000003 +# define NV50_PDISPLAY_UNK50_CTRL_CRTC0_ACTIVE_MASK__SHIFT 0 +# define NV50_PDISPLAY_UNK50_CTRL_CRTC1_ACTIVE (1<<9) +# define NV50_PDISPLAY_UNK50_CTRL_CRTC1_ACTIVE_MASK 0x00000300 +# define NV50_PDISPLAY_UNK50_CTRL_CRTC1_ACTIVE_MASK__SHIFT 8 +# define NV50_PDISPLAY_UNK200_CTRL 0x00610200 +# define NV50_PDISPLAY_CURSOR 0x00610270 +# define NV50_PDISPLAY_CURSOR__LEN 0x2 +# define NV50_PDISPLAY_CURSOR__ESIZE 0x10 +# define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i) (0x00610270+(i)*0x10) +# define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON (1<<0) +# define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_MASK 0x00030000 +# define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_MASK__SHIFT 16 +# define NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE (1<<16) + +# define NV50_PDISPLAY_CTRL_STATE 0x00610300 +# define NV50_PDISPLAY_CTRL_STATE_ENABLE (1<<0) +# define NV50_PDISPLAY_CTRL_STATE_PENDING (1<<31) +# define NV50_PDISPLAY_CTRL_VAL 0x00610304 +# define NV50_PDISPLAY_UNK_380 0x00610380 +# define NV50_PDISPLAY_RAM_AMOUNT 0x00610384 +# define NV50_PDISPLAY_UNK_388 0x00610388 +# define NV50_PDISPLAY_UNK_38C 0x0061038c +# define NV50_PDISPLAY_CRTC_VAL 0x00610a00 +# define NV50_PDISPLAY_CRTC_VAL__LEN 0x2 +# define NV50_PDISPLAY_CRTC_VAL_UNK_900(i,j) (0x00610a18+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_CLUT_MODE(i,j) (0x00610a24+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_INTERLACE(i,j) (0x00610a48+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_SCALE_CTRL(i,j) (0x00610a50+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_CURSOR_CTRL(i,j) (0x00610a58+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_UNK_904(i,j) (0x00610ab8+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_DEPTH(i,j) (0x00610ac8+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_CLOCK(i,j) (0x00610ad0+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_COLOR_CTRL(i,j) (0x00610ae0+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_SYNC_START_TO_BLANK_END(i,j) (0x00610ae8+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_MODE_UNK1(i,j) (0x00610af0+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_DISPLAY_TOTAL(i,j) (0x00610af8+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_SYNC_DURATION(i,j) (0x00610b00+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_MODE_UNK2(i,j) (0x00610b08+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_UNK_828(i,j) (0x00610b10+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_FB_SIZE(i,j) (0x00610b18+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_FB_PITCH(i,j) (0x00610b20+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_FB_PITCH_LINEAR_FB (1<<20) +# define NV50_PDISPLAY_CRTC_VAL_FB_POS(i,j) (0x00610b28+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_SCALE_CENTER_OFFSET(i,j) (0x00610b38+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_REAL_RES(i,j) (0x00610b40+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_SCALE_RES1(i,j) (0x00610b48+(i)*0x540+(j)*0x4) +# define NV50_PDISPLAY_CRTC_VAL_SCALE_RES2(i,j) (0x00610b50+(i)*0x540+(j)*0x4) + + +# define NV50_PDISPLAY_DAC_VAL_MODE_CTRL(i,j) (0x00610b58+(i)*0x8+(j)*0x4) + + +# define NV50_PDISPLAY_SOR_VAL_MODE_CTRL(i,j) (0x00610b70+(i)*0x8+(j)*0x4) + + +# define NV50_PDISPLAY_DAC_VAL_MODE_CTRL2(i,j) (0x00610bdc+(i)*0x8+(j)*0x4) + + +# define NV50_PDISPLAY_CRTC_CLK 0x00614000 +# define NV50_PDISPLAY_CRTC_CLK__LEN 0x2 +# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1(i) (0x00614100+(i)*0x800) +# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1_CONNECTED 0x00000600 +# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL1_CONNECTED__SHIFT 9 +# define NV50_PDISPLAY_CRTC_CLK_VPLL_A(i) (0x00614104+(i)*0x800) +# define NV50_PDISPLAY_CRTC_CLK_VPLL_B(i) (0x00614108+(i)*0x800) +# define NV50_PDISPLAY_CRTC_CLK_CLK_CTRL2(i) (0x00614200+(i)*0x800) + +# define NV50_PDISPLAY_DAC_CLK 0x00614000 +# define NV50_PDISPLAY_DAC_CLK__LEN 0x3 +# define NV50_PDISPLAY_DAC_CLK_CLK_CTRL2(i) (0x00614280+(i)*0x800) + +# define NV50_PDISPLAY_SOR_CLK 0x00614000 +# define NV50_PDISPLAY_SOR_CLK__LEN 0x3 +# define NV50_PDISPLAY_SOR_CLK_CLK_CTRL2(i) (0x00614300+(i)*0x800) + +# define NV50_PDISPLAY_DAC_REGS 0x0061a000 +# define NV50_PDISPLAY_DAC_REGS__LEN 0x3 +# define NV50_PDISPLAY_DAC_REGS__ESIZE 0x800 +# define NV50_PDISPLAY_DAC_REGS_DPMS_CTRL(i) (0x0061a004+(i)*0x800) +# define NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_HSYNC_OFF (1<<0) +# define NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_VSYNC_OFF (1<<2) +# define NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_BLANKED (1<<4) +# define NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_OFF (1<<6) +# define NV50_PDISPLAY_DAC_REGS_DPMS_CTRL_PENDING (1<<31) +# define NV50_PDISPLAY_DAC_REGS_LOAD_CTRL(i) (0x0061a00c+(i)*0x800) +# define NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_ACTIVE (1<<20) +# define NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_PRESENT 0x38000000 +# define NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_PRESENT__SHIFT 29 +# define NV50_PDISPLAY_DAC_REGS_LOAD_CTRL_DONE (1<<31) +# define NV50_PDISPLAY_DAC_REGS_CLK_CTRL1(i) (0x0061a010+(i)*0x800) +# define NV50_PDISPLAY_DAC_REGS_CLK_CTRL1_CONNECTED 0x00000600 +# define NV50_PDISPLAY_DAC_REGS_CLK_CTRL1_CONNECTED__SHIFT 9 + +# define NV50_PDISPLAY_SOR_REGS 0x0061c000 +# define NV50_PDISPLAY_SOR_REGS__LEN 0x2 +# define NV50_PDISPLAY_SOR_REGS__ESIZE 0x800 +# define NV50_PDISPLAY_SOR_REGS_DPMS_CTRL(i) (0x0061c004+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_ON (1<<0) +# define NV50_PDISPLAY_SOR_REGS_DPMS_CTRL_PENDING (1<<31) +# define NV50_PDISPLAY_SOR_REGS_CLK_CTRL1(i) (0x0061c008+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_CLK_CTRL1_CONNECTED 0x00000600 +# define NV50_PDISPLAY_SOR_REGS_CLK_CTRL1_CONNECTED__SHIFT 9 +# define NV50_PDISPLAY_SOR_REGS_UNK_00C(i) (0x0061c00c+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_UNK_010(i) (0x0061c010+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_UNK_014(i) (0x0061c014+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_UNK_018(i) (0x0061c018+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE(i) (0x0061c030+(i)*0x800) +# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_ACTIVE 0x00030000 +# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_ACTIVE__SHIFT 16 +# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_BLANKED (1<<19) +# define NV50_PDISPLAY_SOR_REGS_DPMS_STATE_WAIT (1<<28) + + +#define NV50_UNK640000 0x00640000 +#define NV50_UNK640000__LEN 0x6 +#define NV50_UNK640000__ESIZE 0x1000 +# define NV50_UNK640000_UNK_000(i) (0x00640000+(i)*0x1000) + +#define NV50_HW_CURSOR 0x00647000 +#define NV50_HW_CURSOR__LEN 0x2 +#define NV50_HW_CURSOR__ESIZE 0x1000 +# define NV50_HW_CURSOR_POS_CTRL(i) (0x00647080+(i)*0x1000) +# define NV50_HW_CURSOR_POS(i) (0x00647084+(i)*0x1000) diff --git a/shared-core/nouveau_state.c b/shared-core/nouveau_state.c index d9c6efe7..3baae6ad 100644 --- a/shared-core/nouveau_state.c +++ b/shared-core/nouveau_state.c @@ -27,6 +27,8 @@ #include "drm_sarea.h" #include "nouveau_drv.h" #include "nouveau_drm.h" +#include "nv50_kms_wrapper.h" +#include "nv50_fbcon.h" static int nouveau_init_card_mappings(struct drm_device *dev) { @@ -362,6 +364,14 @@ nouveau_card_init(struct drm_device *dev) if (ret) return ret; dev_priv->init_state = NOUVEAU_CARD_INIT_DONE; + + if (drm_core_check_feature(dev, DRIVER_MODESET)) + if (dev_priv->card_type >= NV_50) { + nv50_kms_init(dev); + //nv50_kms_connector_detect_all(dev); + nv50_fbcon_init(dev); + } + return 0; } @@ -410,8 +420,7 @@ void nouveau_preclose(struct drm_device *dev, struct drm_file *file_priv) nouveau_mem_release(file_priv,dev_priv->pci_heap); } -/* first module load, setup the mmio/fb mapping */ -int nouveau_firstopen(struct drm_device *dev) +int nouveau_setup_mappings(struct drm_device *dev) { #if defined(__powerpc__) struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -457,6 +466,16 @@ int nouveau_firstopen(struct drm_device *dev) return 0; } +/* first module load, setup the mmio/fb mapping */ +/* KMS: we need mmio at load time, not when the first drm client opens. */ +int nouveau_firstopen(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return 0; + + return nouveau_setup_mappings(dev); +} + #define NV40_CHIPSET_MASK 0x00000baf #define NV44_CHIPSET_MASK 0x00005450 @@ -540,6 +559,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) return -EINVAL; } + /* For those who think they want to be funny. */ + if (dev_priv->card_type < NV_50) + dev->driver->driver_features &= ~DRIVER_MODESET; + /* Special flags */ if (dev->pci_device == 0x01a0) { dev_priv->flags |= NV_NFORCE; @@ -549,10 +572,23 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev->dev_private = (void *)dev_priv; + /* init card now, otherwise bad things happen */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + int rval = 0; + + rval = nouveau_setup_mappings(dev); + if (rval != 0) + return rval; + + rval = nouveau_card_init(dev); + if (rval != 0) + return rval; + } + return 0; } -void nouveau_lastclose(struct drm_device *dev) +void nouveau_close(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -568,8 +604,23 @@ void nouveau_lastclose(struct drm_device *dev) } } +/* KMS: we need mmio at load time, not when the first drm client opens. */ +void nouveau_lastclose(struct drm_device *dev) +{ + if (drm_core_check_feature(dev, DRIVER_MODESET)) + return; + + nouveau_close(dev); +} + int nouveau_unload(struct drm_device *dev) { + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + nv50_kms_destroy(dev); + nv50_fbcon_destroy(dev); + nouveau_close(dev); + } + drm_free(dev->dev_private, sizeof(*dev->dev_private), DRM_MEM_DRIVER); dev->dev_private = NULL; return 0; diff --git a/shared-core/nv50_fifo.c b/shared-core/nv50_fifo.c index edf4edbf..d6810666 100644 --- a/shared-core/nv50_fifo.c +++ b/shared-core/nv50_fifo.c @@ -289,6 +289,7 @@ void nv50_fifo_destroy_context(struct nouveau_channel *chan) { struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; DRM_DEBUG("ch%d\n", chan->id); @@ -298,6 +299,9 @@ nv50_fifo_destroy_context(struct nouveau_channel *chan) if (chan->id == 0) nv50_fifo_channel_disable(dev, 127, 0); + if ((NV_READ(NV03_PFIFO_CACHE1_PUSH1) & 0xffff) == chan->id) + NV_WRITE(NV03_PFIFO_CACHE1_PUSH1, 127); + nouveau_gpuobj_ref_del(dev, &chan->ramfc); } |