mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	drm/nouveau: port remainder of drm code, and rip out compat layer
v2: Ben Skeggs <bskeggs@redhat.com> - fill in nouveau_pm.dev to prevent oops - fix ppc issues (build + OF shadow) Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
This commit is contained in:
		
							parent
							
								
									2094dd82ed
								
							
						
					
					
						commit
						77145f1cbd
					
				
					 70 changed files with 3095 additions and 4174 deletions
				
			
		|  | @ -145,47 +145,17 @@ nouveau-y += core/engine/software/nv50.o | ||||||
| nouveau-y += core/engine/software/nvc0.o | nouveau-y += core/engine/software/nvc0.o | ||||||
| nouveau-y += core/engine/vp/nv84.o | nouveau-y += core/engine/vp/nv84.o | ||||||
| 
 | 
 | ||||||
| # drm/compat - will go away
 |  | ||||||
| nouveau-y += nouveau_compat.o nouveau_revcompat.o |  | ||||||
| 
 |  | ||||||
| # drm/core
 | # drm/core
 | ||||||
| nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o | nouveau-y += nouveau_drm.o nouveau_chan.o nouveau_dma.o nouveau_fence.o | ||||||
| nouveau-y += nouveau_agp.o | nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o | ||||||
| nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o | nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o | ||||||
| 
 | nouveau-y += nouveau_prime.o nouveau_abi16.o | ||||||
| nouveau-y += nouveau_abi16.o |  | ||||||
| nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o | nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o | ||||||
| 
 | 
 | ||||||
| # drm/kms/common
 | # drm/kms
 | ||||||
| nouveau-y += nouveau_fbcon.o | nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o | ||||||
| 
 | nouveau-y += nouveau_connector.o nouveau_hdmi.o nouveau_dp.o | ||||||
| # drm/kms/nv04:nv50
 | nouveau-y += nv04_fbcon.o nv50_fbcon.o nvc0_fbcon.o | ||||||
| nouveau-y += nv04_fbcon.o |  | ||||||
| 
 |  | ||||||
| # drm/kms/nv50:nvd9
 |  | ||||||
| nouveau-y += nv50_fbcon.o nvc0_fbcon.o |  | ||||||
| 
 |  | ||||||
| # drm/kms/nvd9-
 |  | ||||||
| 
 |  | ||||||
| # other random bits
 |  | ||||||
| nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o |  | ||||||
| nouveau-$(CONFIG_ACPI) += nouveau_acpi.o |  | ||||||
| nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o |  | ||||||
| 
 |  | ||||||
| ##
 |  | ||||||
| ## unported bits below
 |  | ||||||
| ##
 |  | ||||||
| 
 |  | ||||||
| # drm/core
 |  | ||||||
| nouveau-y += nouveau_drv.o nouveau_state.o nouveau_irq.o |  | ||||||
| nouveau-y += nouveau_prime.o |  | ||||||
| 
 |  | ||||||
| # drm/kms/bios
 |  | ||||||
| nouveau-y += nouveau_bios.o |  | ||||||
| 
 |  | ||||||
| # drm/kms/common
 |  | ||||||
| nouveau-y += nouveau_display.o nouveau_connector.o |  | ||||||
| nouveau-y += nouveau_hdmi.o nouveau_dp.o |  | ||||||
| 
 | 
 | ||||||
| # drm/kms/nv04:nv50
 | # drm/kms/nv04:nv50
 | ||||||
| nouveau-y += nouveau_hw.o nouveau_calc.o | nouveau-y += nouveau_hw.o nouveau_calc.o | ||||||
|  | @ -202,4 +172,9 @@ nouveau-y += nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o | ||||||
| nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o | nouveau-y += nv04_pm.o nv40_pm.o nv50_pm.o nva3_pm.o nvc0_pm.o | ||||||
| nouveau-y += nouveau_mem.o | nouveau-y += nouveau_mem.o | ||||||
| 
 | 
 | ||||||
|  | # other random bits
 | ||||||
|  | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o | ||||||
|  | nouveau-$(CONFIG_ACPI) += nouveau_acpi.o | ||||||
|  | nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o | ||||||
|  | 
 | ||||||
| obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o | obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o | ||||||
|  |  | ||||||
|  | @ -20,8 +20,8 @@ void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); | ||||||
| 	nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) | 	nouveau_timer_wait_eq((o), NV_WAIT_DEFAULT, (a), (m), (v)) | ||||||
| #define nv_wait_ne(o,a,m,v)                                                    \ | #define nv_wait_ne(o,a,m,v)                                                    \ | ||||||
| 	nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v)) | 	nouveau_timer_wait_ne((o), NV_WAIT_DEFAULT, (a), (m), (v)) | ||||||
| #define nv_wait_cb(o,a,m,v)                                                    \ | #define nv_wait_cb(o,c,d)                                                      \ | ||||||
| 	nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (a), (m), (v)) | 	nouveau_timer_wait_cb((o), NV_WAIT_DEFAULT, (c), (d)) | ||||||
| 
 | 
 | ||||||
| struct nouveau_timer { | struct nouveau_timer { | ||||||
| 	struct nouveau_subdev base; | 	struct nouveau_subdev base; | ||||||
|  |  | ||||||
|  | @ -56,6 +56,31 @@ nvbios_findstr(const u8 *data, int size, const char *str, int len) | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #if defined(__powerpc__) | ||||||
|  | static void | ||||||
|  | nouveau_bios_shadow_of(struct nouveau_bios *bios) | ||||||
|  | { | ||||||
|  | 	struct pci_dev *pdev = nv_device(bios)->pdev; | ||||||
|  | 	struct device_node *dn; | ||||||
|  | 	const u32 *data; | ||||||
|  | 	int size, i; | ||||||
|  | 
 | ||||||
|  | 	dn = pci_device_to_OF_node(pdev); | ||||||
|  | 	if (!dn) { | ||||||
|  | 		nv_info(bios, "Unable to get the OF node\n"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	data = of_get_property(dn, "NVDA,BMP", &size); | ||||||
|  | 	if (data) { | ||||||
|  | 		bios->size = size; | ||||||
|  | 		bios->data = kmalloc(bios->size, GFP_KERNEL); | ||||||
|  | 		if (bios->data) | ||||||
|  | 			memcpy(bios->data, data, size); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| nouveau_bios_shadow_pramin(struct nouveau_bios *bios) | nouveau_bios_shadow_pramin(struct nouveau_bios *bios) | ||||||
| { | { | ||||||
|  | @ -221,7 +246,7 @@ nouveau_bios_score(struct nouveau_bios *bios, const bool writeable) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct methods { | struct methods { | ||||||
| 	const char desc[8]; | 	const char desc[16]; | ||||||
| 	void (*shadow)(struct nouveau_bios *); | 	void (*shadow)(struct nouveau_bios *); | ||||||
| 	const bool rw; | 	const bool rw; | ||||||
| 	int score; | 	int score; | ||||||
|  | @ -233,6 +258,9 @@ static int | ||||||
| nouveau_bios_shadow(struct nouveau_bios *bios) | nouveau_bios_shadow(struct nouveau_bios *bios) | ||||||
| { | { | ||||||
| 	struct methods shadow_methods[] = { | 	struct methods shadow_methods[] = { | ||||||
|  | #if defined(__powerpc__) | ||||||
|  | 		{ "OpenFirmware", nouveau_bios_shadow_of, true, 0, 0, NULL }, | ||||||
|  | #endif | ||||||
| 		{ "PRAMIN", nouveau_bios_shadow_pramin, true, 0, 0, NULL }, | 		{ "PRAMIN", nouveau_bios_shadow_pramin, true, 0, 0, NULL }, | ||||||
| 		{ "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL }, | 		{ "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL }, | ||||||
| 		{ "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL }, | 		{ "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL }, | ||||||
|  |  | ||||||
|  | @ -71,7 +71,7 @@ static const struct backlight_ops nv40_bl_ops = { | ||||||
| static int | static int | ||||||
| nv40_backlight_init(struct drm_connector *connector) | nv40_backlight_init(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(connector->dev); | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	struct backlight_properties props; | 	struct backlight_properties props; | ||||||
| 	struct backlight_device *bd; | 	struct backlight_device *bd; | ||||||
|  | @ -95,7 +95,7 @@ static int | ||||||
| nv50_get_intensity(struct backlight_device *bd) | nv50_get_intensity(struct backlight_device *bd) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); | 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 div = 1025; | 	u32 div = 1025; | ||||||
|  | @ -110,7 +110,7 @@ static int | ||||||
| nv50_set_intensity(struct backlight_device *bd) | nv50_set_intensity(struct backlight_device *bd) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); | 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 div = 1025; | 	u32 div = 1025; | ||||||
|  | @ -131,7 +131,7 @@ static int | ||||||
| nva3_get_intensity(struct backlight_device *bd) | nva3_get_intensity(struct backlight_device *bd) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); | 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 div, val; | 	u32 div, val; | ||||||
|  | @ -149,7 +149,7 @@ static int | ||||||
| nva3_set_intensity(struct backlight_device *bd) | nva3_set_intensity(struct backlight_device *bd) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | 	struct nouveau_encoder *nv_encoder = bl_get_data(bd); | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nv_encoder->base.base.dev); | 	struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 div, val; | 	u32 div, val; | ||||||
|  | @ -175,7 +175,7 @@ static const struct backlight_ops nva3_bl_ops = { | ||||||
| static int | static int | ||||||
| nv50_backlight_init(struct drm_connector *connector) | nv50_backlight_init(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(connector->dev); | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	struct nouveau_encoder *nv_encoder; | 	struct nouveau_encoder *nv_encoder; | ||||||
| 	struct backlight_properties props; | 	struct backlight_properties props; | ||||||
|  | @ -216,7 +216,7 @@ nv50_backlight_init(struct drm_connector *connector) | ||||||
| int | int | ||||||
| nouveau_backlight_init(struct drm_device *dev) | nouveau_backlight_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	struct drm_connector *connector; | 	struct drm_connector *connector; | ||||||
| 
 | 
 | ||||||
|  | @ -250,7 +250,7 @@ nouveau_backlight_init(struct drm_device *dev) | ||||||
| void | void | ||||||
| nouveau_backlight_exit(struct drm_device *dev) | nouveau_backlight_exit(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (drm->backlight) { | 	if (drm->backlight) { | ||||||
| 		backlight_device_unregister(drm->backlight); | 		backlight_device_unregister(drm->backlight); | ||||||
|  |  | ||||||
|  | @ -22,9 +22,11 @@ | ||||||
|  * SOFTWARE. |  * SOFTWARE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/bios.h> | ||||||
|  | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #define NV_DEBUG_NOTRACE | #include "nouveau_drm.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| 
 | 
 | ||||||
|  | @ -94,7 +96,9 @@ static void | ||||||
| run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, | run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, | ||||||
| 		      struct dcb_output *dcbent, int head, bool dl) | 		      struct dcb_output *dcbent, int head, bool dl) | ||||||
| { | { | ||||||
| 	NV_TRACE(dev, "0x%04X: Parsing digital output script table\n", | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
|  | 	NV_INFO(drm, "0x%04X: Parsing digital output script table\n", | ||||||
| 		 scriptptr); | 		 scriptptr); | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, head ? NV_CIO_CRE_44_HEADB : | 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, head ? NV_CIO_CRE_44_HEADB : | ||||||
| 					         NV_CIO_CRE_44_HEADA); | 					         NV_CIO_CRE_44_HEADA); | ||||||
|  | @ -105,8 +109,8 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr, | ||||||
| 
 | 
 | ||||||
| static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script) | static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_output *dcbent, int head, enum LVDS_script script) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & DCB_OUTPUT_C ? 1 : 0); | 	uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & DCB_OUTPUT_C ? 1 : 0); | ||||||
| 	uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]); | 	uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]); | ||||||
| 
 | 
 | ||||||
|  | @ -142,8 +146,8 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int | ||||||
| 	 * conf byte. These tables are similar to the TMDS tables, consisting | 	 * conf byte. These tables are similar to the TMDS tables, consisting | ||||||
| 	 * of a list of pxclks and script pointers. | 	 * of a list of pxclks and script pointers. | ||||||
| 	 */ | 	 */ | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	unsigned int outputset = (dcbent->or == 4) ? 1 : 0; | 	unsigned int outputset = (dcbent->or == 4) ? 1 : 0; | ||||||
| 	uint16_t scriptptr = 0, clktable; | 	uint16_t scriptptr = 0, clktable; | ||||||
| 
 | 
 | ||||||
|  | @ -188,14 +192,14 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_output *dcbent, int | ||||||
| 
 | 
 | ||||||
| 		clktable = ROM16(bios->data[clktable]); | 		clktable = ROM16(bios->data[clktable]); | ||||||
| 		if (!clktable) { | 		if (!clktable) { | ||||||
| 			NV_ERROR(dev, "Pixel clock comparison table not found\n"); | 			NV_ERROR(drm, "Pixel clock comparison table not found\n"); | ||||||
| 			return -ENOENT; | 			return -ENOENT; | ||||||
| 		} | 		} | ||||||
| 		scriptptr = clkcmptable(bios, clktable, pxclk); | 		scriptptr = clkcmptable(bios, clktable, pxclk); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!scriptptr) { | 	if (!scriptptr) { | ||||||
| 		NV_ERROR(dev, "LVDS output init script not found\n"); | 		NV_ERROR(drm, "LVDS output init script not found\n"); | ||||||
| 		return -ENOENT; | 		return -ENOENT; | ||||||
| 	} | 	} | ||||||
| 	run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link); | 	run_digital_op_script(dev, scriptptr, dcbent, head, bios->fp.dual_link); | ||||||
|  | @ -211,8 +215,9 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head | ||||||
| 	 * This acts as the demux | 	 * This acts as the demux | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; | 	uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer]; | ||||||
| 	uint32_t sel_clk_binding, sel_clk; | 	uint32_t sel_clk_binding, sel_clk; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -231,10 +236,10 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head | ||||||
| 	if (script == LVDS_RESET && bios->fp.power_off_for_reset) | 	if (script == LVDS_RESET && bios->fp.power_off_for_reset) | ||||||
| 		call_lvds_script(dev, dcbent, head, LVDS_PANEL_OFF, pxclk); | 		call_lvds_script(dev, dcbent, head, LVDS_PANEL_OFF, pxclk); | ||||||
| 
 | 
 | ||||||
| 	NV_TRACE(dev, "Calling LVDS script %d:\n", script); | 	NV_INFO(drm, "Calling LVDS script %d:\n", script); | ||||||
| 
 | 
 | ||||||
| 	/* don't let script change pll->head binding */ | 	/* don't let script change pll->head binding */ | ||||||
| 	sel_clk_binding = nv_rd32(dev, NV_PRAMDAC_SEL_CLK) & 0x50000; | 	sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000; | ||||||
| 
 | 
 | ||||||
| 	if (lvds_ver < 0x30) | 	if (lvds_ver < 0x30) | ||||||
| 		ret = call_lvds_manufacturer_script(dev, dcbent, head, script); | 		ret = call_lvds_manufacturer_script(dev, dcbent, head, script); | ||||||
|  | @ -246,7 +251,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_output *dcbent, int head | ||||||
| 	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; | 	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); | ||||||
| 	/* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */ | 	/* some scripts set a value in NV_PBUS_POWERCTRL_2 and break video overlay */ | ||||||
| 	nv_wr32(dev, NV_PBUS_POWERCTRL_2, 0); | 	nv_wr32(device, NV_PBUS_POWERCTRL_2, 0); | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | @ -264,12 +269,13 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n | ||||||
| 	 * the maximum number of records that can be held in the table. | 	 * the maximum number of records that can be held in the table. | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t lvds_ver, headerlen, recordlen; | 	uint8_t lvds_ver, headerlen, recordlen; | ||||||
| 
 | 
 | ||||||
| 	memset(lth, 0, sizeof(struct lvdstableheader)); | 	memset(lth, 0, sizeof(struct lvdstableheader)); | ||||||
| 
 | 
 | ||||||
| 	if (bios->fp.lvdsmanufacturerpointer == 0x0) { | 	if (bios->fp.lvdsmanufacturerpointer == 0x0) { | ||||||
| 		NV_ERROR(dev, "Pointer to LVDS manufacturer table invalid\n"); | 		NV_ERROR(drm, "Pointer to LVDS manufacturer table invalid\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -283,7 +289,7 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n | ||||||
| 	case 0x30:	/* NV4x */ | 	case 0x30:	/* NV4x */ | ||||||
| 		headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; | 		headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; | ||||||
| 		if (headerlen < 0x1f) { | 		if (headerlen < 0x1f) { | ||||||
| 			NV_ERROR(dev, "LVDS table header not understood\n"); | 			NV_ERROR(drm, "LVDS table header not understood\n"); | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		} | 		} | ||||||
| 		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; | 		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; | ||||||
|  | @ -291,13 +297,13 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n | ||||||
| 	case 0x40:	/* G80/G90 */ | 	case 0x40:	/* G80/G90 */ | ||||||
| 		headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; | 		headerlen = bios->data[bios->fp.lvdsmanufacturerpointer + 1]; | ||||||
| 		if (headerlen < 0x7) { | 		if (headerlen < 0x7) { | ||||||
| 			NV_ERROR(dev, "LVDS table header not understood\n"); | 			NV_ERROR(drm, "LVDS table header not understood\n"); | ||||||
| 			return -EINVAL; | 			return -EINVAL; | ||||||
| 		} | 		} | ||||||
| 		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; | 		recordlen = bios->data[bios->fp.lvdsmanufacturerpointer + 2]; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, | 		NV_ERROR(drm, | ||||||
| 			 "LVDS table revision %d.%d not currently supported\n", | 			 "LVDS table revision %d.%d not currently supported\n", | ||||||
| 			 lvds_ver >> 4, lvds_ver & 0xf); | 			 lvds_ver >> 4, lvds_ver & 0xf); | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
|  | @ -313,7 +319,7 @@ static int parse_lvds_manufacturer_table_header(struct drm_device *dev, struct n | ||||||
| static int | static int | ||||||
| get_fp_strap(struct drm_device *dev, struct nvbios *bios) | get_fp_strap(struct drm_device *dev, struct nvbios *bios) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * The fp strap is normally dictated by the "User Strap" in | 	 * The fp strap is normally dictated by the "User Strap" in | ||||||
|  | @ -327,14 +333,15 @@ get_fp_strap(struct drm_device *dev, struct nvbios *bios) | ||||||
| 	if (bios->major_version < 5 && bios->data[0x48] & 0x4) | 	if (bios->major_version < 5 && bios->data[0x48] & 0x4) | ||||||
| 		return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf; | 		return NVReadVgaCrtc5758(dev, 0, 0xf) & 0xf; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_50) | 	if (device->card_type >= NV_50) | ||||||
| 		return (nv_rd32(dev, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; | 		return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 24) & 0xf; | ||||||
| 	else | 	else | ||||||
| 		return (nv_rd32(dev, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; | 		return (nv_rd32(device, NV_PEXTDEV_BOOT_0) >> 16) & 0xf; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t *fptable; | 	uint8_t *fptable; | ||||||
| 	uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex; | 	uint8_t fptable_ver, headerlen = 0, recordlen, fpentries = 0xf, fpindex; | ||||||
| 	int ret, ofs, fpstrapping; | 	int ret, ofs, fpstrapping; | ||||||
|  | @ -344,7 +351,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 		/* Apple cards don't have the fp table; the laptops use DDC */ | 		/* Apple cards don't have the fp table; the laptops use DDC */ | ||||||
| 		/* The table is also missing on some x86 IGPs */ | 		/* The table is also missing on some x86 IGPs */ | ||||||
| #ifndef __powerpc__ | #ifndef __powerpc__ | ||||||
| 		NV_ERROR(dev, "Pointer to flat panel table invalid\n"); | 		NV_ERROR(drm, "Pointer to flat panel table invalid\n"); | ||||||
| #endif | #endif | ||||||
| 		bios->digital_min_front_porch = 0x4b; | 		bios->digital_min_front_porch = 0x4b; | ||||||
| 		return 0; | 		return 0; | ||||||
|  | @ -383,7 +390,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 		ofs = -7; | 		ofs = -7; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, | 		NV_ERROR(drm, | ||||||
| 			 "FP table revision %d.%d not currently supported\n", | 			 "FP table revision %d.%d not currently supported\n", | ||||||
| 			 fptable_ver >> 4, fptable_ver & 0xf); | 			 fptable_ver >> 4, fptable_ver & 0xf); | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
|  | @ -402,7 +409,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 		bios->fp.xlatwidth = lth.recordlen; | 		bios->fp.xlatwidth = lth.recordlen; | ||||||
| 	} | 	} | ||||||
| 	if (bios->fp.fpxlatetableptr == 0x0) { | 	if (bios->fp.fpxlatetableptr == 0x0) { | ||||||
| 		NV_ERROR(dev, "Pointer to flat panel xlat table invalid\n"); | 		NV_ERROR(drm, "Pointer to flat panel xlat table invalid\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -412,7 +419,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 					fpstrapping * bios->fp.xlatwidth]; | 					fpstrapping * bios->fp.xlatwidth]; | ||||||
| 
 | 
 | ||||||
| 	if (fpindex > fpentries) { | 	if (fpindex > fpentries) { | ||||||
| 		NV_ERROR(dev, "Bad flat panel table index\n"); | 		NV_ERROR(drm, "Bad flat panel table index\n"); | ||||||
| 		return -ENOENT; | 		return -ENOENT; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -431,7 +438,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 	bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen + | 	bios->fp.mode_ptr = bios->fp.fptablepointer + headerlen + | ||||||
| 			    recordlen * fpindex + ofs; | 			    recordlen * fpindex + ofs; | ||||||
| 
 | 
 | ||||||
| 	NV_TRACE(dev, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n", | 	NV_INFO(drm, "BIOS FP mode: %dx%d (%dkHz pixel clock)\n", | ||||||
| 		 ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1, | 		 ROM16(bios->data[bios->fp.mode_ptr + 11]) + 1, | ||||||
| 		 ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1, | 		 ROM16(bios->data[bios->fp.mode_ptr + 25]) + 1, | ||||||
| 		 ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10); | 		 ROM16(bios->data[bios->fp.mode_ptr + 7]) * 10); | ||||||
|  | @ -441,8 +448,8 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 
 | 
 | ||||||
| bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode) | bool nouveau_bios_fp_mode(struct drm_device *dev, struct drm_display_mode *mode) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr]; | 	uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr]; | ||||||
| 
 | 
 | ||||||
| 	if (!mode)	/* just checking whether we can produce a mode */ | 	if (!mode)	/* just checking whether we can produce a mode */ | ||||||
|  | @ -512,8 +519,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b | ||||||
| 	 * requiring tests against the native-mode pixel clock, cannot be done | 	 * requiring tests against the native-mode pixel clock, cannot be done | ||||||
| 	 * until later, when this function should be called with non-zero pxclk | 	 * until later, when this function should be called with non-zero pxclk | ||||||
| 	 */ | 	 */ | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0; | 	int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0; | ||||||
| 	struct lvdstableheader lth; | 	struct lvdstableheader lth; | ||||||
| 	uint16_t lvdsofs; | 	uint16_t lvdsofs; | ||||||
|  | @ -574,7 +581,7 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b | ||||||
| 		lvdsmanufacturerindex = fpstrapping; | 		lvdsmanufacturerindex = fpstrapping; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, "LVDS table revision not currently supported\n"); | 		NV_ERROR(drm, "LVDS table revision not currently supported\n"); | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -671,15 +678,15 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 	 * offset + 5   (16 bits): pointer to first output script table | 	 * offset + 5   (16 bits): pointer to first output script table | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	uint8_t *table = &bios->data[bios->display.script_table_ptr]; | 	uint8_t *table = &bios->data[bios->display.script_table_ptr]; | ||||||
| 	uint8_t *otable = NULL; | 	uint8_t *otable = NULL; | ||||||
| 	uint16_t script; | 	uint16_t script; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (!bios->display.script_table_ptr) { | 	if (!bios->display.script_table_ptr) { | ||||||
| 		NV_ERROR(dev, "No pointer to output script table\n"); | 		NV_ERROR(drm, "No pointer to output script table\n"); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -691,7 +698,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 		return 1; | 		return 1; | ||||||
| 
 | 
 | ||||||
| 	if (table[0] != 0x20 && table[0] != 0x21) { | 	if (table[0] != 0x20 && table[0] != 0x21) { | ||||||
| 		NV_ERROR(dev, "Output script table version 0x%02x unknown\n", | 		NV_ERROR(drm, "Output script table version 0x%02x unknown\n", | ||||||
| 			 table[0]); | 			 table[0]); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
|  | @ -726,7 +733,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 	 * script tables is a pointer to the script to execute. | 	 * script tables is a pointer to the script to execute. | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", | 	NV_DEBUG(drm, "Searching for output entry for %d %d %d\n", | ||||||
| 			dcbent->type, dcbent->location, dcbent->or); | 			dcbent->type, dcbent->location, dcbent->or); | ||||||
| 	for (i = 0; i < table[3]; i++) { | 	for (i = 0; i < table[3]; i++) { | ||||||
| 		otable = ROMPTR(dev, table[table[1] + (i * table[2])]); | 		otable = ROMPTR(dev, table[table[1] + (i * table[2])]); | ||||||
|  | @ -735,7 +742,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!otable) { | 	if (!otable) { | ||||||
| 		NV_DEBUG_KMS(dev, "failed to match any output table\n"); | 		NV_DEBUG(drm, "failed to match any output table\n"); | ||||||
| 		return 1; | 		return 1; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -747,7 +754,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (i == otable[5]) { | 		if (i == otable[5]) { | ||||||
| 			NV_ERROR(dev, "Table 0x%04x not found for %d/%d, " | 			NV_ERROR(drm, "Table 0x%04x not found for %d/%d, " | ||||||
| 				      "using first\n", | 				      "using first\n", | ||||||
| 				 type, dcbent->type, dcbent->or); | 				 type, dcbent->type, dcbent->or); | ||||||
| 			i = 0; | 			i = 0; | ||||||
|  | @ -757,21 +764,21 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 	if (pclk == 0) { | 	if (pclk == 0) { | ||||||
| 		script = ROM16(otable[6]); | 		script = ROM16(otable[6]); | ||||||
| 		if (!script) { | 		if (!script) { | ||||||
| 			NV_DEBUG_KMS(dev, "output script 0 not found\n"); | 			NV_DEBUG(drm, "output script 0 not found\n"); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 0\n", script); | 		NV_DEBUG(drm, "0x%04X: parsing output script 0\n", script); | ||||||
| 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | ||||||
| 	} else | 	} else | ||||||
| 	if (pclk == -1) { | 	if (pclk == -1) { | ||||||
| 		script = ROM16(otable[8]); | 		script = ROM16(otable[8]); | ||||||
| 		if (!script) { | 		if (!script) { | ||||||
| 			NV_DEBUG_KMS(dev, "output script 1 not found\n"); | 			NV_DEBUG(drm, "output script 1 not found\n"); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 1\n", script); | 		NV_DEBUG(drm, "0x%04X: parsing output script 1\n", script); | ||||||
| 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | ||||||
| 	} else | 	} else | ||||||
| 	if (pclk == -2) { | 	if (pclk == -2) { | ||||||
|  | @ -780,11 +787,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 		else | 		else | ||||||
| 			script = 0; | 			script = 0; | ||||||
| 		if (!script) { | 		if (!script) { | ||||||
| 			NV_DEBUG_KMS(dev, "output script 2 not found\n"); | 			NV_DEBUG(drm, "output script 2 not found\n"); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "0x%04X: parsing output script 2\n", script); | 		NV_DEBUG(drm, "0x%04X: parsing output script 2\n", script); | ||||||
| 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | ||||||
| 	} else | 	} else | ||||||
| 	if (pclk > 0) { | 	if (pclk > 0) { | ||||||
|  | @ -792,11 +799,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 		if (script) | 		if (script) | ||||||
| 			script = clkcmptable(bios, script, pclk); | 			script = clkcmptable(bios, script, pclk); | ||||||
| 		if (!script) { | 		if (!script) { | ||||||
| 			NV_DEBUG_KMS(dev, "clock script 0 not found\n"); | 			NV_DEBUG(drm, "clock script 0 not found\n"); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 0\n", script); | 		NV_DEBUG(drm, "0x%04X: parsing clock script 0\n", script); | ||||||
| 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | ||||||
| 	} else | 	} else | ||||||
| 	if (pclk < 0) { | 	if (pclk < 0) { | ||||||
|  | @ -804,11 +811,11 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, | ||||||
| 		if (script) | 		if (script) | ||||||
| 			script = clkcmptable(bios, script, -pclk); | 			script = clkcmptable(bios, script, -pclk); | ||||||
| 		if (!script) { | 		if (!script) { | ||||||
| 			NV_DEBUG_KMS(dev, "clock script 1 not found\n"); | 			NV_DEBUG(drm, "clock script 1 not found\n"); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "0x%04X: parsing clock script 1\n", script); | 		NV_DEBUG(drm, "0x%04X: parsing clock script 1\n", script); | ||||||
| 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | 		nouveau_bios_run_init_table(dev, script, dcbent, crtc); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -827,8 +834,9 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, | ||||||
| 	 * ffs(or) == 3, use the second. | 	 * ffs(or) == 3, use the second. | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	int cv = bios->chip_version; | 	int cv = bios->chip_version; | ||||||
| 	uint16_t clktable = 0, scriptptr; | 	uint16_t clktable = 0, scriptptr; | ||||||
| 	uint32_t sel_clk_binding, sel_clk; | 	uint32_t sel_clk_binding, sel_clk; | ||||||
|  | @ -849,19 +857,19 @@ int run_tmds_table(struct drm_device *dev, struct dcb_output *dcbent, int head, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!clktable) { | 	if (!clktable) { | ||||||
| 		NV_ERROR(dev, "Pixel clock comparison table not found\n"); | 		NV_ERROR(drm, "Pixel clock comparison table not found\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	scriptptr = clkcmptable(bios, clktable, pxclk); | 	scriptptr = clkcmptable(bios, clktable, pxclk); | ||||||
| 
 | 
 | ||||||
| 	if (!scriptptr) { | 	if (!scriptptr) { | ||||||
| 		NV_ERROR(dev, "TMDS output init script not found\n"); | 		NV_ERROR(drm, "TMDS output init script not found\n"); | ||||||
| 		return -ENOENT; | 		return -ENOENT; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* don't let script change pll->head binding */ | 	/* don't let script change pll->head binding */ | ||||||
| 	sel_clk_binding = nv_rd32(dev, NV_PRAMDAC_SEL_CLK) & 0x50000; | 	sel_clk_binding = nv_rd32(device, NV_PRAMDAC_SEL_CLK) & 0x50000; | ||||||
| 	run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000); | 	run_digital_op_script(dev, scriptptr, dcbent, head, pxclk >= 165000); | ||||||
| 	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; | 	sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK) & ~0x50000; | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, sel_clk | sel_clk_binding); | ||||||
|  | @ -877,10 +885,11 @@ static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint | ||||||
| 	 * offset + 2  (8 bits): Chip version | 	 * offset + 2  (8 bits): Chip version | ||||||
| 	 * offset + 3  (8 bits): Major version | 	 * offset + 3  (8 bits): Major version | ||||||
| 	 */ | 	 */ | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	bios->major_version = bios->data[offset + 3]; | 	bios->major_version = bios->data[offset + 3]; | ||||||
| 	bios->chip_version = bios->data[offset + 2]; | 	bios->chip_version = bios->data[offset + 2]; | ||||||
| 	NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n", | 	NV_INFO(drm, "Bios version %02x.%02x.%02x.%02x\n", | ||||||
| 		 bios->data[offset + 3], bios->data[offset + 2], | 		 bios->data[offset + 3], bios->data[offset + 2], | ||||||
| 		 bios->data[offset + 1], bios->data[offset]); | 		 bios->data[offset + 1], bios->data[offset]); | ||||||
| } | } | ||||||
|  | @ -916,25 +925,26 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st | ||||||
| 	 * offset + 0 (16 bits): loadval table pointer | 	 * offset + 0 (16 bits): loadval table pointer | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint16_t load_table_ptr; | 	uint16_t load_table_ptr; | ||||||
| 	uint8_t version, headerlen, entrylen, num_entries; | 	uint8_t version, headerlen, entrylen, num_entries; | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length != 3) { | 	if (bitentry->length != 3) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT A table\n"); | 		NV_ERROR(drm, "Do not understand BIT A table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	load_table_ptr = ROM16(bios->data[bitentry->offset]); | 	load_table_ptr = ROM16(bios->data[bitentry->offset]); | ||||||
| 
 | 
 | ||||||
| 	if (load_table_ptr == 0x0) { | 	if (load_table_ptr == 0x0) { | ||||||
| 		NV_DEBUG(dev, "Pointer to BIT loadval table invalid\n"); | 		NV_DEBUG(drm, "Pointer to BIT loadval table invalid\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	version = bios->data[load_table_ptr]; | 	version = bios->data[load_table_ptr]; | ||||||
| 
 | 
 | ||||||
| 	if (version != 0x10) { | 	if (version != 0x10) { | ||||||
| 		NV_ERROR(dev, "BIT loadval table version %d.%d not supported\n", | 		NV_ERROR(drm, "BIT loadval table version %d.%d not supported\n", | ||||||
| 			 version >> 4, version & 0xF); | 			 version >> 4, version & 0xF); | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
| 	} | 	} | ||||||
|  | @ -944,7 +954,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st | ||||||
| 	num_entries = bios->data[load_table_ptr + 3]; | 	num_entries = bios->data[load_table_ptr + 3]; | ||||||
| 
 | 
 | ||||||
| 	if (headerlen != 4 || entrylen != 4 || num_entries != 2) { | 	if (headerlen != 4 || entrylen != 4 || num_entries != 2) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT loadval table\n"); | 		NV_ERROR(drm, "Do not understand BIT loadval table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -961,9 +971,10 @@ static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, st | ||||||
| 	 * | 	 * | ||||||
| 	 * There's more in here, but that's unknown. | 	 * There's more in here, but that's unknown. | ||||||
| 	 */ | 	 */ | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length < 10) { | 	if (bitentry->length < 10) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT C table\n"); | 		NV_ERROR(drm, "Do not understand BIT C table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -982,9 +993,10 @@ static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bi | ||||||
| 	 * records beginning with a freq. | 	 * records beginning with a freq. | ||||||
| 	 * offset + 2  (16 bits): mode table pointer | 	 * offset + 2  (16 bits): mode table pointer | ||||||
| 	 */ | 	 */ | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length != 4) { | 	if (bitentry->length != 4) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT display table\n"); | 		NV_ERROR(drm, "Do not understand BIT display table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1000,9 +1012,10 @@ static int parse_bit_init_tbl_entry(struct drm_device *dev, struct nvbios *bios, | ||||||
| 	 * | 	 * | ||||||
| 	 * See parse_script_table_pointers for layout | 	 * See parse_script_table_pointers for layout | ||||||
| 	 */ | 	 */ | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length < 14) { | 	if (bitentry->length < 14) { | ||||||
| 		NV_ERROR(dev, "Do not understand init table\n"); | 		NV_ERROR(drm, "Do not understand init table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1029,11 +1042,12 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st | ||||||
| 	 * There's other things in the table, purpose unknown | 	 * There's other things in the table, purpose unknown | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint16_t daccmpoffset; | 	uint16_t daccmpoffset; | ||||||
| 	uint8_t dacver, dacheaderlen; | 	uint8_t dacver, dacheaderlen; | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length < 6) { | 	if (bitentry->length < 6) { | ||||||
| 		NV_ERROR(dev, "BIT i table too short for needed information\n"); | 		NV_ERROR(drm, "BIT i table too short for needed information\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1047,7 +1061,7 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st | ||||||
| 	bios->is_mobile = bios->feature_byte & FEATURE_MOBILE; | 	bios->is_mobile = bios->feature_byte & FEATURE_MOBILE; | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length < 15) { | 	if (bitentry->length < 15) { | ||||||
| 		NV_WARN(dev, "BIT i table not long enough for DAC load " | 		NV_WARN(drm, "BIT i table not long enough for DAC load " | ||||||
| 			       "detection comparison table\n"); | 			       "detection comparison table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
|  | @ -1068,7 +1082,7 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st | ||||||
| 	dacheaderlen = bios->data[daccmpoffset + 1]; | 	dacheaderlen = bios->data[daccmpoffset + 1]; | ||||||
| 
 | 
 | ||||||
| 	if (dacver != 0x00 && dacver != 0x10) { | 	if (dacver != 0x00 && dacver != 0x10) { | ||||||
| 		NV_WARN(dev, "DAC load detection comparison table version " | 		NV_WARN(drm, "DAC load detection comparison table version " | ||||||
| 			       "%d.%d not known\n", dacver >> 4, dacver & 0xf); | 			       "%d.%d not known\n", dacver >> 4, dacver & 0xf); | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
| 	} | 	} | ||||||
|  | @ -1088,8 +1102,10 @@ static int parse_bit_lvds_tbl_entry(struct drm_device *dev, struct nvbios *bios, | ||||||
| 	 * offset + 0  (16 bits): LVDS strap xlate table pointer | 	 * offset + 0  (16 bits): LVDS strap xlate table pointer | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (bitentry->length != 2) { | 	if (bitentry->length != 2) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT LVDS table\n"); | 		NV_ERROR(drm, "Do not understand BIT LVDS table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1159,20 +1175,21 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, | ||||||
| 	 * "or" from the DCB. | 	 * "or" from the DCB. | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint16_t tmdstableptr, script1, script2; | 	uint16_t tmdstableptr, script1, script2; | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length != 2) { | 	if (bitentry->length != 2) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT TMDS table\n"); | 		NV_ERROR(drm, "Do not understand BIT TMDS table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tmdstableptr = ROM16(bios->data[bitentry->offset]); | 	tmdstableptr = ROM16(bios->data[bitentry->offset]); | ||||||
| 	if (!tmdstableptr) { | 	if (!tmdstableptr) { | ||||||
| 		NV_ERROR(dev, "Pointer to TMDS table invalid\n"); | 		NV_ERROR(drm, "Pointer to TMDS table invalid\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "TMDS table version %d.%d\n", | 	NV_INFO(drm, "TMDS table version %d.%d\n", | ||||||
| 		bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); | 		bios->data[tmdstableptr] >> 4, bios->data[tmdstableptr] & 0xf); | ||||||
| 
 | 
 | ||||||
| 	/* nv50+ has v2.0, but we don't parse it atm */ | 	/* nv50+ has v2.0, but we don't parse it atm */ | ||||||
|  | @ -1186,7 +1203,7 @@ static int parse_bit_tmds_tbl_entry(struct drm_device *dev, struct nvbios *bios, | ||||||
| 	script1 = ROM16(bios->data[tmdstableptr + 7]); | 	script1 = ROM16(bios->data[tmdstableptr + 7]); | ||||||
| 	script2 = ROM16(bios->data[tmdstableptr + 9]); | 	script2 = ROM16(bios->data[tmdstableptr + 9]); | ||||||
| 	if (bios->data[script1] != 'q' || bios->data[script2] != 'q') | 	if (bios->data[script1] != 'q' || bios->data[script2] != 'q') | ||||||
| 		NV_WARN(dev, "TMDS table script pointers not stubbed\n"); | 		NV_WARN(drm, "TMDS table script pointers not stubbed\n"); | ||||||
| 
 | 
 | ||||||
| 	bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]); | 	bios->tmds.output0_script_ptr = ROM16(bios->data[tmdstableptr + 11]); | ||||||
| 	bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]); | 	bios->tmds.output1_script_ptr = ROM16(bios->data[tmdstableptr + 13]); | ||||||
|  | @ -1206,10 +1223,11 @@ parse_bit_U_tbl_entry(struct drm_device *dev, struct nvbios *bios, | ||||||
| 	 * offset + 0  (16 bits): output script table pointer | 	 * offset + 0  (16 bits): output script table pointer | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint16_t outputscripttableptr; | 	uint16_t outputscripttableptr; | ||||||
| 
 | 
 | ||||||
| 	if (bitentry->length != 3) { | 	if (bitentry->length != 3) { | ||||||
| 		NV_ERROR(dev, "Do not understand BIT U table\n"); | 		NV_ERROR(drm, "Do not understand BIT U table\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1228,8 +1246,8 @@ struct bit_table { | ||||||
| int | int | ||||||
| bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) | bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	u8 entries, *entry; | 	u8 entries, *entry; | ||||||
| 
 | 
 | ||||||
| 	if (bios->type != NVBIOS_BIT) | 	if (bios->type != NVBIOS_BIT) | ||||||
|  | @ -1258,12 +1276,13 @@ parse_bit_table(struct nvbios *bios, const uint16_t bitoffset, | ||||||
| 		struct bit_table *table) | 		struct bit_table *table) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = bios->dev; | 	struct drm_device *dev = bios->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct bit_entry bitentry; | 	struct bit_entry bitentry; | ||||||
| 
 | 
 | ||||||
| 	if (bit_table(dev, table->id, &bitentry) == 0) | 	if (bit_table(dev, table->id, &bitentry) == 0) | ||||||
| 		return table->parse_fn(dev, bios, &bitentry); | 		return table->parse_fn(dev, bios, &bitentry); | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "BIT table '%c' not found\n", table->id); | 	NV_INFO(drm, "BIT table '%c' not found\n", table->id); | ||||||
| 	return -ENOSYS; | 	return -ENOSYS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1343,6 +1362,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | ||||||
| 	 * offset + 156: minimum pixel clock for LVDS dual link | 	 * offset + 156: minimum pixel clock for LVDS dual link | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor; | 	uint8_t *bmp = &bios->data[offset], bmp_version_major, bmp_version_minor; | ||||||
| 	uint16_t bmplength; | 	uint16_t bmplength; | ||||||
| 	uint16_t legacy_scripts_offset, legacy_i2c_offset; | 	uint16_t legacy_scripts_offset, legacy_i2c_offset; | ||||||
|  | @ -1356,7 +1376,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | ||||||
| 	bmp_version_major = bmp[5]; | 	bmp_version_major = bmp[5]; | ||||||
| 	bmp_version_minor = bmp[6]; | 	bmp_version_minor = bmp[6]; | ||||||
| 
 | 
 | ||||||
| 	NV_TRACE(dev, "BMP version %d.%d\n", | 	NV_INFO(drm, "BMP version %d.%d\n", | ||||||
| 		 bmp_version_major, bmp_version_minor); | 		 bmp_version_major, bmp_version_minor); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -1372,7 +1392,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | ||||||
| 	 * happened instead. | 	 * happened instead. | ||||||
| 	 */ | 	 */ | ||||||
| 	if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) { | 	if ((bmp_version_major < 5 && bmp_version_minor != 1) || bmp_version_major > 5) { | ||||||
| 		NV_ERROR(dev, "You have an unsupported BMP version. " | 		NV_ERROR(drm, "You have an unsupported BMP version. " | ||||||
| 				"Please send in your bios\n"); | 				"Please send in your bios\n"); | ||||||
| 		return -ENOSYS; | 		return -ENOSYS; | ||||||
| 	} | 	} | ||||||
|  | @ -1421,7 +1441,7 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | ||||||
| 
 | 
 | ||||||
| 	/* checksum */ | 	/* checksum */ | ||||||
| 	if (nv_cksum(bmp, 8)) { | 	if (nv_cksum(bmp, 8)) { | ||||||
| 		NV_ERROR(dev, "Bad BMP checksum\n"); | 		NV_ERROR(drm, "Bad BMP checksum\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1508,18 +1528,18 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) | ||||||
| void * | void * | ||||||
| olddcb_table(struct drm_device *dev) | olddcb_table(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u8 *dcb = NULL; | 	u8 *dcb = NULL; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type > NV_04) | 	if (nv_device(drm->device)->card_type > NV_04) | ||||||
| 		dcb = ROMPTR(dev, dev_priv->vbios.data[0x36]); | 		dcb = ROMPTR(dev, drm->vbios.data[0x36]); | ||||||
| 	if (!dcb) { | 	if (!dcb) { | ||||||
| 		NV_WARNONCE(dev, "No DCB data found in VBIOS\n"); | 		NV_WARN(drm, "No DCB data found in VBIOS\n"); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dcb[0] >= 0x41) { | 	if (dcb[0] >= 0x41) { | ||||||
| 		NV_WARNONCE(dev, "DCB version 0x%02x unknown\n", dcb[0]); | 		NV_WARN(drm, "DCB version 0x%02x unknown\n", dcb[0]); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} else | 	} else | ||||||
| 	if (dcb[0] >= 0x30) { | 	if (dcb[0] >= 0x30) { | ||||||
|  | @ -1551,11 +1571,11 @@ olddcb_table(struct drm_device *dev) | ||||||
| 		 * | 		 * | ||||||
| 		 * v1.1 (NV5+, maybe some NV4) is entirely unhelpful | 		 * v1.1 (NV5+, maybe some NV4) is entirely unhelpful | ||||||
| 		 */ | 		 */ | ||||||
| 		NV_WARNONCE(dev, "No useful DCB data in VBIOS\n"); | 		NV_WARN(drm, "No useful DCB data in VBIOS\n"); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_WARNONCE(dev, "DCB header validation failed\n"); | 	NV_WARN(drm, "DCB header validation failed\n"); | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1656,6 +1676,8 @@ static bool | ||||||
| parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | ||||||
| 		  uint32_t conn, uint32_t conf, struct dcb_output *entry) | 		  uint32_t conn, uint32_t conf, struct dcb_output *entry) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	entry->type = conn & 0xf; | 	entry->type = conn & 0xf; | ||||||
| 	entry->i2c_index = (conn >> 4) & 0xf; | 	entry->i2c_index = (conn >> 4) & 0xf; | ||||||
| 	entry->heads = (conn >> 8) & 0xf; | 	entry->heads = (conn >> 8) & 0xf; | ||||||
|  | @ -1709,7 +1731,7 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | ||||||
| 			if (dcb->version >= 0x40) | 			if (dcb->version >= 0x40) | ||||||
| 				break; | 				break; | ||||||
| 
 | 
 | ||||||
| 			NV_ERROR(dev, "Unknown LVDS configuration bits, " | 			NV_ERROR(drm, "Unknown LVDS configuration bits, " | ||||||
| 				      "please report\n"); | 				      "please report\n"); | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
|  | @ -1783,6 +1805,8 @@ static bool | ||||||
| parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, | parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, | ||||||
| 		  uint32_t conn, uint32_t conf, struct dcb_output *entry) | 		  uint32_t conn, uint32_t conf, struct dcb_output *entry) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	switch (conn & 0x0000000f) { | 	switch (conn & 0x0000000f) { | ||||||
| 	case 0: | 	case 0: | ||||||
| 		entry->type = DCB_OUTPUT_ANALOG; | 		entry->type = DCB_OUTPUT_ANALOG; | ||||||
|  | @ -1801,7 +1825,7 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, | ||||||
| 		entry->type = DCB_OUTPUT_LVDS; | 		entry->type = DCB_OUTPUT_LVDS; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); | 		NV_ERROR(drm, "Unknown DCB type %d\n", conn & 0x0000000f); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -1840,6 +1864,7 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) | ||||||
| 	 * more options | 	 * more options | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int i, newentries = 0; | 	int i, newentries = 0; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < dcb->entries; i++) { | 	for (i = 0; i < dcb->entries; i++) { | ||||||
|  | @ -1857,7 +1882,7 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) | ||||||
| 			    jent->type == ient->type && | 			    jent->type == ient->type && | ||||||
| 			    jent->location == ient->location && | 			    jent->location == ient->location && | ||||||
| 			    jent->or == ient->or) { | 			    jent->or == ient->or) { | ||||||
| 				NV_TRACE(dev, "Merging DCB entries %d and %d\n", | 				NV_INFO(drm, "Merging DCB entries %d and %d\n", | ||||||
| 					 i, j); | 					 i, j); | ||||||
| 				ient->heads |= jent->heads; | 				ient->heads |= jent->heads; | ||||||
| 				jent->type = 100; /* dummy value */ | 				jent->type = 100; /* dummy value */ | ||||||
|  | @ -1883,8 +1908,8 @@ void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb) | ||||||
| static bool | static bool | ||||||
| apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) | apply_dcb_encoder_quirks(struct drm_device *dev, int idx, u32 *conn, u32 *conf) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_table *dcb = &dev_priv->vbios.dcb; | 	struct dcb_table *dcb = &drm->vbios.dcb; | ||||||
| 
 | 
 | ||||||
| 	/* Dell Precision M6300
 | 	/* Dell Precision M6300
 | ||||||
| 	 *   DCB entry 2: 02025312 00000010 | 	 *   DCB entry 2: 02025312 00000010 | ||||||
|  | @ -2021,8 +2046,8 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| static int | static int | ||||||
| parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) | parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_table *dcb = &dev_priv->vbios.dcb; | 	struct dcb_table *dcb = &drm->vbios.dcb; | ||||||
| 	u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]); | 	u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]); | ||||||
| 	u32 conn = ROM32(outp[0]); | 	u32 conn = ROM32(outp[0]); | ||||||
| 	bool ret; | 	bool ret; | ||||||
|  | @ -2030,7 +2055,7 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) | ||||||
| 	if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) { | 	if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) { | ||||||
| 		struct dcb_output *entry = new_dcb_entry(dcb); | 		struct dcb_output *entry = new_dcb_entry(dcb); | ||||||
| 
 | 
 | ||||||
| 		NV_TRACEWARN(dev, "DCB outp %02d: %08x %08x\n", idx, conn, conf); | 		NV_INFO(drm, "DCB outp %02d: %08x %08x\n", idx, conn, conf); | ||||||
| 
 | 
 | ||||||
| 		if (dcb->version >= 0x20) | 		if (dcb->version >= 0x20) | ||||||
| 			ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); | 			ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); | ||||||
|  | @ -2100,6 +2125,7 @@ dcb_fake_connectors(struct nvbios *bios) | ||||||
| static int | static int | ||||||
| parse_dcb_table(struct drm_device *dev, struct nvbios *bios) | parse_dcb_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_table *dcb = &bios->dcb; | 	struct dcb_table *dcb = &bios->dcb; | ||||||
| 	u8 *dcbt, *conn; | 	u8 *dcbt, *conn; | ||||||
| 	int idx; | 	int idx; | ||||||
|  | @ -2115,7 +2141,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); | 	NV_INFO(drm, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); | ||||||
| 
 | 
 | ||||||
| 	dcb->version = dcbt[0]; | 	dcb->version = dcbt[0]; | ||||||
| 	olddcb_outp_foreach(dev, NULL, parse_dcb_entry); | 	olddcb_outp_foreach(dev, NULL, parse_dcb_entry); | ||||||
|  | @ -2134,7 +2160,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) | ||||||
| 	idx = -1; | 	idx = -1; | ||||||
| 	while ((conn = olddcb_conn(dev, ++idx))) { | 	while ((conn = olddcb_conn(dev, ++idx))) { | ||||||
| 		if (conn[0] != 0xff) { | 		if (conn[0] != 0xff) { | ||||||
| 			NV_TRACE(dev, "DCB conn %02d: ", idx); | 			NV_INFO(drm, "DCB conn %02d: ", idx); | ||||||
| 			if (olddcb_conntab(dev)[3] < 4) | 			if (olddcb_conntab(dev)[3] < 4) | ||||||
| 				printk("%04x\n", ROM16(conn[0])); | 				printk("%04x\n", ROM16(conn[0])); | ||||||
| 			else | 			else | ||||||
|  | @ -2156,12 +2182,14 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio | ||||||
| 	 * starting at reg 0x00001400 | 	 * starting at reg 0x00001400 | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	uint8_t bytes_to_write; | 	uint8_t bytes_to_write; | ||||||
| 	uint16_t hwsq_entry_offset; | 	uint16_t hwsq_entry_offset; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (bios->data[hwsq_offset] <= entry) { | 	if (bios->data[hwsq_offset] <= entry) { | ||||||
| 		NV_ERROR(dev, "Too few entries in HW sequencer table for " | 		NV_ERROR(drm, "Too few entries in HW sequencer table for " | ||||||
| 				"requested entry\n"); | 				"requested entry\n"); | ||||||
| 		return -ENOENT; | 		return -ENOENT; | ||||||
| 	} | 	} | ||||||
|  | @ -2169,24 +2197,24 @@ static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bio | ||||||
| 	bytes_to_write = bios->data[hwsq_offset + 1]; | 	bytes_to_write = bios->data[hwsq_offset + 1]; | ||||||
| 
 | 
 | ||||||
| 	if (bytes_to_write != 36) { | 	if (bytes_to_write != 36) { | ||||||
| 		NV_ERROR(dev, "Unknown HW sequencer entry size\n"); | 		NV_ERROR(drm, "Unknown HW sequencer entry size\n"); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_TRACE(dev, "Loading NV17 power sequencing microcode\n"); | 	NV_INFO(drm, "Loading NV17 power sequencing microcode\n"); | ||||||
| 
 | 
 | ||||||
| 	hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write; | 	hwsq_entry_offset = hwsq_offset + 2 + entry * bytes_to_write; | ||||||
| 
 | 
 | ||||||
| 	/* set sequencer control */ | 	/* set sequencer control */ | ||||||
| 	nv_wr32(dev, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); | 	nv_wr32(device, 0x00001304, ROM32(bios->data[hwsq_entry_offset])); | ||||||
| 	bytes_to_write -= 4; | 	bytes_to_write -= 4; | ||||||
| 
 | 
 | ||||||
| 	/* write ucode */ | 	/* write ucode */ | ||||||
| 	for (i = 0; i < bytes_to_write; i += 4) | 	for (i = 0; i < bytes_to_write; i += 4) | ||||||
| 		nv_wr32(dev, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); | 		nv_wr32(device, 0x00001400 + i, ROM32(bios->data[hwsq_entry_offset + i + 4])); | ||||||
| 
 | 
 | ||||||
| 	/* twiddle NV_PBUS_DEBUG_4 */ | 	/* twiddle NV_PBUS_DEBUG_4 */ | ||||||
| 	nv_wr32(dev, NV_PBUS_DEBUG_4, nv_rd32(dev, NV_PBUS_DEBUG_4) | 0x18); | 	nv_wr32(device, NV_PBUS_DEBUG_4, nv_rd32(device, NV_PBUS_DEBUG_4) | 0x18); | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -2217,8 +2245,8 @@ static int load_nv17_hw_sequencer_ucode(struct drm_device *dev, | ||||||
| 
 | 
 | ||||||
| uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) | uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	const uint8_t edid_sig[] = { | 	const uint8_t edid_sig[] = { | ||||||
| 			0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; | 			0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; | ||||||
| 	uint16_t offset = 0; | 	uint16_t offset = 0; | ||||||
|  | @ -2241,27 +2269,29 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) | ||||||
| 		offset++; | 		offset++; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_TRACE(dev, "Found EDID in BIOS\n"); | 	NV_INFO(drm, "Found EDID in BIOS\n"); | ||||||
| 
 | 
 | ||||||
| 	return bios->fp.edid = &bios->data[offset]; | 	return bios->fp.edid = &bios->data[offset]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool NVInitVBIOS(struct drm_device *dev) | static bool NVInitVBIOS(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 
 | 
 | ||||||
| 	memset(bios, 0, sizeof(struct nvbios)); | 	memset(bios, 0, sizeof(struct nvbios)); | ||||||
| 	spin_lock_init(&bios->lock); | 	spin_lock_init(&bios->lock); | ||||||
| 	bios->dev = dev; | 	bios->dev = dev; | ||||||
| 
 | 
 | ||||||
| 	return _nv_bios(dev, &bios->data, &bios->length); | 	bios->data = nouveau_bios(drm->device)->data; | ||||||
|  | 	bios->length = nouveau_bios(drm->device)->size; | ||||||
|  | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int nouveau_parse_vbios_struct(struct drm_device *dev) | static int nouveau_parse_vbios_struct(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; | 	const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; | ||||||
| 	const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; | 	const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; | ||||||
| 	int offset; | 	int offset; | ||||||
|  | @ -2269,7 +2299,7 @@ static int nouveau_parse_vbios_struct(struct drm_device *dev) | ||||||
| 	offset = findstr(bios->data, bios->length, | 	offset = findstr(bios->data, bios->length, | ||||||
| 					bit_signature, sizeof(bit_signature)); | 					bit_signature, sizeof(bit_signature)); | ||||||
| 	if (offset) { | 	if (offset) { | ||||||
| 		NV_TRACE(dev, "BIT BIOS found\n"); | 		NV_INFO(drm, "BIT BIOS found\n"); | ||||||
| 		bios->type = NVBIOS_BIT; | 		bios->type = NVBIOS_BIT; | ||||||
| 		bios->offset = offset; | 		bios->offset = offset; | ||||||
| 		return parse_bit_structure(bios, offset + 6); | 		return parse_bit_structure(bios, offset + 6); | ||||||
|  | @ -2278,21 +2308,21 @@ static int nouveau_parse_vbios_struct(struct drm_device *dev) | ||||||
| 	offset = findstr(bios->data, bios->length, | 	offset = findstr(bios->data, bios->length, | ||||||
| 					bmp_signature, sizeof(bmp_signature)); | 					bmp_signature, sizeof(bmp_signature)); | ||||||
| 	if (offset) { | 	if (offset) { | ||||||
| 		NV_TRACE(dev, "BMP BIOS found\n"); | 		NV_INFO(drm, "BMP BIOS found\n"); | ||||||
| 		bios->type = NVBIOS_BMP; | 		bios->type = NVBIOS_BMP; | ||||||
| 		bios->offset = offset; | 		bios->offset = offset; | ||||||
| 		return parse_bmp_structure(dev, bios, offset); | 		return parse_bmp_structure(dev, bios, offset); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_ERROR(dev, "No known BIOS signature found\n"); | 	NV_ERROR(drm, "No known BIOS signature found\n"); | ||||||
| 	return -ENODEV; | 	return -ENODEV; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nouveau_run_vbios_init(struct drm_device *dev) | nouveau_run_vbios_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	int i, ret = 0; | 	int i, ret = 0; | ||||||
| 
 | 
 | ||||||
| 	/* Reset the BIOS head to 0. */ | 	/* Reset the BIOS head to 0. */ | ||||||
|  | @ -2306,7 +2336,7 @@ nouveau_run_vbios_init(struct drm_device *dev) | ||||||
| 		bios->fp.lvds_init_run = false; | 		bios->fp.lvds_init_run = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_50) { | 	if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 		for (i = 0; bios->execute && i < bios->dcb.entries; i++) { | 		for (i = 0; bios->execute && i < bios->dcb.entries; i++) { | ||||||
| 			nouveau_bios_run_display_table(dev, 0, 0, | 			nouveau_bios_run_display_table(dev, 0, 0, | ||||||
| 						       &bios->dcb.entry[i], -1); | 						       &bios->dcb.entry[i], -1); | ||||||
|  | @ -2319,10 +2349,10 @@ nouveau_run_vbios_init(struct drm_device *dev) | ||||||
| static bool | static bool | ||||||
| nouveau_bios_posted(struct drm_device *dev) | nouveau_bios_posted(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	unsigned htotal; | 	unsigned htotal; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_50) { | 	if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 		if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && | 		if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && | ||||||
| 		    NVReadVgaCrtc(dev, 0, 0x1a) == 0) | 		    NVReadVgaCrtc(dev, 0, 0x1a) == 0) | ||||||
| 			return false; | 			return false; | ||||||
|  | @ -2341,8 +2371,8 @@ nouveau_bios_posted(struct drm_device *dev) | ||||||
| int | int | ||||||
| nouveau_bios_init(struct drm_device *dev) | nouveau_bios_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (!NVInitVBIOS(dev)) | 	if (!NVInitVBIOS(dev)) | ||||||
|  | @ -2364,12 +2394,10 @@ nouveau_bios_init(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	/* ... unless card isn't POSTed already */ | 	/* ... unless card isn't POSTed already */ | ||||||
| 	if (!nouveau_bios_posted(dev)) { | 	if (!nouveau_bios_posted(dev)) { | ||||||
| 		NV_INFO(dev, "Adaptor not initialised, " | 		NV_INFO(drm, "Adaptor not initialised, " | ||||||
| 			"running VBIOS init tables.\n"); | 			"running VBIOS init tables.\n"); | ||||||
| 		bios->execute = true; | 		bios->execute = true; | ||||||
| 	} | 	} | ||||||
| 	if (nouveau_force_post) |  | ||||||
| 		bios->execute = true; |  | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_run_vbios_init(dev); | 	ret = nouveau_run_vbios_init(dev); | ||||||
| 	if (ret) | 	if (ret) | ||||||
|  |  | ||||||
|  | @ -21,8 +21,8 @@ | ||||||
|  * DEALINGS IN THE SOFTWARE. |  * DEALINGS IN THE SOFTWARE. | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #ifndef __NOUVEAU_BIOS_H__ | #ifndef __NOUVEAU_DISPBIOS_H__ | ||||||
| #define __NOUVEAU_BIOS_H__ | #define __NOUVEAU_DISPBIOS_H__ | ||||||
| 
 | 
 | ||||||
| #include "nvreg.h" | #include "nvreg.h" | ||||||
| 
 | 
 | ||||||
|  | @ -38,8 +38,8 @@ | ||||||
| #define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); }) | #define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); }) | ||||||
| #define ROM64(x) le64_to_cpu(*(u64 *)&(x)) | #define ROM64(x) le64_to_cpu(*(u64 *)&(x)) | ||||||
| #define ROMPTR(d,x) ({            \ | #define ROMPTR(d,x) ({            \ | ||||||
| 	struct drm_nouveau_private *dev_priv = (d)->dev_private; \ | 	struct nouveau_drm *drm = nouveau_drm((d)); \ | ||||||
| 	ROM16(x) ? &dev_priv->vbios.data[ROM16(x)] : NULL; \ | 	ROM16(x) ? &drm->vbios.data[ROM16(x)] : NULL; \ | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| struct bit_entry { | struct bit_entry { | ||||||
|  | @ -180,4 +180,21 @@ int olddcb_outp_foreach(struct drm_device *, void *data, | ||||||
| u8 *olddcb_conntab(struct drm_device *); | u8 *olddcb_conntab(struct drm_device *); | ||||||
| u8 *olddcb_conn(struct drm_device *, u8 idx); | u8 *olddcb_conn(struct drm_device *, u8 idx); | ||||||
| 
 | 
 | ||||||
|  | int nouveau_bios_init(struct drm_device *); | ||||||
|  | void nouveau_bios_takedown(struct drm_device *dev); | ||||||
|  | int nouveau_run_vbios_init(struct drm_device *); | ||||||
|  | struct dcb_connector_table_entry * | ||||||
|  | nouveau_bios_connector_entry(struct drm_device *, int index); | ||||||
|  | int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, | ||||||
|  | 					  struct dcb_output *, int crtc); | ||||||
|  | bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); | ||||||
|  | uint8_t *nouveau_bios_embedded_edid(struct drm_device *); | ||||||
|  | int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, | ||||||
|  | 					 bool *dl, bool *if_is_24bit); | ||||||
|  | int run_tmds_table(struct drm_device *, struct dcb_output *, | ||||||
|  | 			  int head, int pxclk); | ||||||
|  | int call_lvds_script(struct drm_device *, struct dcb_output *, int head, | ||||||
|  | 			    enum LVDS_script, int pxclk); | ||||||
|  | bool bios_encoder_match(struct dcb_output *, u32 hash); | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -49,7 +49,7 @@ static void | ||||||
| nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, | nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, | ||||||
| 			   u32 addr, u32 size, u32 pitch, u32 flags) | 			   u32 addr, u32 size, u32 pitch, u32 flags) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int i = reg - drm->tile.reg; | 	int i = reg - drm->tile.reg; | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | ||||||
| 	struct nouveau_fb_tile *tile = &pfb->tile.region[i]; | 	struct nouveau_fb_tile *tile = &pfb->tile.region[i]; | ||||||
|  | @ -74,7 +74,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, | ||||||
| static struct nouveau_drm_tile * | static struct nouveau_drm_tile * | ||||||
| nv10_bo_get_tile_region(struct drm_device *dev, int i) | nv10_bo_get_tile_region(struct drm_device *dev, int i) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_drm_tile *tile = &drm->tile.reg[i]; | 	struct nouveau_drm_tile *tile = &drm->tile.reg[i]; | ||||||
| 
 | 
 | ||||||
| 	spin_lock(&drm->tile.lock); | 	spin_lock(&drm->tile.lock); | ||||||
|  | @ -93,7 +93,7 @@ static void | ||||||
| nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, | nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, | ||||||
| 			struct nouveau_fence *fence) | 			struct nouveau_fence *fence) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (tile) { | 	if (tile) { | ||||||
| 		spin_lock(&drm->tile.lock); | 		spin_lock(&drm->tile.lock); | ||||||
|  | @ -112,7 +112,7 @@ static struct nouveau_drm_tile * | ||||||
| nv10_bo_set_tiling(struct drm_device *dev, u32 addr, | nv10_bo_set_tiling(struct drm_device *dev, u32 addr, | ||||||
| 		   u32 size, u32 pitch, u32 flags) | 		   u32 size, u32 pitch, u32 flags) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | ||||||
| 	struct nouveau_drm_tile *tile, *found = NULL; | 	struct nouveau_drm_tile *tile, *found = NULL; | ||||||
| 	int i; | 	int i; | ||||||
|  | @ -191,7 +191,7 @@ nouveau_bo_new(struct drm_device *dev, int size, int align, | ||||||
| 	       struct sg_table *sg, | 	       struct sg_table *sg, | ||||||
| 	       struct nouveau_bo **pnvbo) | 	       struct nouveau_bo **pnvbo) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_bo *nvbo; | 	struct nouveau_bo *nvbo; | ||||||
| 	size_t acc_size; | 	size_t acc_size; | ||||||
| 	int ret; | 	int ret; | ||||||
|  |  | ||||||
|  | @ -22,7 +22,8 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| 
 | 
 | ||||||
| /****************************************************************************\
 | /****************************************************************************\
 | ||||||
|  | @ -195,12 +196,13 @@ static void | ||||||
| nv04_update_arb(struct drm_device *dev, int VClk, int bpp, | nv04_update_arb(struct drm_device *dev, int VClk, int bpp, | ||||||
| 		int *burst, int *lwm) | 		int *burst, int *lwm) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nv_fifo_info fifo_data; | 	struct nv_fifo_info fifo_data; | ||||||
| 	struct nv_sim_state sim_data; | 	struct nv_sim_state sim_data; | ||||||
| 	int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY); | 	int MClk = nouveau_hw_get_clock(dev, PLL_MEMORY); | ||||||
| 	int NVClk = nouveau_hw_get_clock(dev, PLL_CORE); | 	int NVClk = nouveau_hw_get_clock(dev, PLL_CORE); | ||||||
| 	uint32_t cfg1 = nv_rd32(dev, NV04_PFB_CFG1); | 	uint32_t cfg1 = nv_rd32(device, NV04_PFB_CFG1); | ||||||
| 
 | 
 | ||||||
| 	sim_data.pclk_khz = VClk; | 	sim_data.pclk_khz = VClk; | ||||||
| 	sim_data.mclk_khz = MClk; | 	sim_data.mclk_khz = MClk; | ||||||
|  | @ -218,13 +220,13 @@ nv04_update_arb(struct drm_device *dev, int VClk, int bpp, | ||||||
| 		sim_data.mem_latency = 3; | 		sim_data.mem_latency = 3; | ||||||
| 		sim_data.mem_page_miss = 10; | 		sim_data.mem_page_miss = 10; | ||||||
| 	} else { | 	} else { | ||||||
| 		sim_data.memory_type = nv_rd32(dev, NV04_PFB_CFG0) & 0x1; | 		sim_data.memory_type = nv_rd32(device, NV04_PFB_CFG0) & 0x1; | ||||||
| 		sim_data.memory_width = (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; | 		sim_data.memory_width = (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x10) ? 128 : 64; | ||||||
| 		sim_data.mem_latency = cfg1 & 0xf; | 		sim_data.mem_latency = cfg1 & 0xf; | ||||||
| 		sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); | 		sim_data.mem_page_miss = ((cfg1 >> 4) & 0xf) + ((cfg1 >> 31) & 0x1); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_04) | 	if (nv_device(drm->device)->card_type == NV_04) | ||||||
| 		nv04_calc_arb(&fifo_data, &sim_data); | 		nv04_calc_arb(&fifo_data, &sim_data); | ||||||
| 	else | 	else | ||||||
| 		nv10_calc_arb(&fifo_data, &sim_data); | 		nv10_calc_arb(&fifo_data, &sim_data); | ||||||
|  | @ -249,9 +251,9 @@ nv20_update_arb(int *burst, int *lwm) | ||||||
| void | void | ||||||
| nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm) | nouveau_calc_arb(struct drm_device *dev, int vclk, int bpp, int *burst, int *lwm) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type < NV_20) | 	if (nv_device(drm->device)->card_type < NV_20) | ||||||
| 		nv04_update_arb(dev, vclk, bpp, burst, lwm); | 		nv04_update_arb(dev, vclk, bpp, burst, lwm); | ||||||
| 	else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || | 	else if ((dev->pci_device & 0xfff0) == 0x0240 /*CHIPSET_C51*/ || | ||||||
| 		 (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { | 		 (dev->pci_device & 0xfff0) == 0x03d0 /*CHIPSET_C512*/) { | ||||||
|  |  | ||||||
|  | @ -1,609 +0,0 @@ | ||||||
| #include "nouveau_drm.h" |  | ||||||
| #include "nouveau_chan.h" |  | ||||||
| #include "nouveau_compat.h" |  | ||||||
| 
 |  | ||||||
| #include <subdev/bios.h> |  | ||||||
| #include <subdev/bios/dcb.h> |  | ||||||
| #include <subdev/bios/init.h> |  | ||||||
| #include <subdev/bios/pll.h> |  | ||||||
| #include <subdev/gpio.h> |  | ||||||
| #include <subdev/i2c.h> |  | ||||||
| #include <subdev/clock.h> |  | ||||||
| #include <subdev/mc.h> |  | ||||||
| #include <subdev/timer.h> |  | ||||||
| #include <subdev/fb.h> |  | ||||||
| #include <subdev/bar.h> |  | ||||||
| #include <subdev/vm.h> |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvdrm_gart_init(struct drm_device *dev, u64 *base, u64 *size) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	if (drm->agp.stat == ENABLED) { |  | ||||||
| 		*base = drm->agp.base; |  | ||||||
| 		*size = drm->agp.base; |  | ||||||
| 		return 0; |  | ||||||
| 	} |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u8 |  | ||||||
| _nv_rd08(struct drm_device *dev, u32 reg) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return nv_ro08(drm->device, reg); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| _nv_wr08(struct drm_device *dev, u32 reg, u8 val) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	nv_wo08(drm->device, reg, val); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 |  | ||||||
| _nv_rd32(struct drm_device *dev, u32 reg) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return nv_ro32(drm->device, reg); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| _nv_wr32(struct drm_device *dev, u32 reg, u32 val) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	nv_wo32(drm->device, reg, val); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 |  | ||||||
| _nv_mask(struct drm_device *dev, u32 reg, u32 mask, u32 val) |  | ||||||
| { |  | ||||||
| 	u32 tmp = _nv_rd32(dev, reg); |  | ||||||
| 	_nv_wr32(dev, reg, (tmp & ~mask) | val); |  | ||||||
| 	return tmp; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool |  | ||||||
| _nv_bios(struct drm_device *dev, u8 **data, u32 *size) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_bios *bios = nouveau_bios(drm->device); |  | ||||||
| 	*data = bios->data; |  | ||||||
| 	*size = bios->size; |  | ||||||
| 	return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_gpio_reset(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	gpio->reset(gpio); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_gpio_find(struct drm_device *dev, int idx, u8 tag, u8 line, |  | ||||||
| 		  struct dcb_gpio_func *func) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 
 |  | ||||||
| 	return gpio->find(gpio, idx, tag, line, func); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool |  | ||||||
| nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	struct dcb_gpio_func func; |  | ||||||
| 
 |  | ||||||
| 	return gpio->find(gpio, 0, tag, 0xff, &func) == 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	if (gpio && gpio->get) |  | ||||||
| 		return gpio->set(gpio, 0, tag, 0xff, state); |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_gpio_func_get(struct drm_device *dev, u8 tag) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	if (gpio && gpio->get) |  | ||||||
| 		return gpio->get(gpio, 0, tag, 0xff); |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	if (gpio && gpio->irq) |  | ||||||
| 		return gpio->irq(gpio, idx, tag, line, on); |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, |  | ||||||
| 		     void (*exec)(void *, int state), void *data) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	if (gpio && gpio->isr_add) |  | ||||||
| 		return gpio->isr_add(gpio, idx, tag, line, exec, data); |  | ||||||
| 	return -ENODEV; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, |  | ||||||
| 		     void (*exec)(void *, int state), void *data) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); |  | ||||||
| 	if (gpio && gpio->isr_del) |  | ||||||
| 		gpio->isr_del(gpio, idx, tag, line, exec, data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_i2c_port * |  | ||||||
| nouveau_i2c_find(struct drm_device *dev, u8 index) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |  | ||||||
| 
 |  | ||||||
| 	return i2c->find(i2c, index); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool |  | ||||||
| nouveau_probe_i2c_addr(struct nouveau_i2c_port *port, int addr) |  | ||||||
| { |  | ||||||
| 	return nv_probe_i2c(port, addr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct i2c_adapter * |  | ||||||
| nouveau_i2c_adapter(struct nouveau_i2c_port *port) |  | ||||||
| { |  | ||||||
| 	return &port->adapter; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_i2c_identify(struct drm_device *dev, const char *what, |  | ||||||
| 		     struct i2c_board_info *info, |  | ||||||
| 		     bool (*match)(struct nouveau_i2c_port *, |  | ||||||
| 			           struct i2c_board_info *), |  | ||||||
| 		     int index) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |  | ||||||
| 
 |  | ||||||
| 	return i2c->identify(i2c, index, what, info, match); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| auxch_rd(struct drm_device *dev, struct nouveau_i2c_port *port, |  | ||||||
| 	 u32 addr, u8 *data, u8 size) |  | ||||||
| { |  | ||||||
| 	return nv_rdaux(port, addr, data, size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| auxch_wr(struct drm_device *dev, struct nouveau_i2c_port *port, |  | ||||||
| 	 u32 addr, u8 *data, u8 size) |  | ||||||
| { |  | ||||||
| 	return nv_wraux(port, addr, data, size); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 |  | ||||||
| get_pll_register(struct drm_device *dev, u32 type) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_bios *bios = nouveau_bios(drm->device); |  | ||||||
| 	struct nvbios_pll info; |  | ||||||
| 
 |  | ||||||
| 	if (nvbios_pll_parse(bios, type, &info)) |  | ||||||
| 		return 0; |  | ||||||
| 	return info.reg; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| get_pll_limits(struct drm_device *dev, u32 type, struct nvbios_pll *info) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_bios *bios = nouveau_bios(drm->device); |  | ||||||
| 
 |  | ||||||
| 	return nvbios_pll_parse(bios, type, info); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| setPLL(struct drm_device *dev, u32 reg, u32 freq) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_clock *clk = nouveau_clock(drm->device); |  | ||||||
| 	int ret = -ENODEV; |  | ||||||
| 
 |  | ||||||
| 	if (clk->pll_set) |  | ||||||
| 		ret = clk->pll_set(clk, reg, freq); |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_calc_pll_mnp(struct drm_device *dev, struct nvbios_pll *info, |  | ||||||
| 		     int freq, struct nouveau_pll_vals *pv) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_clock *clk = nouveau_clock(drm->device); |  | ||||||
| 	int ret = 0; |  | ||||||
| 
 |  | ||||||
| 	if (clk->pll_calc) |  | ||||||
| 		ret = clk->pll_calc(clk, info, freq, pv); |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_hw_setpll(struct drm_device *dev, u32 reg1, |  | ||||||
| 		  struct nouveau_pll_vals *pv) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_clock *clk = nouveau_clock(drm->device); |  | ||||||
| 	int ret = -ENODEV; |  | ||||||
| 
 |  | ||||||
| 	if (clk->pll_prog) |  | ||||||
| 		ret = clk->pll_prog(clk, reg1, pv); |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int nva3_pll_calc(struct nouveau_clock *, struct nvbios_pll *, u32 freq, |  | ||||||
| 		  int *N, int *fN, int *M, int *P); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, |  | ||||||
| 	      int *N, int *fN, int *M, int *P) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_clock *clk = nouveau_clock(drm->device); |  | ||||||
| 
 |  | ||||||
| 	return nva3_pll_calc(clk, info, freq, N, fN, M, P); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, |  | ||||||
| 			    struct dcb_output *dcbent, int crtc) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_bios *bios = nouveau_bios(drm->device); |  | ||||||
| 	struct nvbios_init init = { |  | ||||||
| 		.subdev = nv_subdev(bios), |  | ||||||
| 		.bios = bios, |  | ||||||
| 		.offset = table, |  | ||||||
| 		.outp = dcbent, |  | ||||||
| 		.crtc = crtc, |  | ||||||
| 		.execute = 1 |  | ||||||
| 	}; |  | ||||||
| 
 |  | ||||||
| 	nvbios_exec(&init); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_bios_init_exec(struct drm_device *dev, uint16_t table) |  | ||||||
| { |  | ||||||
| 	nouveau_bios_run_init_table(dev, table, NULL, 0); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nv_intr(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_mc *pmc = nouveau_mc(drm->device); |  | ||||||
| 	nv_subdev(pmc)->intr(&pmc->base); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool nouveau_wait_eq(struct drm_device *dev, uint64_t timeout, |  | ||||||
| 			    uint32_t reg, uint32_t mask, uint32_t val) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return nouveau_timer_wait_eq(drm->device, timeout, reg, mask, val); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool nouveau_wait_ne(struct drm_device *dev, uint64_t timeout, |  | ||||||
| 			    uint32_t reg, uint32_t mask, uint32_t val) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return nouveau_timer_wait_ne(drm->device, timeout, reg, mask, val); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool nouveau_wait_cb(struct drm_device *dev, u64 timeout, |  | ||||||
| 			    bool (*cond)(void *), void *data) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return nouveau_timer_wait_cb(drm->device, timeout, cond, data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u64 |  | ||||||
| nv_timer_read(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_timer *ptimer = nouveau_timer(drm->device); |  | ||||||
| 	return ptimer->read(ptimer); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvfb_tile_nr(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return pfb->tile.regions; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_fb_tile * |  | ||||||
| nvfb_tile(struct drm_device *dev, int i) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return &pfb->tile.region[i]; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvfb_tile_init(struct drm_device *dev, int i, u32 a, u32 b, u32 c, u32 d) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	pfb->tile.init(pfb, i, a, b, c, d, &pfb->tile.region[i]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvfb_tile_fini(struct drm_device *dev, int i) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	pfb->tile.fini(pfb, i, &pfb->tile.region[i]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvfb_tile_prog(struct drm_device *dev, int i) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	pfb->tile.prog(pfb, i, &pfb->tile.region[i]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| bool |  | ||||||
| nvfb_flags_valid(struct drm_device *dev, u32 flags) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return pfb->memtype_valid(pfb, flags); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, |  | ||||||
| 	      u32 memtype, struct nouveau_mem **pmem) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	int ret = pfb->ram.get(pfb, size, align, ncmin, memtype, pmem); |  | ||||||
| 	if (ret) |  | ||||||
| 		return ret; |  | ||||||
| 	(*pmem)->dev = dev; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	pfb->ram.put(pfb, pmem); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| u64 nvfb_vram_sys_base(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return pfb->ram.stolen; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u64 nvfb_vram_size(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return pfb->ram.size; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int nvfb_vram_type(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return pfb->ram.type; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int nvfb_vram_rank_B(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); |  | ||||||
| 	return pfb->ram.ranks > 1; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nv50_fb_vm_trap(struct drm_device *dev, int disp) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	nv50_fb_trap(nouveau_fb(drm->device), disp); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #include <core/subdev/instmem/nv04.h> |  | ||||||
| 
 |  | ||||||
| struct nouveau_gpuobj * |  | ||||||
| nvimem_ramro(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nv04_instmem_priv *imem = (void *)nouveau_instmem(drm->device); |  | ||||||
| 	return imem->ramro; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_gpuobj * |  | ||||||
| nvimem_ramfc(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nv04_instmem_priv *imem = (void *)nouveau_instmem(drm->device); |  | ||||||
| 	return imem->ramfc; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int _nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_gpuobj *par, |  | ||||||
| 			int size, int align, u32 flags, |  | ||||||
| 			struct nouveau_gpuobj **pobj) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	if (!par) |  | ||||||
| 		flags |= NVOBJ_FLAG_HEAP; |  | ||||||
| 
 |  | ||||||
| 	ret = nouveau_gpuobj_new(drm->device, nv_object(par), size, align, |  | ||||||
| 				 flags, pobj); |  | ||||||
| 	if (ret) |  | ||||||
| 		return ret; |  | ||||||
| 
 |  | ||||||
| 	(*pobj)->dev = dev; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 nv_ri32(struct drm_device *dev , u32 addr) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_instmem *imem = nouveau_instmem(drm->device); |  | ||||||
| 	return nv_ro32(imem, addr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void nv_wi32(struct drm_device *dev, u32 addr, u32 data) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_instmem *imem = nouveau_instmem(drm->device); |  | ||||||
| 	nv_wo32(imem, addr, data); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u32 nvimem_reserved(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_instmem *imem = nouveau_instmem(drm->device); |  | ||||||
| 	return imem->reserved; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvbar_map(struct drm_device *dev, struct nouveau_mem *mem, u32 flags, |  | ||||||
| 	  struct nouveau_vma *vma) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_bar *bar = nouveau_bar(drm->device); |  | ||||||
| 	return bar->umap(bar, mem, flags, vma); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvbar_unmap(struct drm_device *dev, struct nouveau_vma *vma) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_bar *bar = nouveau_bar(drm->device); |  | ||||||
| 	bar->unmap(bar, vma); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_gpuobj_map_bar(struct nouveau_gpuobj *gpuobj, u32 flags, |  | ||||||
| 		       struct nouveau_vma *vma) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(gpuobj->dev); |  | ||||||
| 	struct nouveau_bar *bar = nouveau_bar(drm->device); |  | ||||||
| 	struct nouveau_instobj *iobj = (void *) |  | ||||||
| 		nv_pclass(nv_object(gpuobj), NV_MEMOBJ_CLASS); |  | ||||||
| 	struct nouveau_mem **mem = (void *)(iobj + 1); |  | ||||||
| 	struct nouveau_mem *node = *mem; |  | ||||||
| 
 |  | ||||||
| 	return bar->umap(bar, node, flags, vma); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvimem_flush(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void _nv50_vm_flush_engine(struct drm_device *dev, int engine) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	nv50_vm_flush_engine(nv_subdev(drm->device), engine); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int _nouveau_vm_new(struct drm_device *dev, u64 offset, u64 length, |  | ||||||
| 		    u64 mm_offset, struct nouveau_vm **pvm) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return nouveau_vm_new(nv_device(drm->device), offset, length, mm_offset, pvm); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #include <core/subdev/vm/nv04.h> |  | ||||||
| struct nouveau_vm * |  | ||||||
| nv04vm_ref(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	struct nouveau_vmmgr *vmm = nouveau_vmmgr(drm->device); |  | ||||||
| 	struct nv04_vmmgr_priv *priv = (void *)vmm; |  | ||||||
| 	return priv->vm; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_gpuobj * |  | ||||||
| nv04vm_refdma(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_gpuobj *gpuobj = NULL; |  | ||||||
| 	nouveau_gpuobj_ref(nv04vm_ref(dev)->pgt[0].obj[0], &gpuobj); |  | ||||||
| 	return gpuobj; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvvm_engref(struct nouveau_vm *vm, int eng, int ref) |  | ||||||
| { |  | ||||||
| 	atomic_add(ref, &vm->engref[eng]); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvvm_spg_shift(struct nouveau_vm *vm) |  | ||||||
| { |  | ||||||
| 	return vm->vmm->spg_shift; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvvm_lpg_shift(struct nouveau_vm *vm) |  | ||||||
| { |  | ||||||
| 	return vm->vmm->lpg_shift; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| u64 nvgpuobj_addr(struct nouveau_object *object) |  | ||||||
| { |  | ||||||
| 	return nv_gpuobj(object)->addr; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct drm_device * |  | ||||||
| nouveau_drv(void *ptr) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = ptr; |  | ||||||
| 	return drm->dev; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_channel * |  | ||||||
| nvdrm_channel(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); |  | ||||||
| 	return drm->channel; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct mutex * |  | ||||||
| nvchan_mutex(struct nouveau_channel *chan) |  | ||||||
| { |  | ||||||
| 	return &chan->cli->mutex; |  | ||||||
| } |  | ||||||
|  | @ -1,141 +0,0 @@ | ||||||
| #ifndef __NOUVEAU_COMPAT_H__ |  | ||||||
| #define __NOUVEAU_COMPAT_H__ |  | ||||||
| 
 |  | ||||||
| int nvdrm_gart_init(struct drm_device *, u64 *, u64 *); |  | ||||||
| 
 |  | ||||||
| u8   _nv_rd08(struct drm_device *, u32); |  | ||||||
| void _nv_wr08(struct drm_device *, u32, u8); |  | ||||||
| u32  _nv_rd32(struct drm_device *, u32); |  | ||||||
| void _nv_wr32(struct drm_device *, u32, u32); |  | ||||||
| u32  _nv_mask(struct drm_device *, u32, u32, u32); |  | ||||||
| 
 |  | ||||||
| bool _nv_bios(struct drm_device *, u8 **, u32 *); |  | ||||||
| 
 |  | ||||||
| struct dcb_gpio_func; |  | ||||||
| void nouveau_gpio_reset(struct drm_device *); |  | ||||||
| int  nouveau_gpio_find(struct drm_device *, int, u8, u8, struct dcb_gpio_func *); |  | ||||||
| bool nouveau_gpio_func_valid(struct drm_device *, u8 tag); |  | ||||||
| int  nouveau_gpio_func_set(struct drm_device *, u8 tag, int state); |  | ||||||
| int  nouveau_gpio_func_get(struct drm_device *, u8 tag); |  | ||||||
| int  nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); |  | ||||||
| int  nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, |  | ||||||
| 			  void (*)(void *, int state), void *data); |  | ||||||
| void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, |  | ||||||
| 			  void (*)(void *, int state), void *data); |  | ||||||
| 
 |  | ||||||
| struct nouveau_i2c_port *nouveau_i2c_find(struct drm_device *, u8); |  | ||||||
| bool nouveau_probe_i2c_addr(struct nouveau_i2c_port *, int addr); |  | ||||||
| struct i2c_adapter *nouveau_i2c_adapter(struct nouveau_i2c_port *); |  | ||||||
| int nouveau_i2c_identify(struct drm_device *dev, const char *what, |  | ||||||
| 			 struct i2c_board_info *info, |  | ||||||
| 			 bool (*match)(struct nouveau_i2c_port *, |  | ||||||
| 				       struct i2c_board_info *), int index); |  | ||||||
| 
 |  | ||||||
| int auxch_rd(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); |  | ||||||
| int auxch_wr(struct drm_device *, struct nouveau_i2c_port *, u32, u8 *, u8); |  | ||||||
| 
 |  | ||||||
| struct nvbios_pll; |  | ||||||
| struct nouveau_pll_vals; |  | ||||||
| 
 |  | ||||||
| u32 get_pll_register(struct drm_device *dev, u32 type); |  | ||||||
| int get_pll_limits(struct drm_device *, u32, struct nvbios_pll *); |  | ||||||
| int setPLL(struct drm_device *, u32 reg, u32 clk); |  | ||||||
| 
 |  | ||||||
| int nouveau_calc_pll_mnp(struct drm_device *, struct nvbios_pll *, |  | ||||||
| 			 int, struct nouveau_pll_vals *); |  | ||||||
| int nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *info, u32 freq, |  | ||||||
| 	      int *N, int *fN, int *M, int *P); |  | ||||||
| int nouveau_hw_setpll(struct drm_device *, u32, struct nouveau_pll_vals *); |  | ||||||
| 
 |  | ||||||
| struct dcb_output; |  | ||||||
| void nouveau_bios_run_init_table(struct drm_device *, u16, struct dcb_output *, int); |  | ||||||
| void nouveau_bios_init_exec(struct drm_device *, u16); |  | ||||||
| 
 |  | ||||||
| void nv_intr(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| bool nouveau_wait_eq(struct drm_device *, uint64_t timeout, |  | ||||||
| 			    uint32_t reg, uint32_t mask, uint32_t val); |  | ||||||
| bool nouveau_wait_ne(struct drm_device *, uint64_t timeout, |  | ||||||
| 			    uint32_t reg, uint32_t mask, uint32_t val); |  | ||||||
| bool nouveau_wait_cb(struct drm_device *, u64 timeout, |  | ||||||
| 			    bool (*cond)(void *), void *); |  | ||||||
| 
 |  | ||||||
| u64 nv_timer_read(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| int  nvfb_tile_nr(struct drm_device *); |  | ||||||
| void nvfb_tile_init(struct drm_device *, int, u32, u32, u32, u32); |  | ||||||
| void nvfb_tile_fini(struct drm_device *, int); |  | ||||||
| void nvfb_tile_prog(struct drm_device *, int); |  | ||||||
| 
 |  | ||||||
| struct nouveau_fb_tile *nvfb_tile(struct drm_device *, int); |  | ||||||
| 
 |  | ||||||
| struct nouveau_mem; |  | ||||||
| int nvfb_vram_get(struct drm_device *dev, u64 size, u32 align, u32 ncmin, |  | ||||||
| 		  u32 memtype, struct nouveau_mem **pmem); |  | ||||||
| void nvfb_vram_put(struct drm_device *dev, struct nouveau_mem **pmem); |  | ||||||
| bool nvfb_flags_valid(struct drm_device *dev, u32); |  | ||||||
| 
 |  | ||||||
| u64 nvfb_vram_sys_base(struct drm_device *); |  | ||||||
| u64 nvfb_vram_size(struct drm_device *); |  | ||||||
| int nvfb_vram_type(struct drm_device *); |  | ||||||
| int nvfb_vram_rank_B(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| void nv50_fb_vm_trap(struct drm_device *, int); |  | ||||||
| 
 |  | ||||||
| struct nouveau_gpuobj *nvimem_ramro(struct drm_device *); |  | ||||||
| struct nouveau_gpuobj *nvimem_ramfc(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| int _nouveau_gpuobj_new(struct drm_device *dev, struct nouveau_gpuobj *par, |  | ||||||
| 			int size, int align, u32 flags, |  | ||||||
| 			struct nouveau_gpuobj **pboj); |  | ||||||
| 
 |  | ||||||
| u32 nv_ri32(struct drm_device *, u32); |  | ||||||
| void nv_wi32(struct drm_device *, u32, u32); |  | ||||||
| u32 nvimem_reserved(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| void nvimem_flush(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| void _nv50_vm_flush_engine(struct drm_device *dev, int engine); |  | ||||||
| 
 |  | ||||||
| int _nouveau_vm_new(struct drm_device *, u64 offset, u64 length, |  | ||||||
| 		    u64 mm_offset, struct nouveau_vm **); |  | ||||||
| 
 |  | ||||||
| struct nouveau_vma; |  | ||||||
| int nouveau_gpuobj_map_bar(struct nouveau_gpuobj *, u32, struct nouveau_vma *); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvbar_map(struct drm_device *dev, struct nouveau_mem *mem, u32 flags, |  | ||||||
| 	  struct nouveau_vma *vma); |  | ||||||
| void |  | ||||||
| nvbar_unmap(struct drm_device *dev, struct nouveau_vma *vma); |  | ||||||
| 
 |  | ||||||
| struct nouveau_vm * |  | ||||||
| nv04vm_ref(struct drm_device *dev); |  | ||||||
| 
 |  | ||||||
| struct nouveau_gpuobj * |  | ||||||
| nv04vm_refdma(struct drm_device *dev); |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nvvm_engref(struct nouveau_vm *, int, int); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvvm_spg_shift(struct nouveau_vm *); |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nvvm_lpg_shift(struct nouveau_vm *); |  | ||||||
| 
 |  | ||||||
| u32 |  | ||||||
| nv50_display_active_crtcs(struct drm_device *dev); |  | ||||||
| 
 |  | ||||||
| u64 nvgpuobj_addr(struct nouveau_object *object); |  | ||||||
| 
 |  | ||||||
| struct drm_device * |  | ||||||
| nouveau_drv(void *drm); |  | ||||||
| 
 |  | ||||||
| struct nouveau_channel * |  | ||||||
| nvdrm_channel(struct drm_device *dev); |  | ||||||
| 
 |  | ||||||
| struct mutex * |  | ||||||
| nvchan_mutex(struct nouveau_channel *chan); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
|  | @ -31,14 +31,29 @@ | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_reg.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_encoder.h" |  | ||||||
| #include "nouveau_crtc.h" |  | ||||||
| #include "nouveau_connector.h" |  | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_acpi.h" | #include "nouveau_acpi.h" | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/gpio.h> | #include "nouveau_display.h" | ||||||
|  | #include "nouveau_connector.h" | ||||||
|  | #include "nouveau_encoder.h" | ||||||
|  | #include "nouveau_crtc.h" | ||||||
|  | 
 | ||||||
|  | #include <subdev/i2c.h> | ||||||
|  | #include <subdev/gpio.h> | ||||||
|  | 
 | ||||||
|  | MODULE_PARM_DESC(tv_disable, "Disable TV-out detection"); | ||||||
|  | static int nouveau_tv_disable = 0; | ||||||
|  | module_param_named(tv_disable, nouveau_tv_disable, int, 0400); | ||||||
|  | 
 | ||||||
|  | MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); | ||||||
|  | static int nouveau_ignorelid = 0; | ||||||
|  | module_param_named(ignorelid, nouveau_ignorelid, int, 0400); | ||||||
|  | 
 | ||||||
|  | MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (default: enabled)"); | ||||||
|  | static int nouveau_duallink = 1; | ||||||
|  | module_param_named(duallink, nouveau_duallink, int, 0400); | ||||||
| 
 | 
 | ||||||
| static void nouveau_connector_hotplug(void *, int); | static void nouveau_connector_hotplug(void *, int); | ||||||
| 
 | 
 | ||||||
|  | @ -85,18 +100,20 @@ static void | ||||||
| nouveau_connector_destroy(struct drm_connector *connector) | nouveau_connector_destroy(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct drm_nouveau_private *dev_priv; | 	struct nouveau_gpio *gpio; | ||||||
|  | 	struct nouveau_drm *drm; | ||||||
| 	struct drm_device *dev; | 	struct drm_device *dev; | ||||||
| 
 | 
 | ||||||
| 	if (!nv_connector) | 	if (!nv_connector) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	dev  = nv_connector->base.dev; | 	dev  = nv_connector->base.dev; | ||||||
| 	dev_priv = dev->dev_private; | 	drm  = nouveau_drm(dev); | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	gpio = nouveau_gpio(drm->device); | ||||||
|  | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (nv_connector->hpd != DCB_GPIO_UNUSED) { | 	if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { | ||||||
| 		nouveau_gpio_isr_del(dev, 0, nv_connector->hpd, 0xff, | 		gpio->isr_del(gpio, 0, nv_connector->hpd, 0xff, | ||||||
| 			      nouveau_connector_hotplug, connector); | 			      nouveau_connector_hotplug, connector); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -111,10 +128,12 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | ||||||
| 			     struct nouveau_encoder **pnv_encoder) | 			     struct nouveau_encoder **pnv_encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||||||
| 		struct nouveau_i2c_port *i2c = NULL; | 		struct nouveau_i2c_port *port = NULL; | ||||||
| 		struct nouveau_encoder *nv_encoder; | 		struct nouveau_encoder *nv_encoder; | ||||||
| 		struct drm_mode_object *obj; | 		struct drm_mode_object *obj; | ||||||
| 		int id; | 		int id; | ||||||
|  | @ -129,11 +148,10 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | ||||||
| 		nv_encoder = nouveau_encoder(obj_to_encoder(obj)); | 		nv_encoder = nouveau_encoder(obj_to_encoder(obj)); | ||||||
| 
 | 
 | ||||||
| 		if (nv_encoder->dcb->i2c_index < 0xf) | 		if (nv_encoder->dcb->i2c_index < 0xf) | ||||||
| 			i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | 			port = i2c->find(i2c, nv_encoder->dcb->i2c_index); | ||||||
| 
 | 		if (port && nv_probe_i2c(port, 0x50)) { | ||||||
| 		if (i2c && nouveau_probe_i2c_addr(i2c, 0x50)) { |  | ||||||
| 			*pnv_encoder = nv_encoder; | 			*pnv_encoder = nv_encoder; | ||||||
| 			return i2c; | 			return port; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -175,14 +193,14 @@ nouveau_connector_set_encoder(struct drm_connector *connector, | ||||||
| 			      struct nouveau_encoder *nv_encoder) | 			      struct nouveau_encoder *nv_encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
| 
 | 
 | ||||||
| 	if (nv_connector->detected_encoder == nv_encoder) | 	if (nv_connector->detected_encoder == nv_encoder) | ||||||
| 		return; | 		return; | ||||||
| 	nv_connector->detected_encoder = nv_encoder; | 	nv_connector->detected_encoder = nv_encoder; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_50) { | 	if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 		connector->interlace_allowed = true; | 		connector->interlace_allowed = true; | ||||||
| 		connector->doublescan_allowed = true; | 		connector->doublescan_allowed = true; | ||||||
| 	} else | 	} else | ||||||
|  | @ -192,8 +210,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector, | ||||||
| 		connector->interlace_allowed = false; | 		connector->interlace_allowed = false; | ||||||
| 	} else { | 	} else { | ||||||
| 		connector->doublescan_allowed = true; | 		connector->doublescan_allowed = true; | ||||||
| 		if (dev_priv->card_type == NV_20 || | 		if (nv_device(drm->device)->card_type == NV_20 || | ||||||
| 		   (dev_priv->card_type == NV_10 && | 		   (nv_device(drm->device)->card_type == NV_10 && | ||||||
| 		    (dev->pci_device & 0x0ff0) != 0x0100 && | 		    (dev->pci_device & 0x0ff0) != 0x0100 && | ||||||
| 		    (dev->pci_device & 0x0ff0) != 0x0150)) | 		    (dev->pci_device & 0x0ff0) != 0x0150)) | ||||||
| 			/* HW is broken */ | 			/* HW is broken */ | ||||||
|  | @ -215,6 +233,7 @@ static enum drm_connector_status | ||||||
| nouveau_connector_detect(struct drm_connector *connector, bool force) | nouveau_connector_detect(struct drm_connector *connector, bool force) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct nouveau_encoder *nv_encoder = NULL; | 	struct nouveau_encoder *nv_encoder = NULL; | ||||||
| 	struct nouveau_encoder *nv_partner; | 	struct nouveau_encoder *nv_partner; | ||||||
|  | @ -230,18 +249,18 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | ||||||
| 
 | 
 | ||||||
| 	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); | 	i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); | ||||||
| 	if (i2c) { | 	if (i2c) { | ||||||
| 		nv_connector->edid = drm_get_edid(connector, nouveau_i2c_adapter(i2c)); | 		nv_connector->edid = drm_get_edid(connector, &i2c->adapter); | ||||||
| 		drm_mode_connector_update_edid_property(connector, | 		drm_mode_connector_update_edid_property(connector, | ||||||
| 							nv_connector->edid); | 							nv_connector->edid); | ||||||
| 		if (!nv_connector->edid) { | 		if (!nv_connector->edid) { | ||||||
| 			NV_ERROR(dev, "DDC responded, but no EDID for %s\n", | 			NV_ERROR(drm, "DDC responded, but no EDID for %s\n", | ||||||
| 				 drm_get_connector_name(connector)); | 				 drm_get_connector_name(connector)); | ||||||
| 			goto detect_analog; | 			goto detect_analog; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP && | 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP && | ||||||
| 		    !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { | 		    !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { | ||||||
| 			NV_ERROR(dev, "Detected %s, but failed init\n", | 			NV_ERROR(drm, "Detected %s, but failed init\n", | ||||||
| 				 drm_get_connector_name(connector)); | 				 drm_get_connector_name(connector)); | ||||||
| 			return connector_status_disconnected; | 			return connector_status_disconnected; | ||||||
| 		} | 		} | ||||||
|  | @ -303,7 +322,7 @@ static enum drm_connector_status | ||||||
| nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct nouveau_encoder *nv_encoder = NULL; | 	struct nouveau_encoder *nv_encoder = NULL; | ||||||
| 	enum drm_connector_status status = connector_status_disconnected; | 	enum drm_connector_status status = connector_status_disconnected; | ||||||
|  | @ -320,7 +339,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | ||||||
| 		return connector_status_disconnected; | 		return connector_status_disconnected; | ||||||
| 
 | 
 | ||||||
| 	/* Try retrieving EDID via DDC */ | 	/* Try retrieving EDID via DDC */ | ||||||
| 	if (!dev_priv->vbios.fp_no_ddc) { | 	if (!drm->vbios.fp_no_ddc) { | ||||||
| 		status = nouveau_connector_detect(connector, force); | 		status = nouveau_connector_detect(connector, force); | ||||||
| 		if (status == connector_status_connected) | 		if (status == connector_status_connected) | ||||||
| 			goto out; | 			goto out; | ||||||
|  | @ -346,7 +365,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | ||||||
| 	 * modeline is avalilable for the panel, set it as the panel's | 	 * modeline is avalilable for the panel, set it as the panel's | ||||||
| 	 * native mode and exit. | 	 * native mode and exit. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (nouveau_bios_fp_mode(dev, NULL) && (dev_priv->vbios.fp_no_ddc || | 	if (nouveau_bios_fp_mode(dev, NULL) && (drm->vbios.fp_no_ddc || | ||||||
| 	    nv_encoder->dcb->lvdsconf.use_straps_for_mode)) { | 	    nv_encoder->dcb->lvdsconf.use_straps_for_mode)) { | ||||||
| 		status = connector_status_connected; | 		status = connector_status_connected; | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -355,7 +374,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | ||||||
| 	/* Still nothing, some VBIOS images have a hardcoded EDID block
 | 	/* Still nothing, some VBIOS images have a hardcoded EDID block
 | ||||||
| 	 * stored for the panel stored in them. | 	 * stored for the panel stored in them. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (!dev_priv->vbios.fp_no_ddc) { | 	if (!drm->vbios.fp_no_ddc) { | ||||||
| 		struct edid *edid = | 		struct edid *edid = | ||||||
| 			(struct edid *)nouveau_bios_embedded_edid(dev); | 			(struct edid *)nouveau_bios_embedded_edid(dev); | ||||||
| 		if (edid) { | 		if (edid) { | ||||||
|  | @ -381,6 +400,7 @@ out: | ||||||
| static void | static void | ||||||
| nouveau_connector_force(struct drm_connector *connector) | nouveau_connector_force(struct drm_connector *connector) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct nouveau_encoder *nv_encoder; | 	struct nouveau_encoder *nv_encoder; | ||||||
| 	int type; | 	int type; | ||||||
|  | @ -395,7 +415,7 @@ nouveau_connector_force(struct drm_connector *connector) | ||||||
| 
 | 
 | ||||||
| 	nv_encoder = find_encoder(connector, type); | 	nv_encoder = find_encoder(connector, type); | ||||||
| 	if (!nv_encoder) { | 	if (!nv_encoder) { | ||||||
| 		NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", | 		NV_ERROR(drm, "can't find encoder to force %s on!\n", | ||||||
| 			 drm_get_connector_name(connector)); | 			 drm_get_connector_name(connector)); | ||||||
| 		connector->status = connector_status_disconnected; | 		connector->status = connector_status_disconnected; | ||||||
| 		return; | 		return; | ||||||
|  | @ -408,8 +428,7 @@ static int | ||||||
| nouveau_connector_set_property(struct drm_connector *connector, | nouveau_connector_set_property(struct drm_connector *connector, | ||||||
| 			       struct drm_property *property, uint64_t value) | 			       struct drm_property *property, uint64_t value) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 	struct nouveau_display *disp = nouveau_display(connector->dev); | ||||||
| 	struct nouveau_display_engine *disp = &dev_priv->engine.display; |  | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | ||||||
| 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||||||
|  | @ -545,6 +564,7 @@ static struct drm_display_mode * | ||||||
| nouveau_connector_native_mode(struct drm_connector *connector) | nouveau_connector_native_mode(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_connector_helper_funcs *helper = connector->helper_private; | 	struct drm_connector_helper_funcs *helper = connector->helper_private; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
| 	struct drm_display_mode *mode, *largest = NULL; | 	struct drm_display_mode *mode, *largest = NULL; | ||||||
|  | @ -558,7 +578,7 @@ nouveau_connector_native_mode(struct drm_connector *connector) | ||||||
| 
 | 
 | ||||||
| 		/* Use preferred mode if there is one.. */ | 		/* Use preferred mode if there is one.. */ | ||||||
| 		if (mode->type & DRM_MODE_TYPE_PREFERRED) { | 		if (mode->type & DRM_MODE_TYPE_PREFERRED) { | ||||||
| 			NV_DEBUG_KMS(dev, "native mode from preferred\n"); | 			NV_DEBUG(drm, "native mode from preferred\n"); | ||||||
| 			return drm_mode_duplicate(dev, mode); | 			return drm_mode_duplicate(dev, mode); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -581,7 +601,7 @@ nouveau_connector_native_mode(struct drm_connector *connector) | ||||||
| 		largest = mode; | 		largest = mode; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "native mode from largest: %dx%d@%d\n", | 	NV_DEBUG(drm, "native mode from largest: %dx%d@%d\n", | ||||||
| 		      high_w, high_h, high_v); | 		      high_w, high_h, high_v); | ||||||
| 	return largest ? drm_mode_duplicate(dev, largest) : NULL; | 	return largest ? drm_mode_duplicate(dev, largest) : NULL; | ||||||
| } | } | ||||||
|  | @ -645,10 +665,10 @@ nouveau_connector_scaler_modes_add(struct drm_connector *connector) | ||||||
| static void | static void | ||||||
| nouveau_connector_detect_depth(struct drm_connector *connector) | nouveau_connector_detect_depth(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	struct drm_display_mode *mode = nv_connector->native_mode; | 	struct drm_display_mode *mode = nv_connector->native_mode; | ||||||
| 	bool duallink; | 	bool duallink; | ||||||
| 
 | 
 | ||||||
|  | @ -695,7 +715,7 @@ static int | ||||||
| nouveau_connector_get_modes(struct drm_connector *connector) | nouveau_connector_get_modes(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 	struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | ||||||
| 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 	struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||||||
|  | @ -713,7 +733,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | ||||||
| 	else | 	else | ||||||
| 	if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS && | 	if (nv_encoder->dcb->type == DCB_OUTPUT_LVDS && | ||||||
| 	    (nv_encoder->dcb->lvdsconf.use_straps_for_mode || | 	    (nv_encoder->dcb->lvdsconf.use_straps_for_mode || | ||||||
| 	     dev_priv->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { | 	     drm->vbios.fp_no_ddc) && nouveau_bios_fp_mode(dev, NULL)) { | ||||||
| 		struct drm_display_mode mode; | 		struct drm_display_mode mode; | ||||||
| 
 | 
 | ||||||
| 		nouveau_bios_fp_mode(dev, &mode); | 		nouveau_bios_fp_mode(dev, &mode); | ||||||
|  | @ -763,15 +783,15 @@ static unsigned | ||||||
| get_tmds_link_bandwidth(struct drm_connector *connector) | get_tmds_link_bandwidth(struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | 	struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||||||
| 	struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(connector->dev); | ||||||
| 	struct dcb_output *dcb = nv_connector->detected_encoder->dcb; | 	struct dcb_output *dcb = nv_connector->detected_encoder->dcb; | ||||||
| 
 | 
 | ||||||
| 	if (dcb->location != DCB_LOC_ON_CHIP || | 	if (dcb->location != DCB_LOC_ON_CHIP || | ||||||
| 	    dev_priv->chipset >= 0x46) | 	    nv_device(drm->device)->chipset >= 0x46) | ||||||
| 		return 165000; | 		return 165000; | ||||||
| 	else if (dev_priv->chipset >= 0x40) | 	else if (nv_device(drm->device)->chipset >= 0x40) | ||||||
| 		return 155000; | 		return 155000; | ||||||
| 	else if (dev_priv->chipset >= 0x18) | 	else if (nv_device(drm->device)->chipset >= 0x18) | ||||||
| 		return 135000; | 		return 135000; | ||||||
| 	else | 	else | ||||||
| 		return 112000; | 		return 112000; | ||||||
|  | @ -901,14 +921,15 @@ struct drm_connector * | ||||||
| nouveau_connector_create(struct drm_device *dev, int index) | nouveau_connector_create(struct drm_device *dev, int index) | ||||||
| { | { | ||||||
| 	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; | 	const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_display_engine *disp = &dev_priv->engine.display; | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
|  | 	struct nouveau_display *disp = nouveau_display(dev); | ||||||
| 	struct nouveau_connector *nv_connector = NULL; | 	struct nouveau_connector *nv_connector = NULL; | ||||||
| 	struct drm_connector *connector; | 	struct drm_connector *connector; | ||||||
| 	int type, ret = 0; | 	int type, ret = 0; | ||||||
| 	bool dummy; | 	bool dummy; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||||||
| 		nv_connector = nouveau_connector(connector); | 		nv_connector = nouveau_connector(connector); | ||||||
|  | @ -941,7 +962,7 @@ nouveau_connector_create(struct drm_device *dev, int index) | ||||||
| 		nv_connector->type = nv_connector->dcb[0]; | 		nv_connector->type = nv_connector->dcb[0]; | ||||||
| 		if (drm_conntype_from_dcb(nv_connector->type) == | 		if (drm_conntype_from_dcb(nv_connector->type) == | ||||||
| 					  DRM_MODE_CONNECTOR_Unknown) { | 					  DRM_MODE_CONNECTOR_Unknown) { | ||||||
| 			NV_WARN(dev, "unknown connector type %02x\n", | 			NV_WARN(drm, "unknown connector type %02x\n", | ||||||
| 				nv_connector->type); | 				nv_connector->type); | ||||||
| 			nv_connector->type = DCB_CONNECTOR_NONE; | 			nv_connector->type = DCB_CONNECTOR_NONE; | ||||||
| 		} | 		} | ||||||
|  | @ -966,8 +987,8 @@ nouveau_connector_create(struct drm_device *dev, int index) | ||||||
| 	 * figure out something suitable ourselves | 	 * figure out something suitable ourselves | ||||||
| 	 */ | 	 */ | ||||||
| 	if (nv_connector->type == DCB_CONNECTOR_NONE) { | 	if (nv_connector->type == DCB_CONNECTOR_NONE) { | ||||||
| 		struct drm_nouveau_private *dev_priv = dev->dev_private; | 		struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 		struct dcb_table *dcbt = &dev_priv->vbios.dcb; | 		struct dcb_table *dcbt = &drm->vbios.dcb; | ||||||
| 		u32 encoders = 0; | 		u32 encoders = 0; | ||||||
| 		int i; | 		int i; | ||||||
| 
 | 
 | ||||||
|  | @ -1003,7 +1024,7 @@ nouveau_connector_create(struct drm_device *dev, int index) | ||||||
| 	if (type == DRM_MODE_CONNECTOR_LVDS) { | 	if (type == DRM_MODE_CONNECTOR_LVDS) { | ||||||
| 		ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy); | 		ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			NV_ERROR(dev, "Error parsing LVDS table, disabling\n"); | 			NV_ERROR(drm, "Error parsing LVDS table, disabling\n"); | ||||||
| 			kfree(nv_connector); | 			kfree(nv_connector); | ||||||
| 			return ERR_PTR(ret); | 			return ERR_PTR(ret); | ||||||
| 		} | 		} | ||||||
|  | @ -1053,7 +1074,7 @@ nouveau_connector_create(struct drm_device *dev, int index) | ||||||
| 
 | 
 | ||||||
| 	switch (nv_connector->type) { | 	switch (nv_connector->type) { | ||||||
| 	case DCB_CONNECTOR_VGA: | 	case DCB_CONNECTOR_VGA: | ||||||
| 		if (dev_priv->card_type >= NV_50) { | 		if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 			drm_connector_attach_property(connector, | 			drm_connector_attach_property(connector, | ||||||
| 					dev->mode_config.scaling_mode_property, | 					dev->mode_config.scaling_mode_property, | ||||||
| 					nv_connector->scaling_mode); | 					nv_connector->scaling_mode); | ||||||
|  | @ -1086,10 +1107,9 @@ nouveau_connector_create(struct drm_device *dev, int index) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 	connector->polled = DRM_CONNECTOR_POLL_CONNECT; | ||||||
| 	if (nv_connector->hpd != DCB_GPIO_UNUSED) { | 	if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { | ||||||
| 		ret = nouveau_gpio_isr_add(dev, 0, nv_connector->hpd, 0xff, | 		ret = gpio->isr_add(gpio, 0, nv_connector->hpd, 0xff, | ||||||
| 					   nouveau_connector_hotplug, | 				    nouveau_connector_hotplug, connector); | ||||||
| 					   connector); |  | ||||||
| 		if (ret == 0) | 		if (ret == 0) | ||||||
| 			connector->polled = DRM_CONNECTOR_POLL_HPD; | 			connector->polled = DRM_CONNECTOR_POLL_HPD; | ||||||
| 	} | 	} | ||||||
|  | @ -1103,8 +1123,9 @@ nouveau_connector_hotplug(void *data, int plugged) | ||||||
| { | { | ||||||
| 	struct drm_connector *connector = data; | 	struct drm_connector *connector = data; | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "%splugged %s\n", plugged ? "" : "un", | 	NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", | ||||||
| 		 drm_get_connector_name(connector)); | 		 drm_get_connector_name(connector)); | ||||||
| 
 | 
 | ||||||
| 	if (plugged) | 	if (plugged) | ||||||
|  |  | ||||||
|  | @ -26,18 +26,20 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| #include "nouveau_drv.h" | 
 | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_fbcon.h" | #include "nouveau_fbcon.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
|  | #include "nouveau_gem.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/gpio.h> | #include <subdev/bios/gpio.h> | ||||||
|  | #include <subdev/gpio.h> | ||||||
|  | #include <engine/disp.h> | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) | nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) | ||||||
|  | @ -72,7 +74,7 @@ nouveau_framebuffer_init(struct drm_device *dev, | ||||||
| 			 struct drm_mode_fb_cmd2 *mode_cmd, | 			 struct drm_mode_fb_cmd2 *mode_cmd, | ||||||
| 			 struct nouveau_bo *nvbo) | 			 struct nouveau_bo *nvbo) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_framebuffer *fb = &nv_fb->base; | 	struct drm_framebuffer *fb = &nv_fb->base; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -84,7 +86,7 @@ nouveau_framebuffer_init(struct drm_device *dev, | ||||||
| 	drm_helper_mode_fill_fb_struct(fb, mode_cmd); | 	drm_helper_mode_fill_fb_struct(fb, mode_cmd); | ||||||
| 	nv_fb->nvbo = nvbo; | 	nv_fb->nvbo = nvbo; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_50) { | 	if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 		u32 tile_flags = nouveau_bo_tile_layout(nvbo); | 		u32 tile_flags = nouveau_bo_tile_layout(nvbo); | ||||||
| 		if (tile_flags == 0x7a00 || | 		if (tile_flags == 0x7a00 || | ||||||
| 		    tile_flags == 0xfe00) | 		    tile_flags == 0xfe00) | ||||||
|  | @ -103,21 +105,21 @@ nouveau_framebuffer_init(struct drm_device *dev, | ||||||
| 		case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; | 		case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break; | ||||||
| 		case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; | 		case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break; | ||||||
| 		default: | 		default: | ||||||
| 			 NV_ERROR(dev, "unknown depth %d\n", fb->depth); | 			 NV_ERROR(drm, "unknown depth %d\n", fb->depth); | ||||||
| 			 return -EINVAL; | 			 return -EINVAL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->chipset == 0x50) | 		if (nv_device(drm->device)->chipset == 0x50) | ||||||
| 			nv_fb->r_format |= (tile_flags << 8); | 			nv_fb->r_format |= (tile_flags << 8); | ||||||
| 
 | 
 | ||||||
| 		if (!tile_flags) { | 		if (!tile_flags) { | ||||||
| 			if (dev_priv->card_type < NV_D0) | 			if (nv_device(drm->device)->card_type < NV_D0) | ||||||
| 				nv_fb->r_pitch = 0x00100000 | fb->pitches[0]; | 				nv_fb->r_pitch = 0x00100000 | fb->pitches[0]; | ||||||
| 			else | 			else | ||||||
| 				nv_fb->r_pitch = 0x01000000 | fb->pitches[0]; | 				nv_fb->r_pitch = 0x01000000 | fb->pitches[0]; | ||||||
| 		} else { | 		} else { | ||||||
| 			u32 mode = nvbo->tile_mode; | 			u32 mode = nvbo->tile_mode; | ||||||
| 			if (dev_priv->card_type >= NV_C0) | 			if (nv_device(drm->device)->card_type >= NV_C0) | ||||||
| 				mode >>= 4; | 				mode >>= 4; | ||||||
| 			nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode; | 			nv_fb->r_pitch = ((fb->pitches[0] / 4) << 4) | mode; | ||||||
| 		} | 		} | ||||||
|  | @ -213,8 +215,9 @@ static struct nouveau_drm_prop_enum_list dither_depth[] = { | ||||||
| int | int | ||||||
| nouveau_display_init(struct drm_device *dev) | nouveau_display_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_display_engine *disp = &dev_priv->engine.display; | 	struct nouveau_display *disp = nouveau_display(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
| 	struct drm_connector *connector; | 	struct drm_connector *connector; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -226,8 +229,8 @@ nouveau_display_init(struct drm_device *dev) | ||||||
| 	 * some vbios default this to off for some reason, causing the | 	 * some vbios default this to off for some reason, causing the | ||||||
| 	 * panel to not work after resume | 	 * panel to not work after resume | ||||||
| 	 */ | 	 */ | ||||||
| 	if (nouveau_gpio_func_get(dev, DCB_GPIO_PANEL_POWER) == 0) { | 	if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) { | ||||||
| 		nouveau_gpio_func_set(dev, DCB_GPIO_PANEL_POWER, true); | 		gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||||||
| 		msleep(300); | 		msleep(300); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -237,7 +240,8 @@ nouveau_display_init(struct drm_device *dev) | ||||||
| 	/* enable hotplug interrupts */ | 	/* enable hotplug interrupts */ | ||||||
| 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||||||
| 		struct nouveau_connector *conn = nouveau_connector(connector); | 		struct nouveau_connector *conn = nouveau_connector(connector); | ||||||
| 		nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true); | 		if (gpio) | ||||||
|  | 			gpio->irq(gpio, 0, conn->hpd, 0xff, true); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
|  | @ -246,14 +250,16 @@ nouveau_display_init(struct drm_device *dev) | ||||||
| void | void | ||||||
| nouveau_display_fini(struct drm_device *dev) | nouveau_display_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_display_engine *disp = &dev_priv->engine.display; | 	struct nouveau_display *disp = nouveau_display(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
| 	struct drm_connector *connector; | 	struct drm_connector *connector; | ||||||
| 
 | 
 | ||||||
| 	/* disable hotplug interrupts */ | 	/* disable hotplug interrupts */ | ||||||
| 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | 	list_for_each_entry(connector, &dev->mode_config.connector_list, head) { | ||||||
| 		struct nouveau_connector *conn = nouveau_connector(connector); | 		struct nouveau_connector *conn = nouveau_connector(connector); | ||||||
| 		nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, false); | 		if (gpio) | ||||||
|  | 			gpio->irq(gpio, 0, conn->hpd, 0xff, false); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	drm_kms_helper_poll_disable(dev); | 	drm_kms_helper_poll_disable(dev); | ||||||
|  | @ -281,18 +287,28 @@ nouveau_display_vblank_put(void *data, int crtc) | ||||||
| int | int | ||||||
| nouveau_display_create(struct drm_device *dev) | nouveau_display_create(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_display_engine *disp = &dev_priv->engine.display; | 	struct nouveau_disp *pdisp = nouveau_disp(drm->device); | ||||||
|  | 	struct nouveau_display *disp; | ||||||
| 	int ret, gen; | 	int ret, gen; | ||||||
| 
 | 
 | ||||||
|  | 	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); | ||||||
|  | 	if (!disp) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	pdisp->vblank.data = dev; | ||||||
|  | 	pdisp->vblank.notify = nouveau_display_vblank_notify; | ||||||
|  | 	pdisp->vblank.get = nouveau_display_vblank_get; | ||||||
|  | 	pdisp->vblank.put = nouveau_display_vblank_put; | ||||||
|  | 
 | ||||||
| 	drm_mode_config_init(dev); | 	drm_mode_config_init(dev); | ||||||
| 	drm_mode_create_scaling_mode_property(dev); | 	drm_mode_create_scaling_mode_property(dev); | ||||||
| 	drm_mode_create_dvi_i_properties(dev); | 	drm_mode_create_dvi_i_properties(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type < NV_50) | 	if (nv_device(drm->device)->card_type < NV_50) | ||||||
| 		gen = 0; | 		gen = 0; | ||||||
| 	else | 	else | ||||||
| 	if (dev_priv->card_type < NV_D0) | 	if (nv_device(drm->device)->card_type < NV_D0) | ||||||
| 		gen = 1; | 		gen = 1; | ||||||
| 	else | 	else | ||||||
| 		gen = 2; | 		gen = 2; | ||||||
|  | @ -326,11 +342,11 @@ nouveau_display_create(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	dev->mode_config.min_width = 0; | 	dev->mode_config.min_width = 0; | ||||||
| 	dev->mode_config.min_height = 0; | 	dev->mode_config.min_height = 0; | ||||||
| 	if (dev_priv->card_type < NV_10) { | 	if (nv_device(drm->device)->card_type < NV_10) { | ||||||
| 		dev->mode_config.max_width = 2048; | 		dev->mode_config.max_width = 2048; | ||||||
| 		dev->mode_config.max_height = 2048; | 		dev->mode_config.max_height = 2048; | ||||||
| 	} else | 	} else | ||||||
| 	if (dev_priv->card_type < NV_50) { | 	if (nv_device(drm->device)->card_type < NV_50) { | ||||||
| 		dev->mode_config.max_width = 4096; | 		dev->mode_config.max_width = 4096; | ||||||
| 		dev->mode_config.max_height = 4096; | 		dev->mode_config.max_height = 4096; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -344,7 +360,13 @@ nouveau_display_create(struct drm_device *dev) | ||||||
| 	drm_kms_helper_poll_init(dev); | 	drm_kms_helper_poll_init(dev); | ||||||
| 	drm_kms_helper_poll_disable(dev); | 	drm_kms_helper_poll_disable(dev); | ||||||
| 
 | 
 | ||||||
| 	ret = disp->create(dev); | 	if (nv_device(drm->device)->card_type < NV_50) | ||||||
|  | 		ret = nv04_display_create(dev); | ||||||
|  | 	else | ||||||
|  | 	if (nv_device(drm->device)->card_type < NV_D0) | ||||||
|  | 		ret = nv50_display_create(dev); | ||||||
|  | 	else | ||||||
|  | 		ret = nvd0_display_create(dev); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto disp_create_err; | 		goto disp_create_err; | ||||||
| 
 | 
 | ||||||
|  | @ -354,10 +376,11 @@ nouveau_display_create(struct drm_device *dev) | ||||||
| 			goto vblank_err; | 			goto vblank_err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	nouveau_backlight_init(dev); | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| vblank_err: | vblank_err: | ||||||
| 	disp->destroy(dev); | 	disp->dtor(dev); | ||||||
| disp_create_err: | disp_create_err: | ||||||
| 	drm_kms_helper_poll_fini(dev); | 	drm_kms_helper_poll_fini(dev); | ||||||
| 	drm_mode_config_cleanup(dev); | 	drm_mode_config_cleanup(dev); | ||||||
|  | @ -367,28 +390,109 @@ disp_create_err: | ||||||
| void | void | ||||||
| nouveau_display_destroy(struct drm_device *dev) | nouveau_display_destroy(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_display *disp = nouveau_display(dev); | ||||||
| 	struct nouveau_display_engine *disp = &dev_priv->engine.display; |  | ||||||
| 
 | 
 | ||||||
|  | 	nouveau_backlight_exit(dev); | ||||||
| 	drm_vblank_cleanup(dev); | 	drm_vblank_cleanup(dev); | ||||||
| 
 | 
 | ||||||
| 	disp->destroy(dev); | 	disp->dtor(dev); | ||||||
| 
 | 
 | ||||||
| 	drm_kms_helper_poll_fini(dev); | 	drm_kms_helper_poll_fini(dev); | ||||||
| 	drm_mode_config_cleanup(dev); | 	drm_mode_config_cleanup(dev); | ||||||
|  | 	nouveau_drm(dev)->display = NULL; | ||||||
|  | 	kfree(disp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | nouveau_display_suspend(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct drm_crtc *crtc; | ||||||
|  | 
 | ||||||
|  | 	nouveau_display_fini(dev); | ||||||
|  | 
 | ||||||
|  | 	NV_INFO(drm, "unpinning framebuffer(s)...\n"); | ||||||
|  | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | 		struct nouveau_framebuffer *nouveau_fb; | ||||||
|  | 
 | ||||||
|  | 		nouveau_fb = nouveau_framebuffer(crtc->fb); | ||||||
|  | 		if (!nouveau_fb || !nouveau_fb->nvbo) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		nouveau_bo_unpin(nouveau_fb->nvbo); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
|  | 
 | ||||||
|  | 		nouveau_bo_unmap(nv_crtc->cursor.nvbo); | ||||||
|  | 		nouveau_bo_unpin(nv_crtc->cursor.nvbo); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | nouveau_display_resume(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct drm_crtc *crtc; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | 		struct nouveau_framebuffer *nouveau_fb; | ||||||
|  | 
 | ||||||
|  | 		nouveau_fb = nouveau_framebuffer(crtc->fb); | ||||||
|  | 		if (!nouveau_fb || !nouveau_fb->nvbo) | ||||||
|  | 			continue; | ||||||
|  | 
 | ||||||
|  | 		nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
|  | 
 | ||||||
|  | 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); | ||||||
|  | 		if (!ret) | ||||||
|  | 			ret = nouveau_bo_map(nv_crtc->cursor.nvbo); | ||||||
|  | 		if (ret) | ||||||
|  | 			NV_ERROR(drm, "Could not pin/map cursor.\n"); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	nouveau_fbcon_set_suspend(dev, 0); | ||||||
|  | 	nouveau_fbcon_zfill_all(dev); | ||||||
|  | 
 | ||||||
|  | 	nouveau_display_init(dev); | ||||||
|  | 
 | ||||||
|  | 	/* Force CLUT to get re-loaded during modeset */ | ||||||
|  | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
|  | 
 | ||||||
|  | 		nv_crtc->lut.depth = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	drm_helper_resume_force_mode(dev); | ||||||
|  | 
 | ||||||
|  | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
|  | 		u32 offset = nv_crtc->cursor.nvbo->bo.offset; | ||||||
|  | 
 | ||||||
|  | 		nv_crtc->cursor.set_offset(nv_crtc, offset); | ||||||
|  | 		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, | ||||||
|  | 						 nv_crtc->cursor_saved_y); | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nouveau_vblank_enable(struct drm_device *dev, int crtc) | nouveau_vblank_enable(struct drm_device *dev, int crtc) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_D0) | 	if (device->card_type >= NV_D0) | ||||||
| 		nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 1); | 		nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1); | ||||||
| 	else | 	else | ||||||
| 
 | 	if (device->card_type >= NV_50) | ||||||
| 	if (dev_priv->card_type >= NV_50) | 		nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0, | ||||||
| 		nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, 0, |  | ||||||
| 			NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); | 			NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); | ||||||
| 	else | 	else | ||||||
| 		NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, | 		NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, | ||||||
|  | @ -400,13 +504,13 @@ nouveau_vblank_enable(struct drm_device *dev, int crtc) | ||||||
| void | void | ||||||
| nouveau_vblank_disable(struct drm_device *dev, int crtc) | nouveau_vblank_disable(struct drm_device *dev, int crtc) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_D0) | 	if (device->card_type >= NV_D0) | ||||||
| 		nv_mask(dev, 0x6100c0 + (crtc * 0x800), 1, 0); | 		nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0); | ||||||
| 	else | 	else | ||||||
| 	if (dev_priv->card_type >= NV_50) | 	if (device->card_type >= NV_50) | ||||||
| 		nv_mask(dev, NV50_PDISPLAY_INTR_EN_1, | 		nv_mask(device, NV50_PDISPLAY_INTR_EN_1, | ||||||
| 			NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); | 			NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); | ||||||
| 	else | 	else | ||||||
| 		NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); | 		NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); | ||||||
|  | @ -461,8 +565,8 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, | ||||||
| 		       struct nouveau_fence **pfence) | 		       struct nouveau_fence **pfence) | ||||||
| { | { | ||||||
| 	struct nouveau_fence_chan *fctx = chan->fence; | 	struct nouveau_fence_chan *fctx = chan->fence; | ||||||
| 	struct drm_device *dev = nouveau_drv(chan->drm); | 	struct nouveau_drm *drm = chan->drm; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct drm_device *dev = drm->dev; | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -481,7 +585,7 @@ nouveau_page_flip_emit(struct nouveau_channel *chan, | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail; | 		goto fail; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type < NV_C0) { | 	if (nv_device(drm->device)->card_type < NV_C0) { | ||||||
| 		BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); | 		BEGIN_NV04(chan, NvSubSw, NV_SW_PAGE_FLIP, 1); | ||||||
| 		OUT_RING  (chan, 0x00000000); | 		OUT_RING  (chan, 0x00000000); | ||||||
| 		OUT_RING  (chan, 0x00000000); | 		OUT_RING  (chan, 0x00000000); | ||||||
|  | @ -509,7 +613,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| 		       struct drm_pending_vblank_event *event) | 		       struct drm_pending_vblank_event *event) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; | 	struct nouveau_bo *old_bo = nouveau_framebuffer(crtc->fb)->nvbo; | ||||||
| 	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; | 	struct nouveau_bo *new_bo = nouveau_framebuffer(fb)->nvbo; | ||||||
| 	struct nouveau_page_flip_state *s; | 	struct nouveau_page_flip_state *s; | ||||||
|  | @ -517,7 +621,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| 	struct nouveau_fence *fence; | 	struct nouveau_fence *fence; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (!nvdrm_channel(dev)) | 	if (!drm->channel) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 	s = kzalloc(sizeof(*s), GFP_KERNEL); | 	s = kzalloc(sizeof(*s), GFP_KERNEL); | ||||||
|  | @ -540,23 +644,23 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| 	if (fence) | 	if (fence) | ||||||
| 		chan = fence->channel; | 		chan = fence->channel; | ||||||
| 	if (!chan) | 	if (!chan) | ||||||
| 		chan = nvdrm_channel(dev); | 		chan = drm->channel; | ||||||
| 	mutex_lock(nvchan_mutex(chan)); | 	mutex_lock(&chan->cli->mutex); | ||||||
| 
 | 
 | ||||||
| 	/* Emit a page flip */ | 	/* Emit a page flip */ | ||||||
| 	if (dev_priv->card_type >= NV_50) { | 	if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 		if (dev_priv->card_type >= NV_D0) | 		if (nv_device(drm->device)->card_type >= NV_D0) | ||||||
| 			ret = nvd0_display_flip_next(crtc, fb, chan, 0); | 			ret = nvd0_display_flip_next(crtc, fb, chan, 0); | ||||||
| 		else | 		else | ||||||
| 			ret = nv50_display_flip_next(crtc, fb, chan); | 			ret = nv50_display_flip_next(crtc, fb, chan); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			mutex_unlock(nvchan_mutex(chan)); | 			mutex_unlock(&chan->cli->mutex); | ||||||
| 			goto fail_unreserve; | 			goto fail_unreserve; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | 	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence); | ||||||
| 	mutex_unlock(nvchan_mutex(chan)); | 	mutex_unlock(&chan->cli->mutex); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail_unreserve; | 		goto fail_unreserve; | ||||||
| 
 | 
 | ||||||
|  | @ -579,14 +683,15 @@ nouveau_finish_page_flip(struct nouveau_channel *chan, | ||||||
| 			 struct nouveau_page_flip_state *ps) | 			 struct nouveau_page_flip_state *ps) | ||||||
| { | { | ||||||
| 	struct nouveau_fence_chan *fctx = chan->fence; | 	struct nouveau_fence_chan *fctx = chan->fence; | ||||||
| 	struct drm_device *dev = nouveau_drv(chan->drm); | 	struct nouveau_drm *drm = chan->drm; | ||||||
|  | 	struct drm_device *dev = drm->dev; | ||||||
| 	struct nouveau_page_flip_state *s; | 	struct nouveau_page_flip_state *s; | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&dev->event_lock, flags); | 	spin_lock_irqsave(&dev->event_lock, flags); | ||||||
| 
 | 
 | ||||||
| 	if (list_empty(&fctx->flip)) { | 	if (list_empty(&fctx->flip)) { | ||||||
| 		NV_ERROR(dev, "unexpected pageflip\n"); | 		NV_ERROR(drm, "unexpected pageflip\n"); | ||||||
| 		spin_unlock_irqrestore(&dev->event_lock, flags); | 		spin_unlock_irqrestore(&dev->event_lock, flags); | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 	} | 	} | ||||||
|  | @ -617,13 +722,12 @@ int | ||||||
| nouveau_flip_complete(void *data) | nouveau_flip_complete(void *data) | ||||||
| { | { | ||||||
| 	struct nouveau_channel *chan = data; | 	struct nouveau_channel *chan = data; | ||||||
| 	struct drm_device *dev = nouveau_drv(chan->drm); | 	struct nouveau_drm *drm = chan->drm; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	struct nouveau_page_flip_state state; | 	struct nouveau_page_flip_state state; | ||||||
| 
 | 
 | ||||||
| 	if (!nouveau_finish_page_flip(chan, &state)) { | 	if (!nouveau_finish_page_flip(chan, &state)) { | ||||||
| 		if (dev_priv->card_type < NV_50) { | 		if (nv_device(drm->device)->card_type < NV_50) { | ||||||
| 			nv_set_crtc_base(dev, state.crtc, state.offset + | 			nv_set_crtc_base(drm->dev, state.crtc, state.offset + | ||||||
| 					 state.y * state.pitch + | 					 state.y * state.pitch + | ||||||
| 					 state.x * state.bpp / 8); | 					 state.x * state.bpp / 8); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
							
								
								
									
										94
									
								
								drivers/gpu/drm/nouveau/nouveau_display.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								drivers/gpu/drm/nouveau/nouveau_display.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | ||||||
|  | #ifndef __NOUVEAU_DISPLAY_H__ | ||||||
|  | #define __NOUVEAU_DISPLAY_H__ | ||||||
|  | 
 | ||||||
|  | #include <subdev/vm.h> | ||||||
|  | 
 | ||||||
|  | #include "nouveau_drm.h" | ||||||
|  | 
 | ||||||
|  | struct nouveau_framebuffer { | ||||||
|  | 	struct drm_framebuffer base; | ||||||
|  | 	struct nouveau_bo *nvbo; | ||||||
|  | 	struct nouveau_vma vma; | ||||||
|  | 	u32 r_dma; | ||||||
|  | 	u32 r_format; | ||||||
|  | 	u32 r_pitch; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline struct nouveau_framebuffer * | ||||||
|  | nouveau_framebuffer(struct drm_framebuffer *fb) | ||||||
|  | { | ||||||
|  | 	return container_of(fb, struct nouveau_framebuffer, base); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *, | ||||||
|  | 			     struct drm_mode_fb_cmd2 *, struct nouveau_bo *); | ||||||
|  | 
 | ||||||
|  | struct nouveau_page_flip_state { | ||||||
|  | 	struct list_head head; | ||||||
|  | 	struct drm_pending_vblank_event *event; | ||||||
|  | 	int crtc, bpp, pitch, x, y; | ||||||
|  | 	u64 offset; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_display { | ||||||
|  | 	void *priv; | ||||||
|  | 	void (*dtor)(struct drm_device *); | ||||||
|  | 	int  (*init)(struct drm_device *); | ||||||
|  | 	void (*fini)(struct drm_device *); | ||||||
|  | 
 | ||||||
|  | 	struct drm_property *dithering_mode; | ||||||
|  | 	struct drm_property *dithering_depth; | ||||||
|  | 	struct drm_property *underscan_property; | ||||||
|  | 	struct drm_property *underscan_hborder_property; | ||||||
|  | 	struct drm_property *underscan_vborder_property; | ||||||
|  | 	/* not really hue and saturation: */ | ||||||
|  | 	struct drm_property *vibrant_hue_property; | ||||||
|  | 	struct drm_property *color_vibrance_property; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline struct nouveau_display * | ||||||
|  | nouveau_display(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	return nouveau_drm(dev)->display; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int  nouveau_display_create(struct drm_device *dev); | ||||||
|  | void nouveau_display_destroy(struct drm_device *dev); | ||||||
|  | int  nouveau_display_init(struct drm_device *dev); | ||||||
|  | void nouveau_display_fini(struct drm_device *dev); | ||||||
|  | int  nouveau_display_suspend(struct drm_device *dev); | ||||||
|  | void nouveau_display_resume(struct drm_device *dev); | ||||||
|  | 
 | ||||||
|  | int  nouveau_vblank_enable(struct drm_device *dev, int crtc); | ||||||
|  | void nouveau_vblank_disable(struct drm_device *dev, int crtc); | ||||||
|  | 
 | ||||||
|  | int  nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
|  | 			    struct drm_pending_vblank_event *event); | ||||||
|  | int  nouveau_finish_page_flip(struct nouveau_channel *, | ||||||
|  | 			      struct nouveau_page_flip_state *); | ||||||
|  | 
 | ||||||
|  | int  nouveau_display_dumb_create(struct drm_file *, struct drm_device *, | ||||||
|  | 				 struct drm_mode_create_dumb *args); | ||||||
|  | int  nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, | ||||||
|  | 				     u32 handle, u64 *offset); | ||||||
|  | int  nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, | ||||||
|  | 				  u32 handle); | ||||||
|  | 
 | ||||||
|  | void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT | ||||||
|  | extern int nouveau_backlight_init(struct drm_device *); | ||||||
|  | extern void nouveau_backlight_exit(struct drm_device *); | ||||||
|  | #else | ||||||
|  | static inline int | ||||||
|  | nouveau_backlight_init(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | nouveau_backlight_exit(struct drm_device *dev) { | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -25,31 +25,35 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_dp_helper.h" | #include "drm_dp_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/gpio.h> | ||||||
|  | #include <subdev/i2c.h> | ||||||
|  | 
 | ||||||
| u8 * | u8 * | ||||||
| nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) | nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct bit_entry d; | 	struct bit_entry d; | ||||||
| 	u8 *table; | 	u8 *table; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (bit_table(dev, 'd', &d)) { | 	if (bit_table(dev, 'd', &d)) { | ||||||
| 		NV_ERROR(dev, "BIT 'd' table not found\n"); | 		NV_ERROR(drm, "BIT 'd' table not found\n"); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (d.version != 1) { | 	if (d.version != 1) { | ||||||
| 		NV_ERROR(dev, "BIT 'd' table version %d unknown\n", d.version); | 		NV_ERROR(drm, "BIT 'd' table version %d unknown\n", d.version); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	table = ROMPTR(dev, d.data[0]); | 	table = ROMPTR(dev, d.data[0]); | ||||||
| 	if (!table) { | 	if (!table) { | ||||||
| 		NV_ERROR(dev, "displayport table pointer invalid\n"); | 		NV_ERROR(drm, "displayport table pointer invalid\n"); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -60,7 +64,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) | ||||||
| 	case 0x40: | 	case 0x40: | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, "displayport table 0x%02x unknown\n", table[0]); | 		NV_ERROR(drm, "displayport table 0x%02x unknown\n", table[0]); | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -70,7 +74,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_output *dcb, u8 **entry) | ||||||
| 			return table; | 			return table; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_ERROR(dev, "displayport encoder table not found\n"); | 	NV_ERROR(drm, "displayport encoder table not found\n"); | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -92,9 +96,10 @@ struct dp_state { | ||||||
| static void | static void | ||||||
| dp_set_link_config(struct drm_device *dev, struct dp_state *dp) | dp_set_link_config(struct drm_device *dev, struct dp_state *dp) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u8 sink[2]; | 	u8 sink[2]; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); | 	NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); | ||||||
| 
 | 
 | ||||||
| 	/* set desired link configuration on the source */ | 	/* set desired link configuration on the source */ | ||||||
| 	dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, | 	dp->func->link_set(dev, dp->dcb, dp->crtc, dp->link_nr, dp->link_bw, | ||||||
|  | @ -106,27 +111,29 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) | ||||||
| 	if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) | 	if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) | ||||||
| 		sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | 		sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; | ||||||
| 
 | 
 | ||||||
| 	auxch_wr(dev, dp->auxch, DP_LINK_BW_SET, sink, 2); | 	nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) | dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u8 sink_tp; | 	u8 sink_tp; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "training pattern %d\n", pattern); | 	NV_DEBUG(drm, "training pattern %d\n", pattern); | ||||||
| 
 | 
 | ||||||
| 	dp->func->train_set(dev, dp->dcb, pattern); | 	dp->func->train_set(dev, dp->dcb, pattern); | ||||||
| 
 | 
 | ||||||
| 	auxch_rd(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); | 	nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); | ||||||
| 	sink_tp &= ~DP_TRAINING_PATTERN_MASK; | 	sink_tp &= ~DP_TRAINING_PATTERN_MASK; | ||||||
| 	sink_tp |= pattern; | 	sink_tp |= pattern; | ||||||
| 	auxch_wr(dev, dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); | 	nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) | dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < dp->link_nr; i++) { | 	for (i = 0; i < dp->link_nr; i++) { | ||||||
|  | @ -140,25 +147,26 @@ dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) | ||||||
| 		if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) | 		if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) | ||||||
| 			dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; | 			dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "config lane %d %02x\n", i, dp->conf[i]); | 		NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]); | ||||||
| 		dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); | 		dp->func->train_adj(dev, dp->dcb, i, lvsw, lpre); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return auxch_wr(dev, dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); | 	return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) | dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	udelay(delay); | 	udelay(delay); | ||||||
| 
 | 
 | ||||||
| 	ret = auxch_rd(dev, dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); | 	ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "status %02x %02x %02x %02x %02x %02x\n", | 	NV_DEBUG(drm, "status %02x %02x %02x %02x %02x %02x\n", | ||||||
| 		     dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], | 		     dp->stat[0], dp->stat[1], dp->stat[2], dp->stat[3], | ||||||
| 		     dp->stat[4], dp->stat[5]); | 		     dp->stat[4], dp->stat[5]); | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -287,11 +295,14 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, | ||||||
| 	struct nouveau_connector *nv_connector = | 	struct nouveau_connector *nv_connector = | ||||||
| 		nouveau_encoder_connector_get(nv_encoder); | 		nouveau_encoder_connector_get(nv_encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
| 	const u32 bw_list[] = { 270000, 162000, 0 }; | 	const u32 bw_list[] = { 270000, 162000, 0 }; | ||||||
| 	const u32 *link_bw = bw_list; | 	const u32 *link_bw = bw_list; | ||||||
| 	struct dp_state dp; | 	struct dp_state dp; | ||||||
| 
 | 
 | ||||||
| 	dp.auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | 	dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); | ||||||
| 	if (!dp.auxch) | 	if (!dp.auxch) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
|  | @ -307,7 +318,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, | ||||||
| 	 * we take during link training (DP_SET_POWER is one), we need | 	 * we take during link training (DP_SET_POWER is one), we need | ||||||
| 	 * to ignore them for the moment to avoid races. | 	 * to ignore them for the moment to avoid races. | ||||||
| 	 */ | 	 */ | ||||||
| 	nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false); | 	gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false); | ||||||
| 
 | 
 | ||||||
| 	/* enable down-spreading, if possible */ | 	/* enable down-spreading, if possible */ | ||||||
| 	dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1); | 	dp_set_downspread(dev, &dp, nv_encoder->dp.dpcd[3] & 1); | ||||||
|  | @ -350,7 +361,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, | ||||||
| 	dp_link_train_fini(dev, &dp); | 	dp_link_train_fini(dev, &dp); | ||||||
| 
 | 
 | ||||||
| 	/* re-enable hotplug detect */ | 	/* re-enable hotplug detect */ | ||||||
| 	nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true); | 	gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true); | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -359,10 +370,12 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, | ||||||
| 		struct dp_train_func *func) | 		struct dp_train_func *func) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
|  | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
| 	struct nouveau_i2c_port *auxch; | 	struct nouveau_i2c_port *auxch; | ||||||
| 	u8 status; | 	u8 status; | ||||||
| 
 | 
 | ||||||
| 	auxch = nouveau_i2c_find(encoder->dev, nv_encoder->dcb->i2c_index); | 	auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); | ||||||
| 	if (!auxch) | 	if (!auxch) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | @ -371,7 +384,7 @@ nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, | ||||||
| 	else | 	else | ||||||
| 		status = DP_SET_POWER_D3; | 		status = DP_SET_POWER_D3; | ||||||
| 
 | 
 | ||||||
| 	auxch_wr(encoder->dev, auxch, DP_SET_POWER, &status, 1); | 	nv_wraux(auxch, DP_SET_POWER, &status, 1); | ||||||
| 
 | 
 | ||||||
| 	if (mode == DRM_MODE_DPMS_ON) | 	if (mode == DRM_MODE_DPMS_ON) | ||||||
| 		nouveau_dp_link_train(encoder, datarate, func); | 		nouveau_dp_link_train(encoder, datarate, func); | ||||||
|  | @ -381,17 +394,18 @@ static void | ||||||
| nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, | nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, | ||||||
| 		     u8 *dpcd) | 		     u8 *dpcd) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u8 buf[3]; | 	u8 buf[3]; | ||||||
| 
 | 
 | ||||||
| 	if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) | 	if (!(dpcd[DP_DOWN_STREAM_PORT_COUNT] & DP_OUI_SUPPORT)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	if (!auxch_rd(dev, auxch, DP_SINK_OUI, buf, 3)) | 	if (!nv_rdaux(auxch, DP_SINK_OUI, buf, 3)) | ||||||
| 		NV_DEBUG_KMS(dev, "Sink OUI: %02hx%02hx%02hx\n", | 		NV_DEBUG(drm, "Sink OUI: %02hx%02hx%02hx\n", | ||||||
| 			     buf[0], buf[1], buf[2]); | 			     buf[0], buf[1], buf[2]); | ||||||
| 
 | 
 | ||||||
| 	if (!auxch_rd(dev, auxch, DP_BRANCH_OUI, buf, 3)) | 	if (!nv_rdaux(auxch, DP_BRANCH_OUI, buf, 3)) | ||||||
| 		NV_DEBUG_KMS(dev, "Branch OUI: %02hx%02hx%02hx\n", | 		NV_DEBUG(drm, "Branch OUI: %02hx%02hx%02hx\n", | ||||||
| 			     buf[0], buf[1], buf[2]); | 			     buf[0], buf[1], buf[2]); | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  | @ -401,24 +415,26 @@ nouveau_dp_detect(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
| 	struct nouveau_i2c_port *auxch; | 	struct nouveau_i2c_port *auxch; | ||||||
| 	u8 *dpcd = nv_encoder->dp.dpcd; | 	u8 *dpcd = nv_encoder->dp.dpcd; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); | 	auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); | ||||||
| 	if (!auxch) | 	if (!auxch) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	ret = auxch_rd(dev, auxch, DP_DPCD_REV, dpcd, 8); | 	ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	nv_encoder->dp.link_bw = 27000 * dpcd[1]; | 	nv_encoder->dp.link_bw = 27000 * dpcd[1]; | ||||||
| 	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; | 	nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "display: %dx%d dpcd 0x%02x\n", | 	NV_DEBUG(drm, "display: %dx%d dpcd 0x%02x\n", | ||||||
| 		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); | 		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw, dpcd[0]); | ||||||
| 	NV_DEBUG_KMS(dev, "encoder: %dx%d\n", | 	NV_DEBUG(drm, "encoder: %dx%d\n", | ||||||
| 		     nv_encoder->dcb->dpconf.link_nr, | 		     nv_encoder->dcb->dpconf.link_nr, | ||||||
| 		     nv_encoder->dcb->dpconf.link_bw); | 		     nv_encoder->dcb->dpconf.link_bw); | ||||||
| 
 | 
 | ||||||
|  | @ -427,7 +443,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) | ||||||
| 	if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) | 	if (nv_encoder->dcb->dpconf.link_bw < nv_encoder->dp.link_bw) | ||||||
| 		nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; | 		nv_encoder->dp.link_bw = nv_encoder->dcb->dpconf.link_bw; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "maximum: %dx%d\n", | 	NV_DEBUG(drm, "maximum: %dx%d\n", | ||||||
| 		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); | 		     nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); | ||||||
| 
 | 
 | ||||||
| 	nouveau_dp_probe_oui(dev, auxch, dpcd); | 	nouveau_dp_probe_oui(dev, auxch, dpcd); | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ | ||||||
|  * Authors: Ben Skeggs |  * Authors: Ben Skeggs | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <linux/console.h> | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/pci.h> | #include <linux/pci.h> | ||||||
| 
 | 
 | ||||||
|  | @ -34,24 +35,22 @@ | ||||||
| #include <subdev/vm.h> | #include <subdev/vm.h> | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drm.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_irq.h" | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
|  | #include "nouveau_ttm.h" | ||||||
|  | #include "nouveau_gem.h" | ||||||
| #include "nouveau_agp.h" | #include "nouveau_agp.h" | ||||||
|  | #include "nouveau_vga.h" | ||||||
|  | #include "nouveau_pm.h" | ||||||
|  | #include "nouveau_acpi.h" | ||||||
|  | #include "nouveau_bios.h" | ||||||
|  | #include "nouveau_ioctl.h" | ||||||
| #include "nouveau_abi16.h" | #include "nouveau_abi16.h" | ||||||
| #include "nouveau_fbcon.h" | #include "nouveau_fbcon.h" | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_ttm.h" | #include "nouveau_ttm.h" | ||||||
| 
 | 
 | ||||||
| int __devinit nouveau_pci_probe(struct pci_dev *, const struct pci_device_id *); |  | ||||||
| void nouveau_pci_remove(struct pci_dev *); |  | ||||||
| int nouveau_pci_suspend(struct pci_dev *, pm_message_t); |  | ||||||
| int nouveau_pci_resume(struct pci_dev *); |  | ||||||
| int __init nouveau_init(struct pci_driver *); |  | ||||||
| void __exit nouveau_exit(struct pci_driver *); |  | ||||||
| 
 |  | ||||||
| int nouveau_load(struct drm_device *, unsigned long); |  | ||||||
| int nouveau_unload(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(config, "option string to pass to driver core"); | MODULE_PARM_DESC(config, "option string to pass to driver core"); | ||||||
| static char *nouveau_config; | static char *nouveau_config; | ||||||
| module_param_named(config, nouveau_config, charp, 0400); | module_param_named(config, nouveau_config, charp, 0400); | ||||||
|  | @ -64,6 +63,12 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration"); | ||||||
| static int nouveau_noaccel = 0; | static int nouveau_noaccel = 0; | ||||||
| module_param_named(noaccel, nouveau_noaccel, int, 0400); | module_param_named(noaccel, nouveau_noaccel, int, 0400); | ||||||
| 
 | 
 | ||||||
|  | MODULE_PARM_DESC(modeset, "enable driver"); | ||||||
|  | int nouveau_modeset = -1; | ||||||
|  | module_param_named(modeset, nouveau_modeset, int, 0400); | ||||||
|  | 
 | ||||||
|  | static struct drm_driver driver; | ||||||
|  | 
 | ||||||
| static u64 | static u64 | ||||||
| nouveau_name(struct pci_dev *pdev) | nouveau_name(struct pci_dev *pdev) | ||||||
| { | { | ||||||
|  | @ -206,7 +211,7 @@ nouveau_drm_probe(struct pci_dev *pdev, const struct pci_device_id *pent) | ||||||
| 
 | 
 | ||||||
| 	pci_set_master(pdev); | 	pci_set_master(pdev); | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_pci_probe(pdev, pent); | 	ret = drm_get_pci_dev(pdev, pent, &driver); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		nouveau_object_ref(NULL, (struct nouveau_object **)&device); | 		nouveau_object_ref(NULL, (struct nouveau_object **)&device); | ||||||
| 		return ret; | 		return ret; | ||||||
|  | @ -224,13 +229,14 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_cli_create(pdev, 0, sizeof(*drm), (void**)&drm); | 	ret = nouveau_cli_create(pdev, 0, sizeof(*drm), (void**)&drm); | ||||||
| 	dev->dev_private = drm; |  | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
|  | 	dev->dev_private = drm; | ||||||
|  | 	drm->dev = dev; | ||||||
|  | 
 | ||||||
| 	INIT_LIST_HEAD(&drm->clients); | 	INIT_LIST_HEAD(&drm->clients); | ||||||
| 	spin_lock_init(&drm->tile.lock); | 	spin_lock_init(&drm->tile.lock); | ||||||
| 	drm->dev = dev; |  | ||||||
| 
 | 
 | ||||||
| 	/* make sure AGP controller is in a consistent state before we
 | 	/* make sure AGP controller is in a consistent state before we
 | ||||||
| 	 * (possibly) execute vbios init tables (see nouveau_agp.h) | 	 * (possibly) execute vbios init tables (see nouveau_agp.h) | ||||||
|  | @ -266,9 +272,15 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail_device; | 		goto fail_device; | ||||||
| 
 | 
 | ||||||
|  | 	/* workaround an odd issue on nvc1 by disabling the device's
 | ||||||
|  | 	 * nosnoop capability.  hopefully won't cause issues until a | ||||||
|  | 	 * better fix is found - assuming there is one... | ||||||
|  | 	 */ | ||||||
| 	device = nv_device(drm->device); | 	device = nv_device(drm->device); | ||||||
|  | 	if (nv_device(drm->device)->chipset == 0xc1) | ||||||
|  | 		nv_mask(device, 0x00088080, 0x00000800, 0x00000000); | ||||||
| 
 | 
 | ||||||
| 	/* initialise AGP */ | 	nouveau_vga_init(drm); | ||||||
| 	nouveau_agp_init(drm); | 	nouveau_agp_init(drm); | ||||||
| 
 | 
 | ||||||
| 	if (device->card_type >= NV_50) { | 	if (device->card_type >= NV_50) { | ||||||
|  | @ -280,18 +292,43 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_ttm_init(drm); | 	ret = nouveau_ttm_init(drm); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail_device; | 		goto fail_ttm; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_load(dev, flags); | 	ret = nouveau_bios_init(dev); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto fail_load; | 		goto fail_bios; | ||||||
|  | 
 | ||||||
|  | 	ret = nouveau_irq_init(dev); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto fail_irq; | ||||||
|  | 
 | ||||||
|  | 	ret = nouveau_display_create(dev); | ||||||
|  | 	if (ret) | ||||||
|  | 		goto fail_dispctor; | ||||||
|  | 
 | ||||||
|  | 	if (dev->mode_config.num_crtc) { | ||||||
|  | 		ret = nouveau_display_init(dev); | ||||||
|  | 		if (ret) | ||||||
|  | 			goto fail_dispinit; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	nouveau_pm_init(dev); | ||||||
| 
 | 
 | ||||||
| 	nouveau_accel_init(drm); | 	nouveau_accel_init(drm); | ||||||
| 	nouveau_fbcon_init(dev); | 	nouveau_fbcon_init(dev); | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| fail_load: | fail_dispinit: | ||||||
|  | 	nouveau_display_destroy(dev); | ||||||
|  | fail_dispctor: | ||||||
|  | 	nouveau_irq_fini(dev); | ||||||
|  | fail_irq: | ||||||
|  | 	nouveau_bios_takedown(dev); | ||||||
|  | fail_bios: | ||||||
| 	nouveau_ttm_fini(drm); | 	nouveau_ttm_fini(drm); | ||||||
|  | fail_ttm: | ||||||
|  | 	nouveau_agp_fini(drm); | ||||||
|  | 	nouveau_vga_fini(drm); | ||||||
| fail_device: | fail_device: | ||||||
| 	nouveau_cli_destroy(&drm->client); | 	nouveau_cli_destroy(&drm->client); | ||||||
| 	return ret; | 	return ret; | ||||||
|  | @ -300,21 +337,23 @@ fail_device: | ||||||
| int | int | ||||||
| nouveau_drm_unload(struct drm_device *dev) | nouveau_drm_unload(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct pci_dev *pdev = dev->pdev; |  | ||||||
| 	int ret; |  | ||||||
| 
 | 
 | ||||||
| 	nouveau_fbcon_fini(dev); | 	nouveau_fbcon_fini(dev); | ||||||
| 	nouveau_accel_fini(drm); | 	nouveau_accel_fini(drm); | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_unload(dev); | 	nouveau_pm_fini(dev); | ||||||
| 	if (ret) | 
 | ||||||
| 		return ret; | 	nouveau_display_fini(dev); | ||||||
|  | 	nouveau_display_destroy(dev); | ||||||
|  | 
 | ||||||
|  | 	nouveau_irq_fini(dev); | ||||||
|  | 	nouveau_bios_takedown(dev); | ||||||
| 
 | 
 | ||||||
| 	nouveau_ttm_fini(drm); | 	nouveau_ttm_fini(drm); | ||||||
| 	nouveau_agp_fini(drm); | 	nouveau_agp_fini(drm); | ||||||
|  | 	nouveau_vga_fini(drm); | ||||||
| 
 | 
 | ||||||
| 	pci_set_drvdata(pdev, drm->client.base.device); |  | ||||||
| 	nouveau_cli_destroy(&drm->client); | 	nouveau_cli_destroy(&drm->client); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -322,9 +361,13 @@ nouveau_drm_unload(struct drm_device *dev) | ||||||
| static void | static void | ||||||
| nouveau_drm_remove(struct pci_dev *pdev) | nouveau_drm_remove(struct pci_dev *pdev) | ||||||
| { | { | ||||||
|  | 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_object *device; | 	struct nouveau_object *device; | ||||||
| 	nouveau_pci_remove(pdev); | 
 | ||||||
| 	device = pci_get_drvdata(pdev); | 	device = drm->client.base.device; | ||||||
|  | 	drm_put_dev(dev); | ||||||
|  | 
 | ||||||
| 	nouveau_object_ref(NULL, &device); | 	nouveau_object_ref(NULL, &device); | ||||||
| 	nouveau_object_debug(); | 	nouveau_object_debug(); | ||||||
| } | } | ||||||
|  | @ -333,7 +376,7 @@ int | ||||||
| nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) | nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); | 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_cli *cli; | 	struct nouveau_cli *cli; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -344,8 +387,8 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state) | ||||||
| 	NV_INFO(drm, "suspending fbcon...\n"); | 	NV_INFO(drm, "suspending fbcon...\n"); | ||||||
| 	nouveau_fbcon_set_suspend(dev, 1); | 	nouveau_fbcon_set_suspend(dev, 1); | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(drm, "suspending drm...\n"); | 	NV_INFO(drm, "suspending display...\n"); | ||||||
| 	ret = nouveau_pci_suspend(pdev, pm_state); | 	ret = nouveau_display_suspend(dev); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
|  | @ -383,7 +426,8 @@ fail_client: | ||||||
| 		nouveau_client_init(&cli->base); | 		nouveau_client_init(&cli->base); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nouveau_pci_resume(pdev); | 	NV_INFO(drm, "resuming display...\n"); | ||||||
|  | 	nouveau_display_resume(dev); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -391,7 +435,7 @@ int | ||||||
| nouveau_drm_resume(struct pci_dev *pdev) | nouveau_drm_resume(struct pci_dev *pdev) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); | 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_cli *cli; | 	struct nouveau_cli *cli; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -419,7 +463,13 @@ nouveau_drm_resume(struct pci_dev *pdev) | ||||||
| 	if (drm->fence && nouveau_fence(drm)->resume) | 	if (drm->fence && nouveau_fence(drm)->resume) | ||||||
| 		nouveau_fence(drm)->resume(drm); | 		nouveau_fence(drm)->resume(drm); | ||||||
| 
 | 
 | ||||||
| 	return nouveau_pci_resume(pdev); | 	nouveau_run_vbios_init(dev); | ||||||
|  | 	nouveau_irq_postinstall(dev); | ||||||
|  | 	nouveau_pm_resume(dev); | ||||||
|  | 
 | ||||||
|  | 	NV_INFO(drm, "resuming display...\n"); | ||||||
|  | 	nouveau_display_resume(dev); | ||||||
|  | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
|  | @ -472,6 +522,90 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) | ||||||
| 	nouveau_cli_destroy(cli); | 	nouveau_cli_destroy(cli); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static struct drm_ioctl_desc | ||||||
|  | nouveau_ioctls[] = { | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const struct file_operations | ||||||
|  | nouveau_driver_fops = { | ||||||
|  | 	.owner = THIS_MODULE, | ||||||
|  | 	.open = drm_open, | ||||||
|  | 	.release = drm_release, | ||||||
|  | 	.unlocked_ioctl = drm_ioctl, | ||||||
|  | 	.mmap = nouveau_ttm_mmap, | ||||||
|  | 	.poll = drm_poll, | ||||||
|  | 	.fasync = drm_fasync, | ||||||
|  | 	.read = drm_read, | ||||||
|  | #if defined(CONFIG_COMPAT) | ||||||
|  | 	.compat_ioctl = nouveau_compat_ioctl, | ||||||
|  | #endif | ||||||
|  | 	.llseek = noop_llseek, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static struct drm_driver | ||||||
|  | driver = { | ||||||
|  | 	.driver_features = | ||||||
|  | 		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | | ||||||
|  | 		DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | | ||||||
|  | 		DRIVER_MODESET | DRIVER_PRIME, | ||||||
|  | 
 | ||||||
|  | 	.load = nouveau_drm_load, | ||||||
|  | 	.unload = nouveau_drm_unload, | ||||||
|  | 	.open = nouveau_drm_open, | ||||||
|  | 	.preclose = nouveau_drm_preclose, | ||||||
|  | 	.postclose = nouveau_drm_postclose, | ||||||
|  | 	.lastclose = nouveau_vga_lastclose, | ||||||
|  | 
 | ||||||
|  | 	.irq_preinstall = nouveau_irq_preinstall, | ||||||
|  | 	.irq_postinstall = nouveau_irq_postinstall, | ||||||
|  | 	.irq_uninstall = nouveau_irq_uninstall, | ||||||
|  | 	.irq_handler = nouveau_irq_handler, | ||||||
|  | 
 | ||||||
|  | 	.get_vblank_counter = drm_vblank_count, | ||||||
|  | 	.enable_vblank = nouveau_vblank_enable, | ||||||
|  | 	.disable_vblank = nouveau_vblank_disable, | ||||||
|  | 
 | ||||||
|  | 	.ioctls = nouveau_ioctls, | ||||||
|  | 	.fops = &nouveau_driver_fops, | ||||||
|  | 
 | ||||||
|  | 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd, | ||||||
|  | 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle, | ||||||
|  | 	.gem_prime_export = nouveau_gem_prime_export, | ||||||
|  | 	.gem_prime_import = nouveau_gem_prime_import, | ||||||
|  | 
 | ||||||
|  | 	.gem_init_object = nouveau_gem_object_new, | ||||||
|  | 	.gem_free_object = nouveau_gem_object_del, | ||||||
|  | 	.gem_open_object = nouveau_gem_object_open, | ||||||
|  | 	.gem_close_object = nouveau_gem_object_close, | ||||||
|  | 
 | ||||||
|  | 	.dumb_create = nouveau_display_dumb_create, | ||||||
|  | 	.dumb_map_offset = nouveau_display_dumb_map_offset, | ||||||
|  | 	.dumb_destroy = nouveau_display_dumb_destroy, | ||||||
|  | 
 | ||||||
|  | 	.name = DRIVER_NAME, | ||||||
|  | 	.desc = DRIVER_DESC, | ||||||
|  | #ifdef GIT_REVISION | ||||||
|  | 	.date = GIT_REVISION, | ||||||
|  | #else | ||||||
|  | 	.date = DRIVER_DATE, | ||||||
|  | #endif | ||||||
|  | 	.major = DRIVER_MAJOR, | ||||||
|  | 	.minor = DRIVER_MINOR, | ||||||
|  | 	.patchlevel = DRIVER_PATCHLEVEL, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| static struct pci_device_id | static struct pci_device_id | ||||||
| nouveau_drm_pci_table[] = { | nouveau_drm_pci_table[] = { | ||||||
| 	{ | 	{ | ||||||
|  | @ -500,19 +634,38 @@ nouveau_drm_pci_driver = { | ||||||
| static int __init | static int __init | ||||||
| nouveau_drm_init(void) | nouveau_drm_init(void) | ||||||
| { | { | ||||||
| 	return nouveau_init(&nouveau_drm_pci_driver); | 	driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls); | ||||||
|  | 
 | ||||||
|  | 	if (nouveau_modeset == -1) { | ||||||
|  | #ifdef CONFIG_VGA_CONSOLE | ||||||
|  | 		if (vgacon_text_force()) | ||||||
|  | 			nouveau_modeset = 0; | ||||||
|  | 		else | ||||||
|  | #endif | ||||||
|  | 			nouveau_modeset = 1; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!nouveau_modeset) | ||||||
|  | 		return 0; | ||||||
|  | 
 | ||||||
|  | 	nouveau_register_dsm_handler(); | ||||||
|  | 	return drm_pci_init(&driver, &nouveau_drm_pci_driver); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void __exit | static void __exit | ||||||
| nouveau_drm_exit(void) | nouveau_drm_exit(void) | ||||||
| { | { | ||||||
| 	nouveau_exit(&nouveau_drm_pci_driver); | 	if (!nouveau_modeset) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	drm_pci_exit(&driver, &nouveau_drm_pci_driver); | ||||||
|  | 	nouveau_unregister_dsm_handler(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| module_init(nouveau_drm_init); | module_init(nouveau_drm_init); | ||||||
| module_exit(nouveau_drm_exit); | module_exit(nouveau_drm_exit); | ||||||
| 
 | 
 | ||||||
| MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table); | MODULE_DEVICE_TABLE(pci, nouveau_drm_pci_table); | ||||||
| MODULE_AUTHOR("Nouveau Project"); | MODULE_AUTHOR(DRIVER_AUTHOR); | ||||||
| MODULE_DESCRIPTION("nVidia Riva/TNT/GeForce/Quadro/Tesla"); | MODULE_DESCRIPTION(DRIVER_DESC); | ||||||
| MODULE_LICENSE("GPL and additional rights"); | MODULE_LICENSE("GPL and additional rights"); | ||||||
|  |  | ||||||
|  | @ -1,6 +1,17 @@ | ||||||
| #ifndef __NOUVEAU_DRMCLI_H__ | #ifndef __NOUVEAU_DRMCLI_H__ | ||||||
| #define __NOUVEAU_DRMCLI_H__ | #define __NOUVEAU_DRMCLI_H__ | ||||||
| 
 | 
 | ||||||
|  | #define DRIVER_AUTHOR		"Nouveau Project" | ||||||
|  | #define DRIVER_EMAIL		"nouveau@lists.freedesktop.org" | ||||||
|  | 
 | ||||||
|  | #define DRIVER_NAME		"nouveau" | ||||||
|  | #define DRIVER_DESC		"nVidia Riva/TNT/GeForce/Quadro/Tesla" | ||||||
|  | #define DRIVER_DATE		"20120801" | ||||||
|  | 
 | ||||||
|  | #define DRIVER_MAJOR		1 | ||||||
|  | #define DRIVER_MINOR		1 | ||||||
|  | #define DRIVER_PATCHLEVEL	0 | ||||||
|  | 
 | ||||||
| #include <core/client.h> | #include <core/client.h> | ||||||
| 
 | 
 | ||||||
| #include <subdev/vm.h> | #include <subdev/vm.h> | ||||||
|  | @ -19,8 +30,8 @@ struct nouveau_channel; | ||||||
| 
 | 
 | ||||||
| #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) | #define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT) | ||||||
| 
 | 
 | ||||||
| #include "nouveau_revcompat.h" |  | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
|  | #include "nouveau_bios.h" | ||||||
| 
 | 
 | ||||||
| struct nouveau_drm_tile { | struct nouveau_drm_tile { | ||||||
| 	struct nouveau_fence *fence; | 	struct nouveau_fence *fence; | ||||||
|  | @ -96,13 +107,25 @@ struct nouveau_drm { | ||||||
| 		spinlock_t lock; | 		spinlock_t lock; | ||||||
| 	} tile; | 	} tile; | ||||||
| 
 | 
 | ||||||
|  | 	/* modesetting */ | ||||||
|  | 	struct nvbios vbios; | ||||||
|  | 	struct nouveau_display *display; | ||||||
| 	struct backlight_device *backlight; | 	struct backlight_device *backlight; | ||||||
|  | 
 | ||||||
|  | 	/* power management */ | ||||||
|  | 	struct nouveau_pm *pm; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static inline struct nouveau_drm * | static inline struct nouveau_drm * | ||||||
| nouveau_drm(struct drm_device *dev) | nouveau_drm(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	return nouveau_newpriv(dev); | 	return dev->dev_private; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline struct nouveau_device * | ||||||
|  | nouveau_dev(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	return nv_device(nouveau_drm(dev)->device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int nouveau_drm_suspend(struct pci_dev *, pm_message_t); | int nouveau_drm_suspend(struct pci_dev *, pm_message_t); | ||||||
|  |  | ||||||
|  | @ -1,353 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright 2005 Stephane Marchesin. |  | ||||||
|  * All Rights Reserved. |  | ||||||
|  * |  | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a |  | ||||||
|  * copy of this software and associated documentation files (the "Software"), |  | ||||||
|  * to deal in the Software without restriction, including without limitation |  | ||||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, |  | ||||||
|  * and/or sell copies of the Software, and to permit persons to whom the |  | ||||||
|  * Software is furnished to do so, subject to the following conditions: |  | ||||||
|  * |  | ||||||
|  * The above copyright notice and this permission notice (including the next |  | ||||||
|  * paragraph) shall be included in all copies or substantial portions of the |  | ||||||
|  * Software. |  | ||||||
|  * |  | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL |  | ||||||
|  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |  | ||||||
|  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |  | ||||||
|  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |  | ||||||
|  * OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include <linux/console.h> |  | ||||||
| #include <linux/module.h> |  | ||||||
| 
 |  | ||||||
| #include "drmP.h" |  | ||||||
| #include "drm.h" |  | ||||||
| #include "drm_crtc_helper.h" |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_abi16.h" |  | ||||||
| #include "nouveau_hw.h" |  | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_fbcon.h" |  | ||||||
| #include "nouveau_fence.h" |  | ||||||
| #include "nouveau_pm.h" |  | ||||||
| #include "nv50_display.h" |  | ||||||
| #include "nouveau_acpi.h" |  | ||||||
| #include "nouveau_ioctl.h" |  | ||||||
| 
 |  | ||||||
| #include "drm_pciids.h" |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(modeset, "Enable kernel modesetting"); |  | ||||||
| int nouveau_modeset = -1; |  | ||||||
| module_param_named(modeset, nouveau_modeset, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); |  | ||||||
| int nouveau_vram_notify = 0; |  | ||||||
| module_param_named(vram_notify, nouveau_vram_notify, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(vram_type, "Override detected VRAM type"); |  | ||||||
| char *nouveau_vram_type; |  | ||||||
| module_param_named(vram_type, nouveau_vram_type, charp, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); |  | ||||||
| int nouveau_duallink = 1; |  | ||||||
| module_param_named(duallink, nouveau_duallink, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(uscript_lvds, "LVDS output script table ID (>=GeForce 8)"); |  | ||||||
| int nouveau_uscript_lvds = -1; |  | ||||||
| module_param_named(uscript_lvds, nouveau_uscript_lvds, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)"); |  | ||||||
| int nouveau_uscript_tmds = -1; |  | ||||||
| module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); |  | ||||||
| int nouveau_ignorelid = 0; |  | ||||||
| module_param_named(ignorelid, nouveau_ignorelid, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(force_post, "Force POST"); |  | ||||||
| int nouveau_force_post = 0; |  | ||||||
| module_param_named(force_post, nouveau_force_post, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); |  | ||||||
| int nouveau_override_conntype = 0; |  | ||||||
| module_param_named(override_conntype, nouveau_override_conntype, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(tv_disable, "Disable TV-out detection"); |  | ||||||
| int nouveau_tv_disable = 0; |  | ||||||
| module_param_named(tv_disable, nouveau_tv_disable, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" |  | ||||||
| 		 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" |  | ||||||
| 		 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" |  | ||||||
| 		 "\t\tDefault: PAL\n" |  | ||||||
| 		 "\t\t*NOTE* Ignored for cards with external TV encoders."); |  | ||||||
| char *nouveau_tv_norm; |  | ||||||
| module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); |  | ||||||
| char *nouveau_perflvl; |  | ||||||
| module_param_named(perflvl, nouveau_perflvl, charp, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)"); |  | ||||||
| int nouveau_perflvl_wr; |  | ||||||
| module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(msi, "Enable MSI (default: off)"); |  | ||||||
| int nouveau_msi; |  | ||||||
| module_param_named(msi, nouveau_msi, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)"); |  | ||||||
| int nouveau_ctxfw; |  | ||||||
| module_param_named(ctxfw, nouveau_ctxfw, int, 0400); |  | ||||||
| 
 |  | ||||||
| MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS"); |  | ||||||
| int nouveau_mxmdcb = 1; |  | ||||||
| module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); |  | ||||||
| 
 |  | ||||||
| int nouveau_fbpercrtc; |  | ||||||
| #if 0 |  | ||||||
| module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| static struct drm_driver driver; |  | ||||||
| 
 |  | ||||||
| int __devinit |  | ||||||
| nouveau_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |  | ||||||
| { |  | ||||||
| 	return drm_get_pci_dev(pdev, ent, &driver); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_pci_remove(struct pci_dev *pdev) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); |  | ||||||
| 
 |  | ||||||
| 	drm_put_dev(dev); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); |  | ||||||
| 	struct drm_crtc *crtc; |  | ||||||
| 
 |  | ||||||
| 	NV_INFO(dev, "Disabling display...\n"); |  | ||||||
| 	nouveau_display_fini(dev); |  | ||||||
| 
 |  | ||||||
| 	NV_INFO(dev, "Unpinning framebuffer(s)...\n"); |  | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |  | ||||||
| 		struct nouveau_framebuffer *nouveau_fb; |  | ||||||
| 
 |  | ||||||
| 		nouveau_fb = nouveau_framebuffer(crtc->fb); |  | ||||||
| 		if (!nouveau_fb || !nouveau_fb->nvbo) |  | ||||||
| 			continue; |  | ||||||
| 
 |  | ||||||
| 		nouveau_bo_unpin(nouveau_fb->nvbo); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |  | ||||||
| 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |  | ||||||
| 
 |  | ||||||
| 		nouveau_bo_unmap(nv_crtc->cursor.nvbo); |  | ||||||
| 		nouveau_bo_unpin(nv_crtc->cursor.nvbo); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_pci_resume(struct pci_dev *pdev) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); |  | ||||||
| 	struct drm_crtc *crtc; |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	ret = nouveau_run_vbios_init(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		return ret; |  | ||||||
| 
 |  | ||||||
| 	nouveau_irq_postinstall(dev); |  | ||||||
| 
 |  | ||||||
| #if 0 |  | ||||||
| 	/* Re-write SKIPS, they'll have been lost over the suspend */ |  | ||||||
| 	if (nouveau_vram_pushbuf) { |  | ||||||
| 		struct nouveau_channel *chan; |  | ||||||
| 		int j; |  | ||||||
| 
 |  | ||||||
| 		for (i = 0; i < (pfifo ? pfifo->channels : 0); i++) { |  | ||||||
| 			chan = dev_priv->channels.ptr[i]; |  | ||||||
| 			if (!chan || !chan->pushbuf_bo) |  | ||||||
| 				continue; |  | ||||||
| 
 |  | ||||||
| 			for (j = 0; j < NOUVEAU_DMA_SKIPS; j++) |  | ||||||
| 				nouveau_bo_wr32(chan->pushbuf_bo, i, 0); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| 	nouveau_pm_resume(dev); |  | ||||||
| 
 |  | ||||||
| 	NV_INFO(dev, "Restoring mode...\n"); |  | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |  | ||||||
| 		struct nouveau_framebuffer *nouveau_fb; |  | ||||||
| 
 |  | ||||||
| 		nouveau_fb = nouveau_framebuffer(crtc->fb); |  | ||||||
| 		if (!nouveau_fb || !nouveau_fb->nvbo) |  | ||||||
| 			continue; |  | ||||||
| 
 |  | ||||||
| 		nouveau_bo_pin(nouveau_fb->nvbo, TTM_PL_FLAG_VRAM); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |  | ||||||
| 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |  | ||||||
| 
 |  | ||||||
| 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM); |  | ||||||
| 		if (!ret) |  | ||||||
| 			ret = nouveau_bo_map(nv_crtc->cursor.nvbo); |  | ||||||
| 		if (ret) |  | ||||||
| 			NV_ERROR(dev, "Could not pin/map cursor.\n"); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	nouveau_fbcon_set_suspend(dev, 0); |  | ||||||
| 	nouveau_fbcon_zfill_all(dev); |  | ||||||
| 
 |  | ||||||
| 	nouveau_display_init(dev); |  | ||||||
| 
 |  | ||||||
| 	/* Force CLUT to get re-loaded during modeset */ |  | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |  | ||||||
| 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |  | ||||||
| 
 |  | ||||||
| 		nv_crtc->lut.depth = 0; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	drm_helper_resume_force_mode(dev); |  | ||||||
| 
 |  | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |  | ||||||
| 		struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |  | ||||||
| 		u32 offset = nv_crtc->cursor.nvbo->bo.offset; |  | ||||||
| 
 |  | ||||||
| 		nv_crtc->cursor.set_offset(nv_crtc, offset); |  | ||||||
| 		nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, |  | ||||||
| 						 nv_crtc->cursor_saved_y); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static struct drm_ioctl_desc nouveau_ioctls[] = { |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_UNLOCKED|DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| 	DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_UNLOCKED|DRM_AUTH), |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static const struct file_operations nouveau_driver_fops = { |  | ||||||
| 	.owner = THIS_MODULE, |  | ||||||
| 	.open = drm_open, |  | ||||||
| 	.release = drm_release, |  | ||||||
| 	.unlocked_ioctl = drm_ioctl, |  | ||||||
| 	.mmap = nouveau_ttm_mmap, |  | ||||||
| 	.poll = drm_poll, |  | ||||||
| 	.fasync = drm_fasync, |  | ||||||
| 	.read = drm_read, |  | ||||||
| #if defined(CONFIG_COMPAT) |  | ||||||
| 	.compat_ioctl = nouveau_compat_ioctl, |  | ||||||
| #endif |  | ||||||
| 	.llseek = noop_llseek, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int nouveau_drm_load(struct drm_device *, unsigned long); |  | ||||||
| int nouveau_drm_unload(struct drm_device *); |  | ||||||
| int  nouveau_drm_open(struct drm_device *, struct drm_file *); |  | ||||||
| void nouveau_drm_preclose(struct drm_device *dev, struct drm_file *); |  | ||||||
| void nouveau_drm_postclose(struct drm_device *, struct drm_file *); |  | ||||||
| 
 |  | ||||||
| static struct drm_driver driver = { |  | ||||||
| 	.driver_features = |  | ||||||
| 		DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | |  | ||||||
| 		DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_GEM | |  | ||||||
| 		DRIVER_MODESET | DRIVER_PRIME, |  | ||||||
| 	.load = nouveau_drm_load, |  | ||||||
| 	.firstopen = nouveau_firstopen, |  | ||||||
| 	.lastclose = nouveau_lastclose, |  | ||||||
| 	.unload = nouveau_drm_unload, |  | ||||||
| 	.open = nouveau_drm_open, |  | ||||||
| 	.preclose = nouveau_drm_preclose, |  | ||||||
| 	.postclose = nouveau_drm_postclose, |  | ||||||
| 	.irq_preinstall = nouveau_irq_preinstall, |  | ||||||
| 	.irq_postinstall = nouveau_irq_postinstall, |  | ||||||
| 	.irq_uninstall = nouveau_irq_uninstall, |  | ||||||
| 	.irq_handler = nouveau_irq_handler, |  | ||||||
| 	.get_vblank_counter = drm_vblank_count, |  | ||||||
| 	.enable_vblank = nouveau_vblank_enable, |  | ||||||
| 	.disable_vblank = nouveau_vblank_disable, |  | ||||||
| 	.ioctls = nouveau_ioctls, |  | ||||||
| 	.fops = &nouveau_driver_fops, |  | ||||||
| 
 |  | ||||||
| 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd, |  | ||||||
| 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle, |  | ||||||
| 	.gem_prime_export = nouveau_gem_prime_export, |  | ||||||
| 	.gem_prime_import = nouveau_gem_prime_import, |  | ||||||
| 
 |  | ||||||
| 	.gem_init_object = nouveau_gem_object_new, |  | ||||||
| 	.gem_free_object = nouveau_gem_object_del, |  | ||||||
| 	.gem_open_object = nouveau_gem_object_open, |  | ||||||
| 	.gem_close_object = nouveau_gem_object_close, |  | ||||||
| 
 |  | ||||||
| 	.dumb_create = nouveau_display_dumb_create, |  | ||||||
| 	.dumb_map_offset = nouveau_display_dumb_map_offset, |  | ||||||
| 	.dumb_destroy = nouveau_display_dumb_destroy, |  | ||||||
| 
 |  | ||||||
| 	.name = DRIVER_NAME, |  | ||||||
| 	.desc = DRIVER_DESC, |  | ||||||
| #ifdef GIT_REVISION |  | ||||||
| 	.date = GIT_REVISION, |  | ||||||
| #else |  | ||||||
| 	.date = DRIVER_DATE, |  | ||||||
| #endif |  | ||||||
| 	.major = DRIVER_MAJOR, |  | ||||||
| 	.minor = DRIVER_MINOR, |  | ||||||
| 	.patchlevel = DRIVER_PATCHLEVEL, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int __init nouveau_init(struct pci_driver *pdrv) |  | ||||||
| { |  | ||||||
| 	driver.num_ioctls = ARRAY_SIZE(nouveau_ioctls); |  | ||||||
| 
 |  | ||||||
| 	if (nouveau_modeset == -1) { |  | ||||||
| #ifdef CONFIG_VGA_CONSOLE |  | ||||||
| 		if (vgacon_text_force()) |  | ||||||
| 			nouveau_modeset = 0; |  | ||||||
| 		else |  | ||||||
| #endif |  | ||||||
| 			nouveau_modeset = 1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!nouveau_modeset) |  | ||||||
| 		return 0; |  | ||||||
| 
 |  | ||||||
| 	nouveau_register_dsm_handler(); |  | ||||||
| 	return drm_pci_init(&driver, pdrv); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void __exit nouveau_exit(struct pci_driver *pdrv) |  | ||||||
| { |  | ||||||
| 	if (!nouveau_modeset) |  | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	drm_pci_exit(&driver, pdrv); |  | ||||||
| 	nouveau_unregister_dsm_handler(); |  | ||||||
| } |  | ||||||
|  | @ -1,551 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright 2005 Stephane Marchesin. |  | ||||||
|  * All Rights Reserved. |  | ||||||
|  * |  | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a |  | ||||||
|  * copy of this software and associated documentation files (the "Software"), |  | ||||||
|  * to deal in the Software without restriction, including without limitation |  | ||||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, |  | ||||||
|  * and/or sell copies of the Software, and to permit persons to whom the |  | ||||||
|  * Software is furnished to do so, subject to the following conditions: |  | ||||||
|  * |  | ||||||
|  * The above copyright notice and this permission notice (including the next |  | ||||||
|  * paragraph) shall be included in all copies or substantial portions of the |  | ||||||
|  * Software. |  | ||||||
|  * |  | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL |  | ||||||
|  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |  | ||||||
|  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |  | ||||||
|  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |  | ||||||
|  * OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #ifndef __NOUVEAU_DRV_H__ |  | ||||||
| #define __NOUVEAU_DRV_H__ |  | ||||||
| 
 |  | ||||||
| #define DRIVER_AUTHOR		"Stephane Marchesin" |  | ||||||
| #define DRIVER_EMAIL		"nouveau@lists.freedesktop.org" |  | ||||||
| 
 |  | ||||||
| #define DRIVER_NAME		"nouveau" |  | ||||||
| #define DRIVER_DESC		"nVidia Riva/TNT/GeForce" |  | ||||||
| #define DRIVER_DATE		"20120316" |  | ||||||
| 
 |  | ||||||
| #define DRIVER_MAJOR		1 |  | ||||||
| #define DRIVER_MINOR		0 |  | ||||||
| #define DRIVER_PATCHLEVEL	0 |  | ||||||
| 
 |  | ||||||
| #define NOUVEAU_FAMILY   0x0000FFFF |  | ||||||
| #define NOUVEAU_FLAGS    0xFFFF0000 |  | ||||||
| 
 |  | ||||||
| #include "ttm/ttm_bo_api.h" |  | ||||||
| #include "ttm/ttm_bo_driver.h" |  | ||||||
| #include "ttm/ttm_placement.h" |  | ||||||
| #include "ttm/ttm_memory.h" |  | ||||||
| #include "ttm/ttm_module.h" |  | ||||||
| 
 |  | ||||||
| #define XXX_THIS_IS_A_HACK |  | ||||||
| #include <subdev/vm.h> |  | ||||||
| #include <subdev/fb.h> |  | ||||||
| #include <core/gpuobj.h> |  | ||||||
| 
 |  | ||||||
| enum blah { |  | ||||||
| 	NV_MEM_TYPE_UNKNOWN = 0, |  | ||||||
| 	NV_MEM_TYPE_STOLEN, |  | ||||||
| 	NV_MEM_TYPE_SGRAM, |  | ||||||
| 	NV_MEM_TYPE_SDRAM, |  | ||||||
| 	NV_MEM_TYPE_DDR1, |  | ||||||
| 	NV_MEM_TYPE_DDR2, |  | ||||||
| 	NV_MEM_TYPE_DDR3, |  | ||||||
| 	NV_MEM_TYPE_GDDR2, |  | ||||||
| 	NV_MEM_TYPE_GDDR3, |  | ||||||
| 	NV_MEM_TYPE_GDDR4, |  | ||||||
| 	NV_MEM_TYPE_GDDR5 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| #include <nouveau_drm.h> |  | ||||||
| #include "nouveau_reg.h" |  | ||||||
| #include <nouveau_bios.h> |  | ||||||
| 
 |  | ||||||
| #include <subdev/bios/pll.h> |  | ||||||
| #include "nouveau_compat.h" |  | ||||||
| 
 |  | ||||||
| #define nouveau_gpuobj_new(d,c,s,a,f,o) \ |  | ||||||
| 	_nouveau_gpuobj_new((d), NULL, (s), (a), (f), (o)) |  | ||||||
| 
 |  | ||||||
| #define nouveau_vm_new(d,o,l,m,v) \ |  | ||||||
| 	_nouveau_vm_new((d), (o), (l), (m), (v)) |  | ||||||
| 
 |  | ||||||
| #define nv50_vm_flush_engine(d,e) \ |  | ||||||
| 	_nv50_vm_flush_engine((d), (e)) |  | ||||||
| 
 |  | ||||||
| #include "nouveau_bo.h" |  | ||||||
| #include "nouveau_gem.h" |  | ||||||
| 
 |  | ||||||
| struct nouveau_page_flip_state { |  | ||||||
| 	struct list_head head; |  | ||||||
| 	struct drm_pending_vblank_event *event; |  | ||||||
| 	int crtc, bpp, pitch, x, y; |  | ||||||
| 	uint64_t offset; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_display_engine { |  | ||||||
| 	void *priv; |  | ||||||
| 	int (*early_init)(struct drm_device *); |  | ||||||
| 	void (*late_takedown)(struct drm_device *); |  | ||||||
| 	int (*create)(struct drm_device *); |  | ||||||
| 	void (*destroy)(struct drm_device *); |  | ||||||
| 	int (*init)(struct drm_device *); |  | ||||||
| 	void (*fini)(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| 	struct drm_property *dithering_mode; |  | ||||||
| 	struct drm_property *dithering_depth; |  | ||||||
| 	struct drm_property *underscan_property; |  | ||||||
| 	struct drm_property *underscan_hborder_property; |  | ||||||
| 	struct drm_property *underscan_vborder_property; |  | ||||||
| 	/* not really hue and saturation: */ |  | ||||||
| 	struct drm_property *vibrant_hue_property; |  | ||||||
| 	struct drm_property *color_vibrance_property; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_voltage_level { |  | ||||||
| 	u32 voltage; /* microvolts */ |  | ||||||
| 	u8  vid; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_voltage { |  | ||||||
| 	bool supported; |  | ||||||
| 	u8 version; |  | ||||||
| 	u8 vid_mask; |  | ||||||
| 
 |  | ||||||
| 	struct nouveau_pm_voltage_level *level; |  | ||||||
| 	int nr_level; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| /* Exclusive upper limits */ |  | ||||||
| #define NV_MEM_CL_DDR2_MAX 8 |  | ||||||
| #define NV_MEM_WR_DDR2_MAX 9 |  | ||||||
| #define NV_MEM_CL_DDR3_MAX 17 |  | ||||||
| #define NV_MEM_WR_DDR3_MAX 17 |  | ||||||
| #define NV_MEM_CL_GDDR3_MAX 16 |  | ||||||
| #define NV_MEM_WR_GDDR3_MAX 18 |  | ||||||
| #define NV_MEM_CL_GDDR5_MAX 21 |  | ||||||
| #define NV_MEM_WR_GDDR5_MAX 20 |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_memtiming { |  | ||||||
| 	int id; |  | ||||||
| 
 |  | ||||||
| 	u32 reg[9]; |  | ||||||
| 	u32 mr[4]; |  | ||||||
| 
 |  | ||||||
| 	u8 tCWL; |  | ||||||
| 
 |  | ||||||
| 	u8 odt; |  | ||||||
| 	u8 drive_strength; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_tbl_header { |  | ||||||
| 	u8 version; |  | ||||||
| 	u8 header_len; |  | ||||||
| 	u8 entry_cnt; |  | ||||||
| 	u8 entry_len; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_tbl_entry { |  | ||||||
| 	u8 tWR; |  | ||||||
| 	u8 tWTR; |  | ||||||
| 	u8 tCL; |  | ||||||
| 	u8 tRC; |  | ||||||
| 	u8 empty_4; |  | ||||||
| 	u8 tRFC;	/* Byte 5 */ |  | ||||||
| 	u8 empty_6; |  | ||||||
| 	u8 tRAS;	/* Byte 7 */ |  | ||||||
| 	u8 empty_8; |  | ||||||
| 	u8 tRP;		/* Byte 9 */ |  | ||||||
| 	u8 tRCDRD; |  | ||||||
| 	u8 tRCDWR; |  | ||||||
| 	u8 tRRD; |  | ||||||
| 	u8 tUNK_13; |  | ||||||
| 	u8 RAM_FT1;		/* 14, a bitmask of random RAM features */ |  | ||||||
| 	u8 empty_15; |  | ||||||
| 	u8 tUNK_16; |  | ||||||
| 	u8 empty_17; |  | ||||||
| 	u8 tUNK_18; |  | ||||||
| 	u8 tCWL; |  | ||||||
| 	u8 tUNK_20, tUNK_21; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_profile; |  | ||||||
| struct nouveau_pm_profile_func { |  | ||||||
| 	void (*destroy)(struct nouveau_pm_profile *); |  | ||||||
| 	void (*init)(struct nouveau_pm_profile *); |  | ||||||
| 	void (*fini)(struct nouveau_pm_profile *); |  | ||||||
| 	struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_profile { |  | ||||||
| 	const struct nouveau_pm_profile_func *func; |  | ||||||
| 	struct list_head head; |  | ||||||
| 	char name[8]; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| #define NOUVEAU_PM_MAX_LEVEL 8 |  | ||||||
| struct nouveau_pm_level { |  | ||||||
| 	struct nouveau_pm_profile profile; |  | ||||||
| 	struct device_attribute dev_attr; |  | ||||||
| 	char name[32]; |  | ||||||
| 	int id; |  | ||||||
| 
 |  | ||||||
| 	struct nouveau_pm_memtiming timing; |  | ||||||
| 	u32 memory; |  | ||||||
| 	u16 memscript; |  | ||||||
| 
 |  | ||||||
| 	u32 core; |  | ||||||
| 	u32 shader; |  | ||||||
| 	u32 rop; |  | ||||||
| 	u32 copy; |  | ||||||
| 	u32 daemon; |  | ||||||
| 	u32 vdec; |  | ||||||
| 	u32 dom6; |  | ||||||
| 	u32 unka0;	/* nva3:nvc0 */ |  | ||||||
| 	u32 hub01;	/* nvc0- */ |  | ||||||
| 	u32 hub06;	/* nvc0- */ |  | ||||||
| 	u32 hub07;	/* nvc0- */ |  | ||||||
| 
 |  | ||||||
| 	u32 volt_min; /* microvolts */ |  | ||||||
| 	u32 volt_max; |  | ||||||
| 	u8  fanspeed; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_temp_sensor_constants { |  | ||||||
| 	u16 offset_constant; |  | ||||||
| 	s16 offset_mult; |  | ||||||
| 	s16 offset_div; |  | ||||||
| 	s16 slope_mult; |  | ||||||
| 	s16 slope_div; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_threshold_temp { |  | ||||||
| 	s16 critical; |  | ||||||
| 	s16 down_clock; |  | ||||||
| 	s16 fan_boost; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_fan { |  | ||||||
| 	u32 percent; |  | ||||||
| 	u32 min_duty; |  | ||||||
| 	u32 max_duty; |  | ||||||
| 	u32 pwm_freq; |  | ||||||
| 	u32 pwm_divisor; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_pm_engine { |  | ||||||
| 	struct nouveau_pm_voltage voltage; |  | ||||||
| 	struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; |  | ||||||
| 	int nr_perflvl; |  | ||||||
| 	struct nouveau_pm_temp_sensor_constants sensor_constants; |  | ||||||
| 	struct nouveau_pm_threshold_temp threshold_temp; |  | ||||||
| 	struct nouveau_pm_fan fan; |  | ||||||
| 
 |  | ||||||
| 	struct nouveau_pm_profile *profile_ac; |  | ||||||
| 	struct nouveau_pm_profile *profile_dc; |  | ||||||
| 	struct nouveau_pm_profile *profile; |  | ||||||
| 	struct list_head profiles; |  | ||||||
| 
 |  | ||||||
| 	struct nouveau_pm_level boot; |  | ||||||
| 	struct nouveau_pm_level *cur; |  | ||||||
| 
 |  | ||||||
| 	struct device *hwmon; |  | ||||||
| 	struct notifier_block acpi_nb; |  | ||||||
| 
 |  | ||||||
| 	int  (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); |  | ||||||
| 	void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); |  | ||||||
| 	int (*clocks_set)(struct drm_device *, void *); |  | ||||||
| 
 |  | ||||||
| 	int (*voltage_get)(struct drm_device *); |  | ||||||
| 	int (*voltage_set)(struct drm_device *, int voltage); |  | ||||||
| 	int (*pwm_get)(struct drm_device *, int line, u32*, u32*); |  | ||||||
| 	int (*pwm_set)(struct drm_device *, int line, u32, u32); |  | ||||||
| 	int (*temp_get)(struct drm_device *); |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct nouveau_engine { |  | ||||||
| 	struct nouveau_display_engine display; |  | ||||||
| 	struct nouveau_pm_engine      pm; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| enum nouveau_card_type { |  | ||||||
| 	NV_04      = 0x04, |  | ||||||
| 	NV_10      = 0x10, |  | ||||||
| 	NV_20      = 0x20, |  | ||||||
| 	NV_30      = 0x30, |  | ||||||
| 	NV_40      = 0x40, |  | ||||||
| 	NV_50      = 0x50, |  | ||||||
| 	NV_C0      = 0xc0, |  | ||||||
| 	NV_D0      = 0xd0, |  | ||||||
| 	NV_E0      = 0xe0, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| struct drm_nouveau_private { |  | ||||||
| 	struct drm_device *dev; |  | ||||||
| 
 |  | ||||||
| 	void *newpriv; |  | ||||||
| 
 |  | ||||||
| 	/* the card type, takes NV_* as values */ |  | ||||||
| 	enum nouveau_card_type card_type; |  | ||||||
| 	/* exact chipset, derived from NV_PMC_BOOT_0 */ |  | ||||||
| 	int chipset; |  | ||||||
| 	u32 crystal; |  | ||||||
| 
 |  | ||||||
| 	/* interrupt handling */ |  | ||||||
| 	void (*irq_handler[32])(struct drm_device *); |  | ||||||
| 	bool msi_enabled; |  | ||||||
| 
 |  | ||||||
| 	struct nouveau_engine engine; |  | ||||||
| 
 |  | ||||||
| 	/* For PFIFO and PGRAPH. */ |  | ||||||
| 	spinlock_t context_switch_lock; |  | ||||||
| 
 |  | ||||||
| 	struct nvbios vbios; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static inline struct drm_nouveau_private * |  | ||||||
| nouveau_private(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	return dev->dev_private; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* nouveau_drv.c */ |  | ||||||
| extern int nouveau_modeset; |  | ||||||
| extern int nouveau_duallink; |  | ||||||
| extern int nouveau_uscript_lvds; |  | ||||||
| extern int nouveau_uscript_tmds; |  | ||||||
| extern int nouveau_vram_pushbuf; |  | ||||||
| extern int nouveau_vram_notify; |  | ||||||
| extern char *nouveau_vram_type; |  | ||||||
| extern int nouveau_fbpercrtc; |  | ||||||
| extern int nouveau_tv_disable; |  | ||||||
| extern char *nouveau_tv_norm; |  | ||||||
| extern int nouveau_ignorelid; |  | ||||||
| extern int nouveau_force_post; |  | ||||||
| extern int nouveau_override_conntype; |  | ||||||
| extern char *nouveau_perflvl; |  | ||||||
| extern int nouveau_perflvl_wr; |  | ||||||
| extern int nouveau_msi; |  | ||||||
| extern int nouveau_ctxfw; |  | ||||||
| extern int nouveau_mxmdcb; |  | ||||||
| 
 |  | ||||||
| extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); |  | ||||||
| extern int nouveau_pci_resume(struct pci_dev *pdev); |  | ||||||
| 
 |  | ||||||
| /* nouveau_state.c */ |  | ||||||
| extern int  nouveau_load(struct drm_device *, unsigned long flags); |  | ||||||
| extern int  nouveau_firstopen(struct drm_device *); |  | ||||||
| extern void nouveau_lastclose(struct drm_device *); |  | ||||||
| extern int  nouveau_unload(struct drm_device *); |  | ||||||
| extern int  nouveau_card_init(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| /* nouveau_mem.c */ |  | ||||||
| extern int  nouveau_mem_timing_calc(struct drm_device *, u32 freq, |  | ||||||
| 				    struct nouveau_pm_memtiming *); |  | ||||||
| extern void nouveau_mem_timing_read(struct drm_device *, |  | ||||||
| 				    struct nouveau_pm_memtiming *); |  | ||||||
| 
 |  | ||||||
| /* nouveau_irq.c */ |  | ||||||
| extern int         nouveau_irq_init(struct drm_device *); |  | ||||||
| extern void        nouveau_irq_fini(struct drm_device *); |  | ||||||
| extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); |  | ||||||
| extern void        nouveau_irq_register(struct drm_device *, int status_bit, |  | ||||||
| 					void (*)(struct drm_device *)); |  | ||||||
| extern void        nouveau_irq_unregister(struct drm_device *, int status_bit); |  | ||||||
| extern void        nouveau_irq_preinstall(struct drm_device *); |  | ||||||
| extern int         nouveau_irq_postinstall(struct drm_device *); |  | ||||||
| extern void        nouveau_irq_uninstall(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| /* nouveau_backlight.c */ |  | ||||||
| #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT |  | ||||||
| extern int nouveau_backlight_init(struct drm_device *); |  | ||||||
| extern void nouveau_backlight_exit(struct drm_device *); |  | ||||||
| #else |  | ||||||
| static inline int nouveau_backlight_init(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline void nouveau_backlight_exit(struct drm_device *dev) { } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /* nouveau_bios.c */ |  | ||||||
| extern int nouveau_bios_init(struct drm_device *); |  | ||||||
| extern void nouveau_bios_takedown(struct drm_device *dev); |  | ||||||
| extern int nouveau_run_vbios_init(struct drm_device *); |  | ||||||
| extern struct dcb_connector_table_entry * |  | ||||||
| nouveau_bios_connector_entry(struct drm_device *, int index); |  | ||||||
| extern int nouveau_bios_run_display_table(struct drm_device *, u16 id, int clk, |  | ||||||
| 					  struct dcb_output *, int crtc); |  | ||||||
| extern bool nouveau_bios_fp_mode(struct drm_device *, struct drm_display_mode *); |  | ||||||
| extern uint8_t *nouveau_bios_embedded_edid(struct drm_device *); |  | ||||||
| extern int nouveau_bios_parse_lvds_table(struct drm_device *, int pxclk, |  | ||||||
| 					 bool *dl, bool *if_is_24bit); |  | ||||||
| extern int run_tmds_table(struct drm_device *, struct dcb_output *, |  | ||||||
| 			  int head, int pxclk); |  | ||||||
| extern int call_lvds_script(struct drm_device *, struct dcb_output *, int head, |  | ||||||
| 			    enum LVDS_script, int pxclk); |  | ||||||
| bool bios_encoder_match(struct dcb_output *, u32 hash); |  | ||||||
| 
 |  | ||||||
| /* nouveau_ttm.c */ |  | ||||||
| int nouveau_ttm_global_init(struct drm_nouveau_private *); |  | ||||||
| void nouveau_ttm_global_release(struct drm_nouveau_private *); |  | ||||||
| int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); |  | ||||||
| 
 |  | ||||||
| /* nouveau_hdmi.c */ |  | ||||||
| void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); |  | ||||||
| 
 |  | ||||||
| /* nvd0_display.c */ |  | ||||||
| extern int nvd0_display_create(struct drm_device *); |  | ||||||
| extern void nvd0_display_destroy(struct drm_device *); |  | ||||||
| extern int nvd0_display_init(struct drm_device *); |  | ||||||
| extern void nvd0_display_fini(struct drm_device *); |  | ||||||
| struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int crtc); |  | ||||||
| void nvd0_display_flip_stop(struct drm_crtc *); |  | ||||||
| int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, |  | ||||||
| 			   struct nouveau_channel *, u32 swap_interval); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| /* nouveau_display.c */ |  | ||||||
| int nouveau_display_create(struct drm_device *dev); |  | ||||||
| void nouveau_display_destroy(struct drm_device *dev); |  | ||||||
| int nouveau_display_init(struct drm_device *dev); |  | ||||||
| void nouveau_display_fini(struct drm_device *dev); |  | ||||||
| int nouveau_vblank_enable(struct drm_device *dev, int crtc); |  | ||||||
| void nouveau_vblank_disable(struct drm_device *dev, int crtc); |  | ||||||
| int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, |  | ||||||
| 			   struct drm_pending_vblank_event *event); |  | ||||||
| int nouveau_finish_page_flip(struct nouveau_channel *, |  | ||||||
| 			     struct nouveau_page_flip_state *); |  | ||||||
| int nouveau_display_dumb_create(struct drm_file *, struct drm_device *, |  | ||||||
| 				struct drm_mode_create_dumb *args); |  | ||||||
| int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *, |  | ||||||
| 				    uint32_t handle, uint64_t *offset); |  | ||||||
| int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, |  | ||||||
| 				 uint32_t handle); |  | ||||||
| 
 |  | ||||||
| #ifndef ioread32_native |  | ||||||
| #ifdef __BIG_ENDIAN |  | ||||||
| #define ioread16_native ioread16be |  | ||||||
| #define iowrite16_native iowrite16be |  | ||||||
| #define ioread32_native  ioread32be |  | ||||||
| #define iowrite32_native iowrite32be |  | ||||||
| #else /* def __BIG_ENDIAN */ |  | ||||||
| #define ioread16_native ioread16 |  | ||||||
| #define iowrite16_native iowrite16 |  | ||||||
| #define ioread32_native  ioread32 |  | ||||||
| #define iowrite32_native iowrite32 |  | ||||||
| #endif /* def __BIG_ENDIAN else */ |  | ||||||
| #endif /* !ioread32_native */ |  | ||||||
| 
 |  | ||||||
| /* register access */ |  | ||||||
| #define nv_rd08 _nv_rd08 |  | ||||||
| #define nv_wr08 _nv_wr08 |  | ||||||
| #define nv_rd32 _nv_rd32 |  | ||||||
| #define nv_wr32 _nv_wr32 |  | ||||||
| #define nv_mask _nv_mask |  | ||||||
| 
 |  | ||||||
| #define nv_wait(dev, reg, mask, val) \ |  | ||||||
| 	nouveau_wait_eq(dev, 2000000000ULL, (reg), (mask), (val)) |  | ||||||
| #define nv_wait_ne(dev, reg, mask, val) \ |  | ||||||
| 	nouveau_wait_ne(dev, 2000000000ULL, (reg), (mask), (val)) |  | ||||||
| #define nv_wait_cb(dev, func, data) \ |  | ||||||
| 	nouveau_wait_cb(dev, 2000000000ULL, (func), (data)) |  | ||||||
| 
 |  | ||||||
| /*
 |  | ||||||
|  * Logging |  | ||||||
|  * Argument d is (struct drm_device *). |  | ||||||
|  */ |  | ||||||
| #define NV_PRINTK(level, d, fmt, arg...) \ |  | ||||||
| 	printk(level "[" DRM_NAME "] " DRIVER_NAME " %s: " fmt, \ |  | ||||||
| 					pci_name(d->pdev), ##arg) |  | ||||||
| #ifndef NV_DEBUG_NOTRACE |  | ||||||
| #define NV_DEBUG(d, fmt, arg...) do {                                          \ |  | ||||||
| 	if (drm_debug & DRM_UT_DRIVER) {                                       \ |  | ||||||
| 		NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__,             \ |  | ||||||
| 			  __LINE__, ##arg);                                    \ |  | ||||||
| 	}                                                                      \ |  | ||||||
| } while (0) |  | ||||||
| #define NV_DEBUG_KMS(d, fmt, arg...) do {                                      \ |  | ||||||
| 	if (drm_debug & DRM_UT_KMS) {                                          \ |  | ||||||
| 		NV_PRINTK(KERN_DEBUG, d, "%s:%d - " fmt, __func__,             \ |  | ||||||
| 			  __LINE__, ##arg);                                    \ |  | ||||||
| 	}                                                                      \ |  | ||||||
| } while (0) |  | ||||||
| #else |  | ||||||
| #define NV_DEBUG(d, fmt, arg...) do {                                          \ |  | ||||||
| 	if (drm_debug & DRM_UT_DRIVER)                                         \ |  | ||||||
| 		NV_PRINTK(KERN_DEBUG, d, fmt, ##arg);                          \ |  | ||||||
| } while (0) |  | ||||||
| #define NV_DEBUG_KMS(d, fmt, arg...) do {                                      \ |  | ||||||
| 	if (drm_debug & DRM_UT_KMS)                                            \ |  | ||||||
| 		NV_PRINTK(KERN_DEBUG, d, fmt, ##arg);                          \ |  | ||||||
| } while (0) |  | ||||||
| #endif |  | ||||||
| #define NV_ERROR(d, fmt, arg...) NV_PRINTK(KERN_ERR, d, fmt, ##arg) |  | ||||||
| #define NV_INFO(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) |  | ||||||
| #define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg) |  | ||||||
| #define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) |  | ||||||
| #define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg) |  | ||||||
| #define NV_WARNONCE(d, fmt, arg...) do {                                       \ |  | ||||||
| 	static int _warned = 0;                                                \ |  | ||||||
| 	if (!_warned) {                                                        \ |  | ||||||
| 		NV_WARN(d, fmt, ##arg);                                        \ |  | ||||||
| 		_warned = 1;                                                   \ |  | ||||||
| 	}                                                                      \ |  | ||||||
| } while(0) |  | ||||||
| 
 |  | ||||||
| static inline bool |  | ||||||
| nv_two_heads(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	const int impl = dev->pci_device & 0x0ff0; |  | ||||||
| 
 |  | ||||||
| 	if (dev_priv->card_type >= NV_10 && impl != 0x0100 && |  | ||||||
| 	    impl != 0x0150 && impl != 0x01a0 && impl != 0x0200) |  | ||||||
| 		return true; |  | ||||||
| 
 |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline bool |  | ||||||
| nv_gf4_disp_arch(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline bool |  | ||||||
| nv_two_reg_pll(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	const int impl = dev->pci_device & 0x0ff0; |  | ||||||
| 
 |  | ||||||
| 	if (impl == 0x0310 || impl == 0x0340 || dev_priv->card_type >= NV_40) |  | ||||||
| 		return true; |  | ||||||
| 	return false; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline bool |  | ||||||
| nv_match_device(struct drm_device *dev, unsigned device, |  | ||||||
| 		unsigned sub_vendor, unsigned sub_device) |  | ||||||
| { |  | ||||||
| 	return dev->pdev->device == device && |  | ||||||
| 		dev->pdev->subsystem_vendor == sub_vendor && |  | ||||||
| 		dev->pdev->subsystem_device == sub_device; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static inline struct nv04_display * |  | ||||||
| nv04_display(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	return dev_priv->engine.display.priv; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #endif /* __NOUVEAU_DRV_H__ */ |  | ||||||
|  | @ -1,47 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright (C) 2008 Maarten Maathuis. |  | ||||||
|  * All Rights Reserved. |  | ||||||
|  * |  | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining |  | ||||||
|  * a copy of this software and associated documentation files (the |  | ||||||
|  * "Software"), to deal in the Software without restriction, including |  | ||||||
|  * without limitation the rights to use, copy, modify, merge, publish, |  | ||||||
|  * distribute, sublicense, and/or sell copies of the Software, and to |  | ||||||
|  * permit persons to whom the Software is furnished to do so, subject to |  | ||||||
|  * the following conditions: |  | ||||||
|  * |  | ||||||
|  * The above copyright notice and this permission notice (including the |  | ||||||
|  * next paragraph) shall be included in all copies or substantial |  | ||||||
|  * portions of the Software. |  | ||||||
|  * |  | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |  | ||||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |  | ||||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |  | ||||||
|  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |  | ||||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |  | ||||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |  | ||||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #ifndef __NOUVEAU_FRB_H__ |  | ||||||
| #define __NOUVEAU_FRB_H__ |  | ||||||
| 
 |  | ||||||
| struct nouveau_framebuffer { |  | ||||||
| 	struct drm_framebuffer base; |  | ||||||
| 	struct nouveau_bo *nvbo; |  | ||||||
| 	struct nouveau_vma vma; |  | ||||||
| 	u32 r_dma; |  | ||||||
| 	u32 r_format; |  | ||||||
| 	u32 r_pitch; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static inline struct nouveau_framebuffer * |  | ||||||
| nouveau_framebuffer(struct drm_framebuffer *fb) |  | ||||||
| { |  | ||||||
| 	return container_of(fb, struct nouveau_framebuffer, base); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, |  | ||||||
| 			     struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo); |  | ||||||
| #endif /* __NOUVEAU_FB_H__ */ |  | ||||||
|  | @ -47,7 +47,6 @@ | ||||||
| #include "nouveau_drm.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_gem.h" | #include "nouveau_gem.h" | ||||||
| #include "nouveau_bo.h" | #include "nouveau_bo.h" | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_fbcon.h" | #include "nouveau_fbcon.h" | ||||||
| #include "nouveau_chan.h" | #include "nouveau_chan.h" | ||||||
| 
 | 
 | ||||||
|  | @ -66,7 +65,7 @@ static void | ||||||
| nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *fbcon = info->par; | 	struct nouveau_fbdev *fbcon = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); | 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -98,7 +97,7 @@ static void | ||||||
| nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) | nouveau_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *image) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *fbcon = info->par; | 	struct nouveau_fbdev *fbcon = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); | 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -130,7 +129,7 @@ static void | ||||||
| nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | nouveau_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *fbcon = info->par; | 	struct nouveau_fbdev *fbcon = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); | 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -162,7 +161,7 @@ static int | ||||||
| nouveau_fbcon_sync(struct fb_info *info) | nouveau_fbcon_sync(struct fb_info *info) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *fbcon = info->par; | 	struct nouveau_fbdev *fbcon = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); | 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -257,7 +256,7 @@ nouveau_fbcon_create(struct nouveau_fbdev *fbcon, | ||||||
| 		     struct drm_fb_helper_surface_size *sizes) | 		     struct drm_fb_helper_surface_size *sizes) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = fbcon->dev; | 	struct drm_device *dev = fbcon->dev; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	struct fb_info *info; | 	struct fb_info *info; | ||||||
| 	struct drm_framebuffer *fb; | 	struct drm_framebuffer *fb; | ||||||
|  | @ -410,7 +409,7 @@ nouveau_fbcon_find_or_create_single(struct drm_fb_helper *helper, | ||||||
| void | void | ||||||
| nouveau_fbcon_output_poll_changed(struct drm_device *dev) | nouveau_fbcon_output_poll_changed(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	drm_fb_helper_hotplug_event(&drm->fbcon->helper); | 	drm_fb_helper_hotplug_event(&drm->fbcon->helper); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -442,7 +441,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) | ||||||
| void nouveau_fbcon_gpu_lockup(struct fb_info *info) | void nouveau_fbcon_gpu_lockup(struct fb_info *info) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *fbcon = info->par; | 	struct nouveau_fbdev *fbcon = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(fbcon->dev); | 	struct nouveau_drm *drm = nouveau_drm(fbcon->dev); | ||||||
| 
 | 
 | ||||||
| 	NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); | 	NV_ERROR(drm, "GPU lockup - switching to software fbcon\n"); | ||||||
| 	info->flags |= FBINFO_HWACCEL_DISABLED; | 	info->flags |= FBINFO_HWACCEL_DISABLED; | ||||||
|  | @ -458,7 +457,7 @@ static struct drm_fb_helper_funcs nouveau_fbcon_helper_funcs = { | ||||||
| int | int | ||||||
| nouveau_fbcon_init(struct drm_device *dev) | nouveau_fbcon_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | ||||||
| 	struct nouveau_fbdev *fbcon; | 	struct nouveau_fbdev *fbcon; | ||||||
| 	int preferred_bpp; | 	int preferred_bpp; | ||||||
|  | @ -499,7 +498,7 @@ nouveau_fbcon_init(struct drm_device *dev) | ||||||
| void | void | ||||||
| nouveau_fbcon_fini(struct drm_device *dev) | nouveau_fbcon_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (!drm->fbcon) | 	if (!drm->fbcon) | ||||||
| 		return; | 		return; | ||||||
|  | @ -511,7 +510,7 @@ nouveau_fbcon_fini(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| void nouveau_fbcon_save_disable_accel(struct drm_device *dev) | void nouveau_fbcon_save_disable_accel(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; | 	drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; | ||||||
| 	drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; | 	drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; | ||||||
|  | @ -519,13 +518,13 @@ void nouveau_fbcon_save_disable_accel(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| void nouveau_fbcon_restore_accel(struct drm_device *dev) | void nouveau_fbcon_restore_accel(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; | 	drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) | void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	console_lock(); | 	console_lock(); | ||||||
| 	if (state == 0) | 	if (state == 0) | ||||||
| 		nouveau_fbcon_save_disable_accel(dev); | 		nouveau_fbcon_save_disable_accel(dev); | ||||||
|  | @ -537,6 +536,6 @@ void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) | ||||||
| 
 | 
 | ||||||
| void nouveau_fbcon_zfill_all(struct drm_device *dev) | void nouveau_fbcon_zfill_all(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	nouveau_fbcon_zfill(dev, drm->fbcon); | 	nouveau_fbcon_zfill(dev, drm->fbcon); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,7 +29,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "drm_fb_helper.h" | #include "drm_fb_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_fb.h" | #include "nouveau_display.h" | ||||||
| 
 | 
 | ||||||
| struct nouveau_fbdev { | struct nouveau_fbdev { | ||||||
| 	struct drm_fb_helper helper; | 	struct drm_fb_helper helper; | ||||||
|  |  | ||||||
|  | @ -550,7 +550,7 @@ nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, | ||||||
| 				struct drm_nouveau_gem_pushbuf *req, | 				struct drm_nouveau_gem_pushbuf *req, | ||||||
| 				struct drm_nouveau_gem_pushbuf_bo *bo) | 				struct drm_nouveau_gem_pushbuf_bo *bo) | ||||||
| { | { | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; | 	struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 	unsigned i; | 	unsigned i; | ||||||
|  |  | ||||||
|  | @ -23,7 +23,7 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
|  | @ -31,10 +31,10 @@ | ||||||
| static bool | static bool | ||||||
| hdmi_sor(struct drm_encoder *encoder) | hdmi_sor(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	if (dev_priv->chipset <  0xa3 || | 	if (nv_device(drm->device)->chipset <  0xa3 || | ||||||
| 	    dev_priv->chipset == 0xaa || | 	    nv_device(drm->device)->chipset == 0xaa || | ||||||
| 	    dev_priv->chipset == 0xac) | 	    nv_device(drm->device)->chipset == 0xac) | ||||||
| 		return false; | 		return false; | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
|  | @ -52,13 +52,15 @@ hdmi_base(struct drm_encoder *encoder) | ||||||
| static void | static void | ||||||
| hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val) | hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val) | ||||||
| { | { | ||||||
| 	nv_wr32(encoder->dev, hdmi_base(encoder) + reg, val); | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
|  | 	nv_wr32(device, hdmi_base(encoder) + reg, val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static u32 | static u32 | ||||||
| hdmi_rd32(struct drm_encoder *encoder, u32 reg) | hdmi_rd32(struct drm_encoder *encoder, u32 reg) | ||||||
| { | { | ||||||
| 	return nv_rd32(encoder->dev, hdmi_base(encoder) + reg); | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
|  | 	return nv_rd32(device, hdmi_base(encoder) + reg); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static u32 | static u32 | ||||||
|  | @ -73,12 +75,11 @@ static void | ||||||
| nouveau_audio_disconnect(struct drm_encoder *encoder) | nouveau_audio_disconnect(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
| 	u32 or = nv_encoder->or * 0x800; | 	u32 or = nv_encoder->or * 0x800; | ||||||
| 
 | 
 | ||||||
| 	if (hdmi_sor(encoder)) { | 	if (hdmi_sor(encoder)) | ||||||
| 		nv_mask(dev, 0x61c448 + or, 0x00000003, 0x00000000); | 		nv_mask(device, 0x61c448 + or, 0x00000003, 0x00000000); | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -86,8 +87,8 @@ nouveau_audio_mode_set(struct drm_encoder *encoder, | ||||||
| 		       struct drm_display_mode *mode) | 		       struct drm_display_mode *mode) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct drm_device *dev = encoder->dev; |  | ||||||
| 	u32 or = nv_encoder->or * 0x800; | 	u32 or = nv_encoder->or * 0x800; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
|  | @ -98,16 +99,16 @@ nouveau_audio_mode_set(struct drm_encoder *encoder, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (hdmi_sor(encoder)) { | 	if (hdmi_sor(encoder)) { | ||||||
| 		nv_mask(dev, 0x61c448 + or, 0x00000001, 0x00000001); | 		nv_mask(device, 0x61c448 + or, 0x00000001, 0x00000001); | ||||||
| 
 | 
 | ||||||
| 		drm_edid_to_eld(&nv_connector->base, nv_connector->edid); | 		drm_edid_to_eld(&nv_connector->base, nv_connector->edid); | ||||||
| 		if (nv_connector->base.eld[0]) { | 		if (nv_connector->base.eld[0]) { | ||||||
| 			u8 *eld = nv_connector->base.eld; | 			u8 *eld = nv_connector->base.eld; | ||||||
| 			for (i = 0; i < eld[2] * 4; i++) | 			for (i = 0; i < eld[2] * 4; i++) | ||||||
| 				nv_wr32(dev, 0x61c440 + or, (i << 8) | eld[i]); | 				nv_wr32(device, 0x61c440 + or, (i << 8) | eld[i]); | ||||||
| 			for (i = eld[2] * 4; i < 0x60; i++) | 			for (i = eld[2] * 4; i < 0x60; i++) | ||||||
| 				nv_wr32(dev, 0x61c440 + or, (i << 8) | 0x00); | 				nv_wr32(device, 0x61c440 + or, (i << 8) | 0x00); | ||||||
| 			nv_mask(dev, 0x61c448 + or, 0x00000002, 0x00000002); | 			nv_mask(device, 0x61c448 + or, 0x00000002, 0x00000002); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | @ -219,9 +220,9 @@ void | ||||||
| nouveau_hdmi_mode_set(struct drm_encoder *encoder, | nouveau_hdmi_mode_set(struct drm_encoder *encoder, | ||||||
| 		      struct drm_display_mode *mode) | 		      struct drm_display_mode *mode) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct drm_device *dev = encoder->dev; |  | ||||||
| 	u32 max_ac_packet, rekey; | 	u32 max_ac_packet, rekey; | ||||||
| 
 | 
 | ||||||
| 	nv_connector = nouveau_encoder_connector_get(nv_encoder); | 	nv_connector = nouveau_encoder_connector_get(nv_encoder); | ||||||
|  | @ -238,9 +239,9 @@ nouveau_hdmi_mode_set(struct drm_encoder *encoder, | ||||||
| 	hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ | 	hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ | ||||||
| 	hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ | 	hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ | 	nv_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ | ||||||
| 	nv_mask(dev, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ | 	nv_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ | ||||||
| 	nv_mask(dev, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ | 	nv_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ | ||||||
| 
 | 
 | ||||||
| 	/* value matches nvidia binary driver, and tegra constant */ | 	/* value matches nvidia binary driver, and tegra constant */ | ||||||
| 	rekey = 56; | 	rekey = 56; | ||||||
|  |  | ||||||
|  | @ -23,10 +23,12 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/pll.h> | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
| 
 | 
 | ||||||
| #define CHIPSET_NFORCE 0x01a0 | #define CHIPSET_NFORCE 0x01a0 | ||||||
| #define CHIPSET_NFORCE2 0x01f0 | #define CHIPSET_NFORCE2 0x01f0 | ||||||
|  | @ -84,12 +86,12 @@ NVReadVgaGr(struct drm_device *dev, int head, uint8_t index) | ||||||
| void | void | ||||||
| NVSetOwner(struct drm_device *dev, int owner) | NVSetOwner(struct drm_device *dev, int owner) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (owner == 1) | 	if (owner == 1) | ||||||
| 		owner *= 3; | 		owner *= 3; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset == 0x11) { | 	if (nv_device(drm->device)->chipset == 0x11) { | ||||||
| 		/* This might seem stupid, but the blob does it and
 | 		/* This might seem stupid, but the blob does it and
 | ||||||
| 		 * omitting it often locks the system up. | 		 * omitting it often locks the system up. | ||||||
| 		 */ | 		 */ | ||||||
|  | @ -100,7 +102,7 @@ NVSetOwner(struct drm_device *dev, int owner) | ||||||
| 	/* CR44 is always changed on CRTC0 */ | 	/* CR44 is always changed on CRTC0 */ | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner); | 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_44, owner); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset == 0x11) {	/* set me harder */ | 	if (nv_device(drm->device)->chipset == 0x11) {	/* set me harder */ | ||||||
| 		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); | 		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); | ||||||
| 		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); | 		NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_2E, owner); | ||||||
| 	} | 	} | ||||||
|  | @ -132,7 +134,7 @@ static void | ||||||
| nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, | nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, | ||||||
| 		      uint32_t pll2, struct nouveau_pll_vals *pllvals) | 		      uint32_t pll2, struct nouveau_pll_vals *pllvals) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	/* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */ | 	/* to force parsing as single stage (i.e. nv40 vplls) pass pll2 as 0 */ | ||||||
| 
 | 
 | ||||||
|  | @ -149,7 +151,7 @@ nouveau_hw_decode_pll(struct drm_device *dev, uint32_t reg1, uint32_t pll1, | ||||||
| 		pllvals->NM1 = pll1 & 0xffff; | 		pllvals->NM1 = pll1 & 0xffff; | ||||||
| 		if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2) | 		if (nv_two_reg_pll(dev) && pll2 & NV31_RAMDAC_ENABLE_VCO2) | ||||||
| 			pllvals->NM2 = pll2 & 0xffff; | 			pllvals->NM2 = pll2 & 0xffff; | ||||||
| 		else if (dev_priv->chipset == 0x30 || dev_priv->chipset == 0x35) { | 		else if (nv_device(drm->device)->chipset == 0x30 || nv_device(drm->device)->chipset == 0x35) { | ||||||
| 			pllvals->M1 &= 0xf; /* only 4 bits */ | 			pllvals->M1 &= 0xf; /* only 4 bits */ | ||||||
| 			if (pll1 & NV30_RAMDAC_ENABLE_VCO2) { | 			if (pll1 & NV30_RAMDAC_ENABLE_VCO2) { | ||||||
| 				pllvals->M2 = (pll1 >> 4) & 0x7; | 				pllvals->M2 = (pll1 >> 4) & 0x7; | ||||||
|  | @ -164,25 +166,27 @@ int | ||||||
| nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, | nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, | ||||||
| 		       struct nouveau_pll_vals *pllvals) | 		       struct nouveau_pll_vals *pllvals) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint32_t reg1 = get_pll_register(dev, plltype), pll1, pll2 = 0; | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
|  | 	uint32_t reg1, pll1, pll2 = 0; | ||||||
| 	struct nvbios_pll pll_lim; | 	struct nvbios_pll pll_lim; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (reg1 == 0) | 	ret = nvbios_pll_parse(bios, plltype, &pll_lim); | ||||||
|  | 	if (ret || !(reg1 = pll_lim.reg)) | ||||||
| 		return -ENOENT; | 		return -ENOENT; | ||||||
| 
 | 
 | ||||||
| 	pll1 = nv_rd32(dev, reg1); | 	pll1 = nv_rd32(device, reg1); | ||||||
| 
 |  | ||||||
| 	if (reg1 <= 0x405c) | 	if (reg1 <= 0x405c) | ||||||
| 		pll2 = nv_rd32(dev, reg1 + 4); | 		pll2 = nv_rd32(device, reg1 + 4); | ||||||
| 	else if (nv_two_reg_pll(dev)) { | 	else if (nv_two_reg_pll(dev)) { | ||||||
| 		uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70); | 		uint32_t reg2 = reg1 + (reg1 == NV_RAMDAC_VPLL2 ? 0x5c : 0x70); | ||||||
| 
 | 
 | ||||||
| 		pll2 = nv_rd32(dev, reg2); | 		pll2 = nv_rd32(device, reg2); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { | 	if (nv_device(drm->device)->card_type == 0x40 && reg1 >= NV_PRAMDAC_VPLL_COEFF) { | ||||||
| 		uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); | 		uint32_t ramdac580 = NVReadRAMDAC(dev, 0, NV_PRAMDAC_580); | ||||||
| 
 | 
 | ||||||
| 		/* check whether vpll has been forced into single stage mode */ | 		/* check whether vpll has been forced into single stage mode */ | ||||||
|  | @ -195,13 +199,7 @@ nouveau_hw_get_pllvals(struct drm_device *dev, enum nvbios_pll_type plltype, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nouveau_hw_decode_pll(dev, reg1, pll1, pll2, pllvals); | 	nouveau_hw_decode_pll(dev, reg1, pll1, pll2, pllvals); | ||||||
| 
 |  | ||||||
| 	ret = get_pll_limits(dev, plltype, &pll_lim); |  | ||||||
| 	if (ret) |  | ||||||
| 		return ret; |  | ||||||
| 
 |  | ||||||
| 	pllvals->refclk = pll_lim.refclk; | 	pllvals->refclk = pll_lim.refclk; | ||||||
| 
 |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -255,11 +253,15 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | ||||||
| 	 * when such a condition detected.  only seen on nv11 to date | 	 * when such a condition detected.  only seen on nv11 to date | ||||||
| 	 */ | 	 */ | ||||||
| 
 | 
 | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nouveau_clock *clk = nouveau_clock(device); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
| 	struct nvbios_pll pll_lim; | 	struct nvbios_pll pll_lim; | ||||||
| 	struct nouveau_pll_vals pv; | 	struct nouveau_pll_vals pv; | ||||||
| 	enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0; | 	enum nvbios_pll_type pll = head ? PLL_VPLL1 : PLL_VPLL0; | ||||||
| 
 | 
 | ||||||
| 	if (get_pll_limits(dev, pll, &pll_lim)) | 	if (nvbios_pll_parse(bios, pll, &pll_lim)) | ||||||
| 		return; | 		return; | ||||||
| 	nouveau_hw_get_pllvals(dev, pll, &pv); | 	nouveau_hw_get_pllvals(dev, pll, &pv); | ||||||
| 
 | 
 | ||||||
|  | @ -268,13 +270,13 @@ nouveau_hw_fix_bad_vpll(struct drm_device *dev, int head) | ||||||
| 	    pv.log2P <= pll_lim.max_p) | 	    pv.log2P <= pll_lim.max_p) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	NV_WARN(dev, "VPLL %d outwith limits, attempting to fix\n", head + 1); | 	NV_WARN(drm, "VPLL %d outwith limits, attempting to fix\n", head + 1); | ||||||
| 
 | 
 | ||||||
| 	/* set lowest clock within static limits */ | 	/* set lowest clock within static limits */ | ||||||
| 	pv.M1 = pll_lim.vco1.max_m; | 	pv.M1 = pll_lim.vco1.max_m; | ||||||
| 	pv.N1 = pll_lim.vco1.min_n; | 	pv.N1 = pll_lim.vco1.min_n; | ||||||
| 	pv.log2P = pll_lim.max_p_usable; | 	pv.log2P = pll_lim.max_p_usable; | ||||||
| 	nouveau_hw_setpll(dev, pll_lim.reg, &pv); | 	clk->pll_prog(clk, pll_lim.reg, &pv); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*
 | /*
 | ||||||
|  | @ -303,6 +305,7 @@ static void nouveau_vga_font_io(struct drm_device *dev, | ||||||
| void | void | ||||||
| nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save) | nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t misc, gr4, gr5, gr6, seq2, seq4; | 	uint8_t misc, gr4, gr5, gr6, seq2, seq4; | ||||||
| 	bool graphicsmode; | 	bool graphicsmode; | ||||||
| 	unsigned plane; | 	unsigned plane; | ||||||
|  | @ -318,12 +321,12 @@ nouveau_hw_save_vga_fonts(struct drm_device *dev, bool save) | ||||||
| 	if (graphicsmode) /* graphics mode => framebuffer => no need to save */ | 	if (graphicsmode) /* graphics mode => framebuffer => no need to save */ | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "%sing VGA fonts\n", save ? "Sav" : "Restor"); | 	NV_INFO(drm, "%sing VGA fonts\n", save ? "Sav" : "Restor"); | ||||||
| 
 | 
 | ||||||
| 	/* map first 64KiB of VRAM, holds VGA fonts etc */ | 	/* map first 64KiB of VRAM, holds VGA fonts etc */ | ||||||
| 	iovram = ioremap(pci_resource_start(dev->pdev, 1), 65536); | 	iovram = ioremap(pci_resource_start(dev->pdev, 1), 65536); | ||||||
| 	if (!iovram) { | 	if (!iovram) { | ||||||
| 		NV_ERROR(dev, "Failed to map VRAM, " | 		NV_ERROR(drm, "Failed to map VRAM, " | ||||||
| 					"cannot save/restore VGA fonts.\n"); | 					"cannot save/restore VGA fonts.\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -386,25 +389,25 @@ static void | ||||||
| nv_save_state_ramdac(struct drm_device *dev, int head, | nv_save_state_ramdac(struct drm_device *dev, int head, | ||||||
| 		     struct nv04_mode_state *state) | 		     struct nv04_mode_state *state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_10) | 	if (nv_device(drm->device)->card_type >= NV_10) | ||||||
| 		regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); | 		regp->nv10_cursync = NVReadRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC); | ||||||
| 
 | 
 | ||||||
| 	nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, ®p->pllvals); | 	nouveau_hw_get_pllvals(dev, head ? PLL_VPLL1 : PLL_VPLL0, ®p->pllvals); | ||||||
| 	state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); | 	state->pllsel = NVReadRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT); | ||||||
| 	if (nv_two_heads(dev)) | 	if (nv_two_heads(dev)) | ||||||
| 		state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); | 		state->sel_clk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK); | ||||||
| 	if (dev_priv->chipset == 0x11) | 	if (nv_device(drm->device)->chipset == 0x11) | ||||||
| 		regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11); | 		regp->dither = NVReadRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11); | ||||||
| 
 | 
 | ||||||
| 	regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL); | 	regp->ramdac_gen_ctrl = NVReadRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL); | ||||||
| 
 | 
 | ||||||
| 	if (nv_gf4_disp_arch(dev)) | 	if (nv_gf4_disp_arch(dev)) | ||||||
| 		regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630); | 		regp->ramdac_630 = NVReadRAMDAC(dev, head, NV_PRAMDAC_630); | ||||||
| 	if (dev_priv->chipset >= 0x30) | 	if (nv_device(drm->device)->chipset >= 0x30) | ||||||
| 		regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634); | 		regp->ramdac_634 = NVReadRAMDAC(dev, head, NV_PRAMDAC_634); | ||||||
| 
 | 
 | ||||||
| 	regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP); | 	regp->tv_setup = NVReadRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP); | ||||||
|  | @ -446,7 +449,7 @@ nv_save_state_ramdac(struct drm_device *dev, int head, | ||||||
| 	if (nv_gf4_disp_arch(dev)) | 	if (nv_gf4_disp_arch(dev)) | ||||||
| 		regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0); | 		regp->ramdac_8c0 = NVReadRAMDAC(dev, head, NV_PRAMDAC_8C0); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_40) { | 	if (nv_device(drm->device)->card_type == NV_40) { | ||||||
| 		regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20); | 		regp->ramdac_a20 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A20); | ||||||
| 		regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24); | 		regp->ramdac_a24 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A24); | ||||||
| 		regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34); | 		regp->ramdac_a34 = NVReadRAMDAC(dev, head, NV_PRAMDAC_A34); | ||||||
|  | @ -461,26 +464,27 @@ static void | ||||||
| nv_load_state_ramdac(struct drm_device *dev, int head, | nv_load_state_ramdac(struct drm_device *dev, int head, | ||||||
| 		     struct nv04_mode_state *state) | 		     struct nv04_mode_state *state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_clock *clk = nouveau_clock(drm->device); | ||||||
| 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | ||||||
| 	uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; | 	uint32_t pllreg = head ? NV_RAMDAC_VPLL2 : NV_PRAMDAC_VPLL_COEFF; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_10) | 	if (nv_device(drm->device)->card_type >= NV_10) | ||||||
| 		NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync); | 		NVWriteRAMDAC(dev, head, NV_RAMDAC_NV10_CURSYNC, regp->nv10_cursync); | ||||||
| 
 | 
 | ||||||
| 	nouveau_hw_setpll(dev, pllreg, ®p->pllvals); | 	clk->pll_prog(clk, pllreg, ®p->pllvals); | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); | ||||||
| 	if (nv_two_heads(dev)) | 	if (nv_two_heads(dev)) | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk); | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, state->sel_clk); | ||||||
| 	if (dev_priv->chipset == 0x11) | 	if (nv_device(drm->device)->chipset == 0x11) | ||||||
| 		NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither); | 		NVWriteRAMDAC(dev, head, NV_RAMDAC_DITHER_NV11, regp->dither); | ||||||
| 
 | 
 | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_GENERAL_CONTROL, regp->ramdac_gen_ctrl); | ||||||
| 
 | 
 | ||||||
| 	if (nv_gf4_disp_arch(dev)) | 	if (nv_gf4_disp_arch(dev)) | ||||||
| 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630); | 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_630, regp->ramdac_630); | ||||||
| 	if (dev_priv->chipset >= 0x30) | 	if (nv_device(drm->device)->chipset >= 0x30) | ||||||
| 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634); | 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_634, regp->ramdac_634); | ||||||
| 
 | 
 | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_TV_SETUP, regp->tv_setup); | ||||||
|  | @ -517,7 +521,7 @@ nv_load_state_ramdac(struct drm_device *dev, int head, | ||||||
| 	if (nv_gf4_disp_arch(dev)) | 	if (nv_gf4_disp_arch(dev)) | ||||||
| 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0); | 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_8C0, regp->ramdac_8c0); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_40) { | 	if (nv_device(drm->device)->card_type == NV_40) { | ||||||
| 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20); | 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A20, regp->ramdac_a20); | ||||||
| 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24); | 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A24, regp->ramdac_a24); | ||||||
| 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34); | 		NVWriteRAMDAC(dev, head, NV_PRAMDAC_A34, regp->ramdac_a34); | ||||||
|  | @ -582,7 +586,7 @@ static void | ||||||
| nv_save_state_ext(struct drm_device *dev, int head, | nv_save_state_ext(struct drm_device *dev, int head, | ||||||
| 		  struct nv04_mode_state *state) | 		  struct nv04_mode_state *state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
|  | @ -598,10 +602,10 @@ nv_save_state_ext(struct drm_device *dev, int head, | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_21); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_21); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_20) | 	if (nv_device(drm->device)->card_type >= NV_20) | ||||||
| 		rd_cio_state(dev, head, regp, NV_CIO_CRE_47); | 		rd_cio_state(dev, head, regp, NV_CIO_CRE_47); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_30) | 	if (nv_device(drm->device)->card_type >= NV_30) | ||||||
| 		rd_cio_state(dev, head, regp, 0x9f); | 		rd_cio_state(dev, head, regp, 0x9f); | ||||||
| 
 | 
 | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_49); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_49); | ||||||
|  | @ -610,14 +614,14 @@ nv_save_state_ext(struct drm_device *dev, int head, | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_10) { | 	if (nv_device(drm->device)->card_type >= NV_10) { | ||||||
| 		regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830); | 		regp->crtc_830 = NVReadCRTC(dev, head, NV_PCRTC_830); | ||||||
| 		regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834); | 		regp->crtc_834 = NVReadCRTC(dev, head, NV_PCRTC_834); | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->card_type >= NV_30) | 		if (nv_device(drm->device)->card_type >= NV_30) | ||||||
| 			regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT); | 			regp->gpio_ext = NVReadCRTC(dev, head, NV_PCRTC_GPIO_EXT); | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->card_type == NV_40) | 		if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 			regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850); | 			regp->crtc_850 = NVReadCRTC(dev, head, NV_PCRTC_850); | ||||||
| 
 | 
 | ||||||
| 		if (nv_two_heads(dev)) | 		if (nv_two_heads(dev)) | ||||||
|  | @ -629,7 +633,7 @@ nv_save_state_ext(struct drm_device *dev, int head, | ||||||
| 
 | 
 | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); | ||||||
| 	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); | 	rd_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); | ||||||
| 	if (dev_priv->card_type >= NV_10) { | 	if (nv_device(drm->device)->card_type >= NV_10) { | ||||||
| 		rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); | 		rd_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); | ||||||
| 		rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB); | 		rd_cio_state(dev, head, regp, NV_CIO_CRE_CSB); | ||||||
| 		rd_cio_state(dev, head, regp, NV_CIO_CRE_4B); | 		rd_cio_state(dev, head, regp, NV_CIO_CRE_4B); | ||||||
|  | @ -657,12 +661,14 @@ static void | ||||||
| nv_load_state_ext(struct drm_device *dev, int head, | nv_load_state_ext(struct drm_device *dev, int head, | ||||||
| 		  struct nv04_mode_state *state) | 		  struct nv04_mode_state *state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nouveau_timer *ptimer = nouveau_timer(device); | ||||||
| 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | 	struct nv04_crtc_reg *regp = &state->crtc_reg[head]; | ||||||
| 	uint32_t reg900; | 	uint32_t reg900; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_10) { | 	if (nv_device(drm->device)->card_type >= NV_10) { | ||||||
| 		if (nv_two_heads(dev)) | 		if (nv_two_heads(dev)) | ||||||
| 			/* setting ENGINE_CTRL (EC) *must* come before
 | 			/* setting ENGINE_CTRL (EC) *must* come before
 | ||||||
| 			 * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in | 			 * CIO_CRE_LCD, as writing CRE_LCD sets bits 16 & 17 in | ||||||
|  | @ -670,24 +676,24 @@ nv_load_state_ext(struct drm_device *dev, int head, | ||||||
| 			 */ | 			 */ | ||||||
| 			NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl); | 			NVWriteCRTC(dev, head, NV_PCRTC_ENGINE_CTRL, regp->crtc_eng_ctrl); | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, NV_PVIDEO_STOP, 1); | 		nv_wr32(device, NV_PVIDEO_STOP, 1); | ||||||
| 		nv_wr32(dev, NV_PVIDEO_INTR_EN, 0); | 		nv_wr32(device, NV_PVIDEO_INTR_EN, 0); | ||||||
| 		nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(0), 0); | 		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(0), 0); | ||||||
| 		nv_wr32(dev, NV_PVIDEO_OFFSET_BUFF(1), 0); | 		nv_wr32(device, NV_PVIDEO_OFFSET_BUFF(1), 0); | ||||||
| 		nv_wr32(dev, NV_PVIDEO_LIMIT(0), 0); //dev_priv->fb_available_size - 1);
 | 		nv_wr32(device, NV_PVIDEO_LIMIT(0), 0); //drm->fb_available_size - 1);
 | ||||||
| 		nv_wr32(dev, NV_PVIDEO_LIMIT(1), 0); //dev_priv->fb_available_size - 1);
 | 		nv_wr32(device, NV_PVIDEO_LIMIT(1), 0); //drm->fb_available_size - 1);
 | ||||||
| 		nv_wr32(dev, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //dev_priv->fb_available_size - 1);
 | 		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(0), 0); //drm->fb_available_size - 1);
 | ||||||
| 		nv_wr32(dev, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //dev_priv->fb_available_size - 1);
 | 		nv_wr32(device, NV_PVIDEO_UVPLANE_LIMIT(1), 0); //drm->fb_available_size - 1);
 | ||||||
| 		nv_wr32(dev, NV_PBUS_POWERCTRL_2, 0); | 		nv_wr32(device, NV_PBUS_POWERCTRL_2, 0); | ||||||
| 
 | 
 | ||||||
| 		NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); | 		NVWriteCRTC(dev, head, NV_PCRTC_CURSOR_CONFIG, regp->cursor_cfg); | ||||||
| 		NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830); | 		NVWriteCRTC(dev, head, NV_PCRTC_830, regp->crtc_830); | ||||||
| 		NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834); | 		NVWriteCRTC(dev, head, NV_PCRTC_834, regp->crtc_834); | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->card_type >= NV_30) | 		if (nv_device(drm->device)->card_type >= NV_30) | ||||||
| 			NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext); | 			NVWriteCRTC(dev, head, NV_PCRTC_GPIO_EXT, regp->gpio_ext); | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->card_type == NV_40) { | 		if (nv_device(drm->device)->card_type == NV_40) { | ||||||
| 			NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); | 			NVWriteCRTC(dev, head, NV_PCRTC_850, regp->crtc_850); | ||||||
| 
 | 
 | ||||||
| 			reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); | 			reg900 = NVReadRAMDAC(dev, head, NV_PRAMDAC_900); | ||||||
|  | @ -710,23 +716,23 @@ nv_load_state_ext(struct drm_device *dev, int head, | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_20) | 	if (nv_device(drm->device)->card_type >= NV_20) | ||||||
| 		wr_cio_state(dev, head, regp, NV_CIO_CRE_47); | 		wr_cio_state(dev, head, regp, NV_CIO_CRE_47); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_30) | 	if (nv_device(drm->device)->card_type >= NV_30) | ||||||
| 		wr_cio_state(dev, head, regp, 0x9f); | 		wr_cio_state(dev, head, regp, 0x9f); | ||||||
| 
 | 
 | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_49); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_49); | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		nv_fix_nv40_hw_cursor(dev, head); | 		nv_fix_nv40_hw_cursor(dev, head); | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_ILACE__INDEX); | ||||||
| 
 | 
 | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH3__INDEX); | ||||||
| 	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); | 	wr_cio_state(dev, head, regp, NV_CIO_CRE_SCRATCH4__INDEX); | ||||||
| 	if (dev_priv->card_type >= NV_10) { | 	if (nv_device(drm->device)->card_type >= NV_10) { | ||||||
| 		wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); | 		wr_cio_state(dev, head, regp, NV_CIO_CRE_EBR_INDEX); | ||||||
| 		wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB); | 		wr_cio_state(dev, head, regp, NV_CIO_CRE_CSB); | ||||||
| 		wr_cio_state(dev, head, regp, NV_CIO_CRE_4B); | 		wr_cio_state(dev, head, regp, NV_CIO_CRE_4B); | ||||||
|  | @ -734,11 +740,11 @@ nv_load_state_ext(struct drm_device *dev, int head, | ||||||
| 	} | 	} | ||||||
| 	/* NV11 and NV20 stop at 0x52. */ | 	/* NV11 and NV20 stop at 0x52. */ | ||||||
| 	if (nv_gf4_disp_arch(dev)) { | 	if (nv_gf4_disp_arch(dev)) { | ||||||
| 		if (dev_priv->card_type == NV_10) { | 		if (nv_device(drm->device)->card_type == NV_10) { | ||||||
| 			/* Not waiting for vertical retrace before modifying
 | 			/* Not waiting for vertical retrace before modifying
 | ||||||
| 			   CRE_53/CRE_54 causes lockups. */ | 			   CRE_53/CRE_54 causes lockups. */ | ||||||
| 			nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); | 			nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x8); | ||||||
| 			nouveau_wait_eq(dev, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); | 			nouveau_timer_wait_eq(ptimer, 650000000, NV_PRMCIO_INP0__COLOR, 0x8, 0x0); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		wr_cio_state(dev, head, regp, NV_CIO_CRE_42); | 		wr_cio_state(dev, head, regp, NV_CIO_CRE_42); | ||||||
|  | @ -761,14 +767,15 @@ static void | ||||||
| nv_save_state_palette(struct drm_device *dev, int head, | nv_save_state_palette(struct drm_device *dev, int head, | ||||||
| 		      struct nv04_mode_state *state) | 		      struct nv04_mode_state *state) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int head_offset = head * NV_PRMDIO_SIZE, i; | 	int head_offset = head * NV_PRMDIO_SIZE, i; | ||||||
| 
 | 
 | ||||||
| 	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset, | 	nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset, | ||||||
| 				NV_PRMDIO_PIXEL_MASK_MASK); | 				NV_PRMDIO_PIXEL_MASK_MASK); | ||||||
| 	nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0); | 	nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS + head_offset, 0x0); | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 768; i++) { | 	for (i = 0; i < 768; i++) { | ||||||
| 		state->crtc_reg[head].DAC[i] = nv_rd08(dev, | 		state->crtc_reg[head].DAC[i] = nv_rd08(device, | ||||||
| 				NV_PRMDIO_PALETTE_DATA + head_offset); | 				NV_PRMDIO_PALETTE_DATA + head_offset); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -779,14 +786,15 @@ void | ||||||
| nouveau_hw_load_state_palette(struct drm_device *dev, int head, | nouveau_hw_load_state_palette(struct drm_device *dev, int head, | ||||||
| 			      struct nv04_mode_state *state) | 			      struct nv04_mode_state *state) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int head_offset = head * NV_PRMDIO_SIZE, i; | 	int head_offset = head * NV_PRMDIO_SIZE, i; | ||||||
| 
 | 
 | ||||||
| 	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK + head_offset, | 	nv_wr08(device, NV_PRMDIO_PIXEL_MASK + head_offset, | ||||||
| 				NV_PRMDIO_PIXEL_MASK_MASK); | 				NV_PRMDIO_PIXEL_MASK_MASK); | ||||||
| 	nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0); | 	nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS + head_offset, 0x0); | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 768; i++) { | 	for (i = 0; i < 768; i++) { | ||||||
| 		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA + head_offset, | 		nv_wr08(device, NV_PRMDIO_PALETTE_DATA + head_offset, | ||||||
| 				state->crtc_reg[head].DAC[i]); | 				state->crtc_reg[head].DAC[i]); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -796,9 +804,9 @@ nouveau_hw_load_state_palette(struct drm_device *dev, int head, | ||||||
| void nouveau_hw_save_state(struct drm_device *dev, int head, | void nouveau_hw_save_state(struct drm_device *dev, int head, | ||||||
| 			   struct nv04_mode_state *state) | 			   struct nv04_mode_state *state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset == 0x11) | 	if (nv_device(drm->device)->chipset == 0x11) | ||||||
| 		/* NB: no attempt is made to restore the bad pll later on */ | 		/* NB: no attempt is made to restore the bad pll later on */ | ||||||
| 		nouveau_hw_fix_bad_vpll(dev, head); | 		nouveau_hw_fix_bad_vpll(dev, head); | ||||||
| 	nv_save_state_ramdac(dev, head, state); | 	nv_save_state_ramdac(dev, head, state); | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ | ||||||
| #define __NOUVEAU_HW_H__ | #define __NOUVEAU_HW_H__ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nv04_display.h" | #include "nv04_display.h" | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/pll.h> | #include <subdev/bios/pll.h> | ||||||
|  | @ -60,37 +59,41 @@ extern void nouveau_calc_arb(struct drm_device *, int vclk, int bpp, | ||||||
| static inline uint32_t NVReadCRTC(struct drm_device *dev, | static inline uint32_t NVReadCRTC(struct drm_device *dev, | ||||||
| 					int head, uint32_t reg) | 					int head, uint32_t reg) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	uint32_t val; | 	uint32_t val; | ||||||
| 	if (head) | 	if (head) | ||||||
| 		reg += NV_PCRTC0_SIZE; | 		reg += NV_PCRTC0_SIZE; | ||||||
| 	val = nv_rd32(dev, reg); | 	val = nv_rd32(device, reg); | ||||||
| 	return val; | 	return val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void NVWriteCRTC(struct drm_device *dev, | static inline void NVWriteCRTC(struct drm_device *dev, | ||||||
| 					int head, uint32_t reg, uint32_t val) | 					int head, uint32_t reg, uint32_t val) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	if (head) | 	if (head) | ||||||
| 		reg += NV_PCRTC0_SIZE; | 		reg += NV_PCRTC0_SIZE; | ||||||
| 	nv_wr32(dev, reg, val); | 	nv_wr32(device, reg, val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline uint32_t NVReadRAMDAC(struct drm_device *dev, | static inline uint32_t NVReadRAMDAC(struct drm_device *dev, | ||||||
| 					int head, uint32_t reg) | 					int head, uint32_t reg) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	uint32_t val; | 	uint32_t val; | ||||||
| 	if (head) | 	if (head) | ||||||
| 		reg += NV_PRAMDAC0_SIZE; | 		reg += NV_PRAMDAC0_SIZE; | ||||||
| 	val = nv_rd32(dev, reg); | 	val = nv_rd32(device, reg); | ||||||
| 	return val; | 	return val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void NVWriteRAMDAC(struct drm_device *dev, | static inline void NVWriteRAMDAC(struct drm_device *dev, | ||||||
| 					int head, uint32_t reg, uint32_t val) | 					int head, uint32_t reg, uint32_t val) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	if (head) | 	if (head) | ||||||
| 		reg += NV_PRAMDAC0_SIZE; | 		reg += NV_PRAMDAC0_SIZE; | ||||||
| 	nv_wr32(dev, reg, val); | 	nv_wr32(device, reg, val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline uint8_t nv_read_tmds(struct drm_device *dev, | static inline uint8_t nv_read_tmds(struct drm_device *dev, | ||||||
|  | @ -116,16 +119,18 @@ static inline void nv_write_tmds(struct drm_device *dev, | ||||||
| static inline void NVWriteVgaCrtc(struct drm_device *dev, | static inline void NVWriteVgaCrtc(struct drm_device *dev, | ||||||
| 					int head, uint8_t index, uint8_t value) | 					int head, uint8_t index, uint8_t value) | ||||||
| { | { | ||||||
| 	nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	nv_wr08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); | 	nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); | ||||||
|  | 	nv_wr08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline uint8_t NVReadVgaCrtc(struct drm_device *dev, | static inline uint8_t NVReadVgaCrtc(struct drm_device *dev, | ||||||
| 					int head, uint8_t index) | 					int head, uint8_t index) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	uint8_t val; | 	uint8_t val; | ||||||
| 	nv_wr08(dev, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); | 	nv_wr08(device, NV_PRMCIO_CRX__COLOR + head * NV_PRMCIO_SIZE, index); | ||||||
| 	val = nv_rd08(dev, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); | 	val = nv_rd08(device, NV_PRMCIO_CR__COLOR + head * NV_PRMCIO_SIZE); | ||||||
| 	return val; | 	return val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -159,68 +164,74 @@ static inline uint8_t NVReadVgaCrtc5758(struct drm_device *dev, int head, uint8_ | ||||||
| static inline uint8_t NVReadPRMVIO(struct drm_device *dev, | static inline uint8_t NVReadPRMVIO(struct drm_device *dev, | ||||||
| 					int head, uint32_t reg) | 					int head, uint32_t reg) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t val; | 	uint8_t val; | ||||||
| 
 | 
 | ||||||
| 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
 | 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
 | ||||||
| 	 * NVSetOwner for the relevant head to be programmed */ | 	 * NVSetOwner for the relevant head to be programmed */ | ||||||
| 	if (head && dev_priv->card_type == NV_40) | 	if (head && nv_device(drm->device)->card_type == NV_40) | ||||||
| 		reg += NV_PRMVIO_SIZE; | 		reg += NV_PRMVIO_SIZE; | ||||||
| 
 | 
 | ||||||
| 	val = nv_rd08(dev, reg); | 	val = nv_rd08(device, reg); | ||||||
| 	return val; | 	return val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void NVWritePRMVIO(struct drm_device *dev, | static inline void NVWritePRMVIO(struct drm_device *dev, | ||||||
| 					int head, uint32_t reg, uint8_t value) | 					int head, uint32_t reg, uint8_t value) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
 | 	/* Only NV4x have two pvio ranges; other twoHeads cards MUST call
 | ||||||
| 	 * NVSetOwner for the relevant head to be programmed */ | 	 * NVSetOwner for the relevant head to be programmed */ | ||||||
| 	if (head && dev_priv->card_type == NV_40) | 	if (head && nv_device(drm->device)->card_type == NV_40) | ||||||
| 		reg += NV_PRMVIO_SIZE; | 		reg += NV_PRMVIO_SIZE; | ||||||
| 
 | 
 | ||||||
| 	nv_wr08(dev, reg, value); | 	nv_wr08(device, reg, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable) | static inline void NVSetEnablePalette(struct drm_device *dev, int head, bool enable) | ||||||
| { | { | ||||||
| 	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); | 	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | ||||||
|  | 	nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, enable ? 0 : 0x20); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline bool NVGetEnablePalette(struct drm_device *dev, int head) | static inline bool NVGetEnablePalette(struct drm_device *dev, int head) | ||||||
| { | { | ||||||
| 	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	return !(nv_rd08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); | 	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | ||||||
|  | 	return !(nv_rd08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE) & 0x20); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void NVWriteVgaAttr(struct drm_device *dev, | static inline void NVWriteVgaAttr(struct drm_device *dev, | ||||||
| 					int head, uint8_t index, uint8_t value) | 					int head, uint8_t index, uint8_t value) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	if (NVGetEnablePalette(dev, head)) | 	if (NVGetEnablePalette(dev, head)) | ||||||
| 		index &= ~0x20; | 		index &= ~0x20; | ||||||
| 	else | 	else | ||||||
| 		index |= 0x20; | 		index |= 0x20; | ||||||
| 
 | 
 | ||||||
| 	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | 	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | ||||||
| 	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); | 	nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); | ||||||
| 	nv_wr08(dev, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); | 	nv_wr08(device, NV_PRMCIO_AR__WRITE + head * NV_PRMCIO_SIZE, value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline uint8_t NVReadVgaAttr(struct drm_device *dev, | static inline uint8_t NVReadVgaAttr(struct drm_device *dev, | ||||||
| 					int head, uint8_t index) | 					int head, uint8_t index) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	uint8_t val; | 	uint8_t val; | ||||||
| 	if (NVGetEnablePalette(dev, head)) | 	if (NVGetEnablePalette(dev, head)) | ||||||
| 		index &= ~0x20; | 		index &= ~0x20; | ||||||
| 	else | 	else | ||||||
| 		index |= 0x20; | 		index |= 0x20; | ||||||
| 
 | 
 | ||||||
| 	nv_rd08(dev, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | 	nv_rd08(device, NV_PRMCIO_INP0__COLOR + head * NV_PRMCIO_SIZE); | ||||||
| 	nv_wr08(dev, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); | 	nv_wr08(device, NV_PRMCIO_ARX + head * NV_PRMCIO_SIZE, index); | ||||||
| 	val = nv_rd08(dev, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); | 	val = nv_rd08(device, NV_PRMCIO_AR__READ + head * NV_PRMCIO_SIZE); | ||||||
| 	return val; | 	return val; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -247,10 +258,11 @@ static inline void NVVgaProtect(struct drm_device *dev, int head, bool protect) | ||||||
| static inline bool | static inline bool | ||||||
| nv_heads_tied(struct drm_device *dev) | nv_heads_tied(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset == 0x11) | 	if (nv_device(drm->device)->chipset == 0x11) | ||||||
| 		return !!(nv_rd32(dev, NV_PBUS_DEBUG_1) & (1 << 28)); | 		return !!(nv_rd32(device, NV_PBUS_DEBUG_1) & (1 << 28)); | ||||||
| 
 | 
 | ||||||
| 	return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4; | 	return NVReadVgaCrtc(dev, 0, NV_CIO_CRE_44) & 0x4; | ||||||
| } | } | ||||||
|  | @ -299,13 +311,13 @@ nv_lock_vga_crtc_shadow(struct drm_device *dev, int head, int lock) | ||||||
| static inline bool | static inline bool | ||||||
| NVLockVgaCrtcs(struct drm_device *dev, bool lock) | NVLockVgaCrtcs(struct drm_device *dev, bool lock) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); | 	bool waslocked = !NVReadVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX); | ||||||
| 
 | 
 | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX, | 	NVWriteVgaCrtc(dev, 0, NV_CIO_SR_LOCK_INDEX, | ||||||
| 		       lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); | 		       lock ? NV_CIO_SR_LOCK_VALUE : NV_CIO_SR_UNLOCK_RW_VALUE); | ||||||
| 	/* NV11 has independently lockable extended crtcs, except when tied */ | 	/* NV11 has independently lockable extended crtcs, except when tied */ | ||||||
| 	if (dev_priv->chipset == 0x11 && !nv_heads_tied(dev)) | 	if (nv_device(drm->device)->chipset == 0x11 && !nv_heads_tied(dev)) | ||||||
| 		NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX, | 		NVWriteVgaCrtc(dev, 1, NV_CIO_SR_LOCK_INDEX, | ||||||
| 			       lock ? NV_CIO_SR_LOCK_VALUE : | 			       lock ? NV_CIO_SR_LOCK_VALUE : | ||||||
| 				      NV_CIO_SR_UNLOCK_RW_VALUE); | 				      NV_CIO_SR_UNLOCK_RW_VALUE); | ||||||
|  | @ -320,9 +332,9 @@ NVLockVgaCrtcs(struct drm_device *dev, bool lock) | ||||||
| 
 | 
 | ||||||
| static inline int nv_cursor_width(struct drm_device *dev) | static inline int nv_cursor_width(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	return dev_priv->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; | 	return nv_device(drm->device)->card_type >= NV_10 ? NV10_CURSOR_SIZE : NV04_CURSOR_SIZE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void | static inline void | ||||||
|  | @ -340,11 +352,11 @@ nv_fix_nv40_hw_cursor(struct drm_device *dev, int head) | ||||||
| static inline void | static inline void | ||||||
| nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) | nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	NVWriteCRTC(dev, head, NV_PCRTC_START, offset); | 	NVWriteCRTC(dev, head, NV_PCRTC_START, offset); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_04) { | 	if (nv_device(drm->device)->card_type == NV_04) { | ||||||
| 		/*
 | 		/*
 | ||||||
| 		 * Hilarious, the 24th bit doesn't want to stick to | 		 * Hilarious, the 24th bit doesn't want to stick to | ||||||
| 		 * PCRTC_START... | 		 * PCRTC_START... | ||||||
|  | @ -359,7 +371,7 @@ nv_set_crtc_base(struct drm_device *dev, int head, uint32_t offset) | ||||||
| static inline void | static inline void | ||||||
| nv_show_cursor(struct drm_device *dev, int head, bool show) | nv_show_cursor(struct drm_device *dev, int head, bool show) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t *curctl1 = | 	uint8_t *curctl1 = | ||||||
| 		&nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX]; | 		&nv04_display(dev)->mode_reg.crtc_reg[head].CRTC[NV_CIO_CRE_HCUR_ADDR1_INDEX]; | ||||||
| 
 | 
 | ||||||
|  | @ -369,14 +381,14 @@ nv_show_cursor(struct drm_device *dev, int head, bool show) | ||||||
| 		*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); | 		*curctl1 &= ~MASK(NV_CIO_CRE_HCUR_ADDR1_ENABLE); | ||||||
| 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1); | 	NVWriteVgaCrtc(dev, head, NV_CIO_CRE_HCUR_ADDR1_INDEX, *curctl1); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		nv_fix_nv40_hw_cursor(dev, head); | 		nv_fix_nv40_hw_cursor(dev, head); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline uint32_t | static inline uint32_t | ||||||
| nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) | nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int mask; | 	int mask; | ||||||
| 
 | 
 | ||||||
| 	if (bpp == 15) | 	if (bpp == 15) | ||||||
|  | @ -385,7 +397,7 @@ nv_pitch_align(struct drm_device *dev, uint32_t width, int bpp) | ||||||
| 		bpp = 8; | 		bpp = 8; | ||||||
| 
 | 
 | ||||||
| 	/* Alignment requirements taken from the Haiku driver */ | 	/* Alignment requirements taken from the Haiku driver */ | ||||||
| 	if (dev_priv->card_type == NV_04) | 	if (nv_device(drm->device)->card_type == NV_04) | ||||||
| 		mask = 128 / bpp - 1; | 		mask = 128 / bpp - 1; | ||||||
| 	else | 	else | ||||||
| 		mask = 512 / bpp - 1; | 		mask = 512 / bpp - 1; | ||||||
|  |  | ||||||
|  | @ -1,145 +1,85 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (C) 2006 Ben Skeggs. |  * Copyright 2012 Red Hat Inc. | ||||||
|  * |  * | ||||||
|  * All Rights Reserved. |  * Permission is hereby granted, free of charge, to any person obtaining a | ||||||
|  |  * copy of this software and associated documentation files (the "Software"), | ||||||
|  |  * to deal in the Software without restriction, including without limitation | ||||||
|  |  * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||||||
|  |  * and/or sell copies of the Software, and to permit persons to whom the | ||||||
|  |  * Software is furnished to do so, subject to the following conditions: | ||||||
|  * |  * | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining |  * The above copyright notice and this permission notice shall be included in | ||||||
|  * a copy of this software and associated documentation files (the |  * all copies or substantial portions of the Software. | ||||||
|  * "Software"), to deal in the Software without restriction, including |  | ||||||
|  * without limitation the rights to use, copy, modify, merge, publish, |  | ||||||
|  * distribute, sublicense, and/or sell copies of the Software, and to |  | ||||||
|  * permit persons to whom the Software is furnished to do so, subject to |  | ||||||
|  * the following conditions: |  | ||||||
|  * |  * | ||||||
|  * The above copyright notice and this permission notice (including the |  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  * next paragraph) shall be included in all copies or substantial |  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  * portions of the Software. |  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL | ||||||
|  * |  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |  * OTHER DEALINGS IN THE SOFTWARE. | ||||||
|  * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |  | ||||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |  | ||||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |  | ||||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |  | ||||||
|  * |  * | ||||||
|  |  * Authors: Ben Skeggs | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /*
 | #include <subdev/mc.h> | ||||||
|  * Authors: |  | ||||||
|  *   Ben Skeggs <darktama@iinet.net.au> |  | ||||||
|  */ |  | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "nouveau_drm.h" | ||||||
| #include "drm.h" | #include "nv50_display.h" | ||||||
| #include <nouveau_drm.h> |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_reg.h" |  | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| nouveau_irq_preinstall(struct drm_device *dev) | nouveau_irq_preinstall(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	/* Master disable */ | 	nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000); | ||||||
| 	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nouveau_irq_postinstall(struct drm_device *dev) | nouveau_irq_postinstall(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	nv_wr32(nouveau_dev(dev), 0x000140, 0x00000001); | ||||||
| 
 |  | ||||||
| 	/* Master enable */ |  | ||||||
| 	nv_wr32(dev, NV03_PMC_INTR_EN_0, NV_PMC_INTR_EN_0_MASTER_ENABLE); |  | ||||||
| 	if (dev_priv->msi_enabled) |  | ||||||
| 		nv_wr08(dev, 0x00088068, 0xff); |  | ||||||
| 
 |  | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| nouveau_irq_uninstall(struct drm_device *dev) | nouveau_irq_uninstall(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	/* Master disable */ | 	nv_wr32(nouveau_dev(dev), 0x000140, 0x00000000); | ||||||
| 	nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| irqreturn_t | irqreturn_t | ||||||
| nouveau_irq_handler(DRM_IRQ_ARGS) | nouveau_irq_handler(DRM_IRQ_ARGS) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = (struct drm_device *)arg; | 	struct drm_device *dev = arg; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	unsigned long flags; | 	struct nouveau_mc *pmc = nouveau_mc(device); | ||||||
| 	u32 stat; | 	u32 stat; | ||||||
| 	int i; |  | ||||||
| 
 | 
 | ||||||
| 	stat = nv_rd32(dev, NV03_PMC_INTR_0); | 	stat = nv_rd32(device, 0x000100); | ||||||
| 	if (stat == 0 || stat == ~0) | 	if (stat == 0 || stat == ~0) | ||||||
| 		return IRQ_NONE; | 		return IRQ_NONE; | ||||||
| 
 | 
 | ||||||
| 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 	nv_subdev(pmc)->intr(nv_subdev(pmc)); | ||||||
| 	for (i = 0; i < 32 && stat; i++) { |  | ||||||
| 		if (!(stat & (1 << i)) || !dev_priv->irq_handler[i]) |  | ||||||
| 			continue; |  | ||||||
| 
 | 
 | ||||||
| 		dev_priv->irq_handler[i](dev); | 	if (device->card_type >= NV_D0) { | ||||||
| 		stat &= ~(1 << i); | 		if (nv_rd32(device, 0x000100) & 0x04000000) | ||||||
|  | 			nvd0_display_intr(dev); | ||||||
|  | 	} else | ||||||
|  | 	if (device->card_type >= NV_50) { | ||||||
|  | 		if (nv_rd32(device, 0x000100) & 0x04000000) | ||||||
|  | 			nv50_display_intr(dev); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_intr(dev); |  | ||||||
| 
 |  | ||||||
| 	if (dev_priv->msi_enabled) |  | ||||||
| 		nv_wr08(dev, 0x00088068, 0xff); |  | ||||||
| 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |  | ||||||
| 
 |  | ||||||
| 	return IRQ_HANDLED; | 	return IRQ_HANDLED; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nouveau_irq_init(struct drm_device *dev) | nouveau_irq_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	if (nouveau_msi != 0 && dev_priv->card_type >= NV_50) { |  | ||||||
| 		ret = pci_enable_msi(dev->pdev); |  | ||||||
| 		if (ret == 0) { |  | ||||||
| 			NV_INFO(dev, "enabled MSI\n"); |  | ||||||
| 			dev_priv->msi_enabled = true; |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return drm_irq_install(dev); | 	return drm_irq_install(dev); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| nouveau_irq_fini(struct drm_device *dev) | nouveau_irq_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 
 |  | ||||||
| 	drm_irq_uninstall(dev); | 	drm_irq_uninstall(dev); | ||||||
| 	if (dev_priv->msi_enabled) |  | ||||||
| 		pci_disable_msi(dev->pdev); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_irq_register(struct drm_device *dev, int status_bit, |  | ||||||
| 		     void (*handler)(struct drm_device *)) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	unsigned long flags; |  | ||||||
| 
 |  | ||||||
| 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |  | ||||||
| 	dev_priv->irq_handler[status_bit] = handler; |  | ||||||
| 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void |  | ||||||
| nouveau_irq_unregister(struct drm_device *dev, int status_bit) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	unsigned long flags; |  | ||||||
| 
 |  | ||||||
| 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |  | ||||||
| 	dev_priv->irq_handler[status_bit] = NULL; |  | ||||||
| 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |  | ||||||
| } | } | ||||||
|  |  | ||||||
							
								
								
									
										11
									
								
								drivers/gpu/drm/nouveau/nouveau_irq.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								drivers/gpu/drm/nouveau/nouveau_irq.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | #ifndef __NOUVEAU_IRQ_H__ | ||||||
|  | #define __NOUVEAU_IRQ_H__ | ||||||
|  | 
 | ||||||
|  | extern int         nouveau_irq_init(struct drm_device *); | ||||||
|  | extern void        nouveau_irq_fini(struct drm_device *); | ||||||
|  | extern irqreturn_t nouveau_irq_handler(DRM_IRQ_ARGS); | ||||||
|  | extern void        nouveau_irq_preinstall(struct drm_device *); | ||||||
|  | extern int         nouveau_irq_postinstall(struct drm_device *); | ||||||
|  | extern void        nouveau_irq_uninstall(struct drm_device *); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -30,20 +30,19 @@ | ||||||
|  *    Roy Spliet <r.spliet@student.tudelft.nl> |  *    Roy Spliet <r.spliet@student.tudelft.nl> | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| 
 | #include "nouveau_drm.h" | ||||||
| #include "drmP.h" |  | ||||||
| #include "drm.h" |  | ||||||
| #include "drm_sarea.h" |  | ||||||
| 
 |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/fb.h> | ||||||
|  | 
 | ||||||
| static int | static int | ||||||
| nv40_mem_timing_calc(struct drm_device *dev, u32 freq, | nv40_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		     struct nouveau_pm_tbl_entry *e, u8 len, | 		     struct nouveau_pm_tbl_entry *e, u8 len, | ||||||
| 		     struct nouveau_pm_memtiming *boot, | 		     struct nouveau_pm_memtiming *boot, | ||||||
| 		     struct nouveau_pm_memtiming *t) | 		     struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); | 	t->reg[0] = (e->tRP << 24 | e->tRAS << 16 | e->tRFC << 8 | e->tRC); | ||||||
| 
 | 
 | ||||||
| 	/* XXX: I don't trust the -1's and +1's... they must come
 | 	/* XXX: I don't trust the -1's and +1's... they must come
 | ||||||
|  | @ -59,7 +58,7 @@ nv40_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		     e->tRCDWR << 8 | | 		     e->tRCDWR << 8 | | ||||||
| 		     e->tRCDRD); | 		     e->tRCDRD); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x\n", t->id, | 	NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x\n", t->id, | ||||||
| 		 t->reg[0], t->reg[1], t->reg[2]); | 		 t->reg[0], t->reg[1], t->reg[2]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -70,6 +69,9 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		     struct nouveau_pm_memtiming *boot, | 		     struct nouveau_pm_memtiming *boot, | ||||||
| 		     struct nouveau_pm_memtiming *t) | 		     struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 	uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; | 	uint8_t unk18 = 1, unk20 = 0, unk21 = 0, tmp7_3; | ||||||
| 
 | 
 | ||||||
|  | @ -123,7 +125,7 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; | 		t->reg[7] = 0x4000202 | (e->tCL - 1) << 16; | ||||||
| 
 | 
 | ||||||
| 		/* XXX: P.version == 1 only has DDR2 and GDDR3? */ | 		/* XXX: P.version == 1 only has DDR2 and GDDR3? */ | ||||||
| 		if (nvfb_vram_type(dev) == NV_MEM_TYPE_DDR2) { | 		if (pfb->ram.type == NV_MEM_TYPE_DDR2) { | ||||||
| 			t->reg[5] |= (e->tCL + 3) << 8; | 			t->reg[5] |= (e->tCL + 3) << 8; | ||||||
| 			t->reg[6] |= (t->tCWL - 2) << 8; | 			t->reg[6] |= (t->tCWL - 2) << 8; | ||||||
| 			t->reg[8] |= (e->tCL - 4); | 			t->reg[8] |= (e->tCL - 4); | ||||||
|  | @ -156,11 +158,11 @@ nv50_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 			    0x202; | 			    0x202; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", t->id, | 	NV_DEBUG(drm, "Entry %d: 220: %08x %08x %08x %08x\n", t->id, | ||||||
| 		 t->reg[0], t->reg[1], t->reg[2], t->reg[3]); | 		 t->reg[0], t->reg[1], t->reg[2], t->reg[3]); | ||||||
| 	NV_DEBUG(dev, "         230: %08x %08x %08x %08x\n", | 	NV_DEBUG(drm, "         230: %08x %08x %08x %08x\n", | ||||||
| 		 t->reg[4], t->reg[5], t->reg[6], t->reg[7]); | 		 t->reg[4], t->reg[5], t->reg[6], t->reg[7]); | ||||||
| 	NV_DEBUG(dev, "         240: %08x\n", t->reg[8]); | 	NV_DEBUG(drm, "         240: %08x\n", t->reg[8]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -170,6 +172,8 @@ nvc0_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		     struct nouveau_pm_memtiming *boot, | 		     struct nouveau_pm_memtiming *boot, | ||||||
| 		     struct nouveau_pm_memtiming *t) | 		     struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (e->tCWL > 0) | 	if (e->tCWL > 0) | ||||||
| 		t->tCWL = e->tCWL; | 		t->tCWL = e->tCWL; | ||||||
| 
 | 
 | ||||||
|  | @ -192,9 +196,9 @@ nvc0_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 	t->reg[4] = (boot->reg[4] & 0xfff00fff) | | 	t->reg[4] = (boot->reg[4] & 0xfff00fff) | | ||||||
| 		    (e->tRRD&0x1f) << 15; | 		    (e->tRRD&0x1f) << 15; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "Entry %d: 290: %08x %08x %08x %08x\n", t->id, | 	NV_DEBUG(drm, "Entry %d: 290: %08x %08x %08x %08x\n", t->id, | ||||||
| 		 t->reg[0], t->reg[1], t->reg[2], t->reg[3]); | 		 t->reg[0], t->reg[1], t->reg[2], t->reg[3]); | ||||||
| 	NV_DEBUG(dev, "         2a0: %08x\n", t->reg[4]); | 	NV_DEBUG(drm, "         2a0: %08x\n", t->reg[4]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -208,6 +212,8 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, | ||||||
| 		    struct nouveau_pm_memtiming *boot, | 		    struct nouveau_pm_memtiming *boot, | ||||||
| 		    struct nouveau_pm_memtiming *t) | 		    struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	t->drive_strength = 0; | 	t->drive_strength = 0; | ||||||
| 	if (len < 15) { | 	if (len < 15) { | ||||||
| 		t->odt = boot->odt; | 		t->odt = boot->odt; | ||||||
|  | @ -216,17 +222,17 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tCL >= NV_MEM_CL_DDR2_MAX) { | 	if (e->tCL >= NV_MEM_CL_DDR2_MAX) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); | 		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tWR >= NV_MEM_WR_DDR2_MAX) { | 	if (e->tWR >= NV_MEM_WR_DDR2_MAX) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); | 		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (t->odt > 3) { | 	if (t->odt > 3) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid odt value, assuming disabled: %x", | 		NV_WARN(drm, "(%u) Invalid odt value, assuming disabled: %x", | ||||||
| 			t->id, t->odt); | 			t->id, t->odt); | ||||||
| 		t->odt = 0; | 		t->odt = 0; | ||||||
| 	} | 	} | ||||||
|  | @ -238,7 +244,7 @@ nouveau_mem_ddr2_mr(struct drm_device *dev, u32 freq, | ||||||
| 		   (t->odt & 0x1) << 2 | | 		   (t->odt & 0x1) << 2 | | ||||||
| 		   (t->odt & 0x2) << 5; | 		   (t->odt & 0x2) << 5; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "(%u) MR: %08x", t->id, t->mr[0]); | 	NV_DEBUG(drm, "(%u) MR: %08x", t->id, t->mr[0]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -251,6 +257,7 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, | ||||||
| 		    struct nouveau_pm_memtiming *boot, | 		    struct nouveau_pm_memtiming *boot, | ||||||
| 		    struct nouveau_pm_memtiming *t) | 		    struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u8 cl = e->tCL - 4; | 	u8 cl = e->tCL - 4; | ||||||
| 
 | 
 | ||||||
| 	t->drive_strength = 0; | 	t->drive_strength = 0; | ||||||
|  | @ -261,17 +268,17 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) { | 	if (e->tCL >= NV_MEM_CL_DDR3_MAX || e->tCL < 4) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); | 		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) { | 	if (e->tWR >= NV_MEM_WR_DDR3_MAX || e->tWR < 4) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); | 		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tCWL < 5) { | 	if (e->tCWL < 5) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tCWL: %u", t->id, e->tCWL); | 		NV_WARN(drm, "(%u) Invalid tCWL: %u", t->id, e->tCWL); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -286,7 +293,7 @@ nouveau_mem_ddr3_mr(struct drm_device *dev, u32 freq, | ||||||
| 		   (t->odt & 0x4) << 7; | 		   (t->odt & 0x4) << 7; | ||||||
| 	t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3; | 	t->mr[2] = (boot->mr[2] & 0x20ffb7) | (e->tCWL - 5) << 3; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]); | 	NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[2]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -301,6 +308,8 @@ nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, | ||||||
| 		     struct nouveau_pm_memtiming *boot, | 		     struct nouveau_pm_memtiming *boot, | ||||||
| 		     struct nouveau_pm_memtiming *t) | 		     struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (len < 15) { | 	if (len < 15) { | ||||||
| 		t->drive_strength = boot->drive_strength; | 		t->drive_strength = boot->drive_strength; | ||||||
| 		t->odt = boot->odt; | 		t->odt = boot->odt; | ||||||
|  | @ -310,17 +319,17 @@ nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tCL >= NV_MEM_CL_GDDR3_MAX) { | 	if (e->tCL >= NV_MEM_CL_GDDR3_MAX) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); | 		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tWR >= NV_MEM_WR_GDDR3_MAX) { | 	if (e->tWR >= NV_MEM_WR_GDDR3_MAX) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); | 		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (t->odt > 3) { | 	if (t->odt > 3) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x", | 		NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x", | ||||||
| 			t->id, t->odt); | 			t->id, t->odt); | ||||||
| 		t->odt = 0; | 		t->odt = 0; | ||||||
| 	} | 	} | ||||||
|  | @ -334,7 +343,7 @@ nouveau_mem_gddr3_mr(struct drm_device *dev, u32 freq, | ||||||
| 		   (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4; | 		   (nv_mem_wr_lut_gddr3[e->tWR] & 0xf) << 4; | ||||||
| 	t->mr[2] = boot->mr[2]; | 	t->mr[2] = boot->mr[2]; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "(%u) MR: %08x %08x %08x", t->id, | 	NV_DEBUG(drm, "(%u) MR: %08x %08x %08x", t->id, | ||||||
| 		      t->mr[0], t->mr[1], t->mr[2]); | 		      t->mr[0], t->mr[1], t->mr[2]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  | @ -345,6 +354,8 @@ nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, | ||||||
| 		     struct nouveau_pm_memtiming *boot, | 		     struct nouveau_pm_memtiming *boot, | ||||||
| 		     struct nouveau_pm_memtiming *t) | 		     struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (len < 15) { | 	if (len < 15) { | ||||||
| 		t->drive_strength = boot->drive_strength; | 		t->drive_strength = boot->drive_strength; | ||||||
| 		t->odt = boot->odt; | 		t->odt = boot->odt; | ||||||
|  | @ -354,17 +365,17 @@ nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tCL >= NV_MEM_CL_GDDR5_MAX) { | 	if (e->tCL >= NV_MEM_CL_GDDR5_MAX) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tCL: %u", t->id, e->tCL); | 		NV_WARN(drm, "(%u) Invalid tCL: %u", t->id, e->tCL); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (e->tWR >= NV_MEM_WR_GDDR5_MAX) { | 	if (e->tWR >= NV_MEM_WR_GDDR5_MAX) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid tWR: %u", t->id, e->tWR); | 		NV_WARN(drm, "(%u) Invalid tWR: %u", t->id, e->tWR); | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (t->odt > 3) { | 	if (t->odt > 3) { | ||||||
| 		NV_WARN(dev, "(%u) Invalid odt value, assuming autocal: %x", | 		NV_WARN(drm, "(%u) Invalid odt value, assuming autocal: %x", | ||||||
| 			t->id, t->odt); | 			t->id, t->odt); | ||||||
| 		t->odt = 0; | 		t->odt = 0; | ||||||
| 	} | 	} | ||||||
|  | @ -376,7 +387,7 @@ nouveau_mem_gddr5_mr(struct drm_device *dev, u32 freq, | ||||||
| 		   t->drive_strength | | 		   t->drive_strength | | ||||||
| 		   (t->odt << 2); | 		   (t->odt << 2); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]); | 	NV_DEBUG(drm, "(%u) MR: %08x %08x", t->id, t->mr[0], t->mr[1]); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -384,8 +395,9 @@ int | ||||||
| nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, | nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 			struct nouveau_pm_memtiming *t) | 			struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
|  | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_memtiming *boot = &pm->boot.timing; | 	struct nouveau_pm_memtiming *boot = &pm->boot.timing; | ||||||
| 	struct nouveau_pm_tbl_entry *e; | 	struct nouveau_pm_tbl_entry *e; | ||||||
| 	u8 ver, len, *ptr, *ramcfg; | 	u8 ver, len, *ptr, *ramcfg; | ||||||
|  | @ -400,7 +412,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 
 | 
 | ||||||
| 	t->tCWL = boot->tCWL; | 	t->tCWL = boot->tCWL; | ||||||
| 
 | 
 | ||||||
| 	switch (dev_priv->card_type) { | 	switch (device->card_type) { | ||||||
| 	case NV_40: | 	case NV_40: | ||||||
| 		ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t); | 		ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t); | ||||||
| 		break; | 		break; | ||||||
|  | @ -416,7 +428,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	switch (nvfb_vram_type(dev) * !ret) { | 	switch (pfb->ram.type * !ret) { | ||||||
| 	case NV_MEM_TYPE_GDDR3: | 	case NV_MEM_TYPE_GDDR3: | ||||||
| 		ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); | 		ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t); | ||||||
| 		break; | 		break; | ||||||
|  | @ -443,7 +455,7 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| 		else | 		else | ||||||
| 			dll_off = !!(ramcfg[2] & 0x40); | 			dll_off = !!(ramcfg[2] & 0x40); | ||||||
| 
 | 
 | ||||||
| 		switch (nvfb_vram_type(dev)) { | 		switch (pfb->ram.type) { | ||||||
| 		case NV_MEM_TYPE_GDDR3: | 		case NV_MEM_TYPE_GDDR3: | ||||||
| 			t->mr[1] &= ~0x00000040; | 			t->mr[1] &= ~0x00000040; | ||||||
| 			t->mr[1] |=  0x00000040 * dll_off; | 			t->mr[1] |=  0x00000040 * dll_off; | ||||||
|  | @ -461,11 +473,12 @@ nouveau_mem_timing_calc(struct drm_device *dev, u32 freq, | ||||||
| void | void | ||||||
| nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) | nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
| 	u32 timing_base, timing_regs, mr_base; | 	u32 timing_base, timing_regs, mr_base; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= 0xC0) { | 	if (device->card_type >= 0xC0) { | ||||||
| 		timing_base = 0x10f290; | 		timing_base = 0x10f290; | ||||||
| 		mr_base = 0x10f300; | 		mr_base = 0x10f300; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -475,7 +488,7 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) | ||||||
| 
 | 
 | ||||||
| 	t->id = -1; | 	t->id = -1; | ||||||
| 
 | 
 | ||||||
| 	switch (dev_priv->card_type) { | 	switch (device->card_type) { | ||||||
| 	case NV_50: | 	case NV_50: | ||||||
| 		timing_regs = 9; | 		timing_regs = 9; | ||||||
| 		break; | 		break; | ||||||
|  | @ -492,24 +505,24 @@ nouveau_mem_timing_read(struct drm_device *dev, struct nouveau_pm_memtiming *t) | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	for(i = 0; i < timing_regs; i++) | 	for(i = 0; i < timing_regs; i++) | ||||||
| 		t->reg[i] = nv_rd32(dev, timing_base + (0x04 * i)); | 		t->reg[i] = nv_rd32(device, timing_base + (0x04 * i)); | ||||||
| 
 | 
 | ||||||
| 	t->tCWL = 0; | 	t->tCWL = 0; | ||||||
| 	if (dev_priv->card_type < NV_C0) { | 	if (device->card_type < NV_C0) { | ||||||
| 		t->tCWL = ((nv_rd32(dev, 0x100228) & 0x0f000000) >> 24) + 1; | 		t->tCWL = ((nv_rd32(device, 0x100228) & 0x0f000000) >> 24) + 1; | ||||||
| 	} else if (dev_priv->card_type <= NV_D0) { | 	} else if (device->card_type <= NV_D0) { | ||||||
| 		t->tCWL = ((nv_rd32(dev, 0x10f294) & 0x00000f80) >> 7); | 		t->tCWL = ((nv_rd32(device, 0x10f294) & 0x00000f80) >> 7); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	t->mr[0] = nv_rd32(dev, mr_base); | 	t->mr[0] = nv_rd32(device, mr_base); | ||||||
| 	t->mr[1] = nv_rd32(dev, mr_base + 0x04); | 	t->mr[1] = nv_rd32(device, mr_base + 0x04); | ||||||
| 	t->mr[2] = nv_rd32(dev, mr_base + 0x20); | 	t->mr[2] = nv_rd32(device, mr_base + 0x20); | ||||||
| 	t->mr[3] = nv_rd32(dev, mr_base + 0x24); | 	t->mr[3] = nv_rd32(device, mr_base + 0x24); | ||||||
| 
 | 
 | ||||||
| 	t->odt = 0; | 	t->odt = 0; | ||||||
| 	t->drive_strength = 0; | 	t->drive_strength = 0; | ||||||
| 
 | 
 | ||||||
| 	switch (nvfb_vram_type(dev)) { | 	switch (pfb->ram.type) { | ||||||
| 	case NV_MEM_TYPE_DDR3: | 	case NV_MEM_TYPE_DDR3: | ||||||
| 		t->odt |= (t->mr[1] & 0x200) >> 7; | 		t->odt |= (t->mr[1] & 0x200) >> 7; | ||||||
| 	case NV_MEM_TYPE_DDR2: | 	case NV_MEM_TYPE_DDR2: | ||||||
|  | @ -530,13 +543,15 @@ int | ||||||
| nouveau_mem_exec(struct nouveau_mem_exec_func *exec, | nouveau_mem_exec(struct nouveau_mem_exec_func *exec, | ||||||
| 		 struct nouveau_pm_level *perflvl) | 		 struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = exec->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(exec->dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
| 	struct nouveau_pm_memtiming *info = &perflvl->timing; | 	struct nouveau_pm_memtiming *info = &perflvl->timing; | ||||||
| 	u32 tMRD = 1000, tCKSRE = 0, tCKSRX = 0, tXS = 0, tDLLK = 0; | 	u32 tMRD = 1000, tCKSRE = 0, tCKSRX = 0, tXS = 0, tDLLK = 0; | ||||||
| 	u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; | 	u32 mr[3] = { info->mr[0], info->mr[1], info->mr[2] }; | ||||||
| 	u32 mr1_dlloff; | 	u32 mr1_dlloff; | ||||||
| 
 | 
 | ||||||
| 	switch (nvfb_vram_type(dev_priv->dev)) { | 	switch (pfb->ram.type) { | ||||||
| 	case NV_MEM_TYPE_DDR2: | 	case NV_MEM_TYPE_DDR2: | ||||||
| 		tDLLK = 2000; | 		tDLLK = 2000; | ||||||
| 		mr1_dlloff = 0x00000001; | 		mr1_dlloff = 0x00000001; | ||||||
|  | @ -552,12 +567,12 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, | ||||||
| 		mr1_dlloff = 0x00000040; | 		mr1_dlloff = 0x00000040; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(exec->dev, "cannot reclock unsupported memtype\n"); | 		NV_ERROR(drm, "cannot reclock unsupported memtype\n"); | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* fetch current MRs */ | 	/* fetch current MRs */ | ||||||
| 	switch (nvfb_vram_type(dev_priv->dev)) { | 	switch (pfb->ram.type) { | ||||||
| 	case NV_MEM_TYPE_GDDR3: | 	case NV_MEM_TYPE_GDDR3: | ||||||
| 	case NV_MEM_TYPE_DDR3: | 	case NV_MEM_TYPE_DDR3: | ||||||
| 		mr[2] = exec->mrg(exec, 2); | 		mr[2] = exec->mrg(exec, 2); | ||||||
|  | @ -624,7 +639,7 @@ nouveau_mem_exec(struct nouveau_mem_exec_func *exec, | ||||||
| 		exec->mrs (exec, 0, info->mr[0] | 0x00000000); | 		exec->mrs (exec, 0, info->mr[0] | 0x00000000); | ||||||
| 		exec->wait(exec, tMRD); | 		exec->wait(exec, tMRD); | ||||||
| 		exec->wait(exec, tDLLK); | 		exec->wait(exec, tDLLK); | ||||||
| 		if (nvfb_vram_type(dev_priv->dev) == NV_MEM_TYPE_GDDR3) | 		if (pfb->ram.type == NV_MEM_TYPE_GDDR3) | ||||||
| 			exec->precharge(exec); | 			exec->precharge(exec); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -24,14 +24,15 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
| static u8 * | static u8 * | ||||||
| nouveau_perf_table(struct drm_device *dev, u8 *ver) | nouveau_perf_table(struct drm_device *dev, u8 *ver) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 
 | 
 | ||||||
| 	if (!bit_table(dev, 'P', &P) && P.version && P.version <= 2) { | 	if (!bit_table(dev, 'P', &P) && P.version && P.version <= 2) { | ||||||
|  | @ -87,7 +88,7 @@ u8 * | ||||||
| nouveau_perf_rammap(struct drm_device *dev, u32 freq, | nouveau_perf_rammap(struct drm_device *dev, u32 freq, | ||||||
| 		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | 		    u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 	u8 *perf, i = 0; | 	u8 *perf, i = 0; | ||||||
| 
 | 
 | ||||||
|  | @ -114,8 +115,8 @@ nouveau_perf_rammap(struct drm_device *dev, u32 freq, | ||||||
| 		return NULL; | 		return NULL; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset == 0x49 || | 	if (nv_device(drm->device)->chipset == 0x49 || | ||||||
| 	    dev_priv->chipset == 0x4b) | 	    nv_device(drm->device)->chipset == 0x4b) | ||||||
| 		freq /= 2; | 		freq /= 2; | ||||||
| 
 | 
 | ||||||
| 	while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) { | 	while ((perf = nouveau_perf_entry(dev, i++, ver, hdr, cnt, len))) { | ||||||
|  | @ -142,12 +143,13 @@ nouveau_perf_rammap(struct drm_device *dev, u32 freq, | ||||||
| u8 * | u8 * | ||||||
| nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	u8 strap, hdr, cnt; | 	u8 strap, hdr, cnt; | ||||||
| 	u8 *rammap; | 	u8 *rammap; | ||||||
| 
 | 
 | ||||||
| 	strap = (nv_rd32(dev, 0x101000) & 0x0000003c) >> 2; | 	strap = (nv_rd32(device, 0x101000) & 0x0000003c) >> 2; | ||||||
| 	if (bios->ram_restrict_tbl_ptr) | 	if (bios->ram_restrict_tbl_ptr) | ||||||
| 		strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; | 		strap = bios->data[bios->ram_restrict_tbl_ptr + strap]; | ||||||
| 
 | 
 | ||||||
|  | @ -161,8 +163,8 @@ nouveau_perf_ramcfg(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | ||||||
| u8 * | u8 * | ||||||
| nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 	u8 *perf, *timing = NULL; | 	u8 *perf, *timing = NULL; | ||||||
| 	u8 i = 0, hdr, cnt; | 	u8 i = 0, hdr, cnt; | ||||||
|  | @ -202,20 +204,21 @@ nouveau_perf_timing(struct drm_device *dev, u32 freq, u8 *ver, u8 *len) | ||||||
| static void | static void | ||||||
| legacy_perf_init(struct drm_device *dev) | legacy_perf_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nvbios *bios = &drm->vbios; | ||||||
|  | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	char *perf, *entry, *bmp = &bios->data[bios->offset]; | 	char *perf, *entry, *bmp = &bios->data[bios->offset]; | ||||||
| 	int headerlen, use_straps; | 	int headerlen, use_straps; | ||||||
| 
 | 
 | ||||||
| 	if (bmp[5] < 0x5 || bmp[6] < 0x14) { | 	if (bmp[5] < 0x5 || bmp[6] < 0x14) { | ||||||
| 		NV_DEBUG(dev, "BMP version too old for perf\n"); | 		NV_DEBUG(drm, "BMP version too old for perf\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	perf = ROMPTR(dev, bmp[0x73]); | 	perf = ROMPTR(dev, bmp[0x73]); | ||||||
| 	if (!perf) { | 	if (!perf) { | ||||||
| 		NV_DEBUG(dev, "No memclock table pointer found.\n"); | 		NV_DEBUG(drm, "No memclock table pointer found.\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -231,13 +234,13 @@ legacy_perf_init(struct drm_device *dev) | ||||||
| 		headerlen = (use_straps ? 8 : 2); | 		headerlen = (use_straps ? 8 : 2); | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_WARN(dev, "Unknown memclock table version %x.\n", perf[0]); | 		NV_WARN(drm, "Unknown memclock table version %x.\n", perf[0]); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	entry = perf + headerlen; | 	entry = perf + headerlen; | ||||||
| 	if (use_straps) | 	if (use_straps) | ||||||
| 		entry += (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; | 		entry += (nv_rd32(device, NV_PEXTDEV_BOOT_0) & 0x3c) >> 1; | ||||||
| 
 | 
 | ||||||
| 	sprintf(pm->perflvl[0].name, "performance_level_0"); | 	sprintf(pm->perflvl[0].name, "performance_level_0"); | ||||||
| 	pm->perflvl[0].memory = ROM16(entry[0]) * 20; | 	pm->perflvl[0].memory = ROM16(entry[0]) * 20; | ||||||
|  | @ -247,7 +250,7 @@ legacy_perf_init(struct drm_device *dev) | ||||||
| static void | static void | ||||||
| nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 	u8 *vmap; | 	u8 *vmap; | ||||||
| 	int id; | 	int id; | ||||||
|  | @ -258,7 +261,7 @@ nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	/* boards using voltage table version <0x40 store the voltage
 | 	/* boards using voltage table version <0x40 store the voltage
 | ||||||
| 	 * level directly in the perflvl entry as a multiple of 10mV | 	 * level directly in the perflvl entry as a multiple of 10mV | ||||||
| 	 */ | 	 */ | ||||||
| 	if (dev_priv->engine.pm.voltage.version < 0x40) { | 	if (drm->pm->voltage.version < 0x40) { | ||||||
| 		perflvl->volt_min = id * 10000; | 		perflvl->volt_min = id * 10000; | ||||||
| 		perflvl->volt_max = perflvl->volt_min; | 		perflvl->volt_max = perflvl->volt_min; | ||||||
| 		return; | 		return; | ||||||
|  | @ -268,14 +271,14 @@ nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	 * vbios table containing a min/max voltage value for the perflvl | 	 * vbios table containing a min/max voltage value for the perflvl | ||||||
| 	 */ | 	 */ | ||||||
| 	if (bit_table(dev, 'P', &P) || P.version != 2 || P.length < 34) { | 	if (bit_table(dev, 'P', &P) || P.version != 2 || P.length < 34) { | ||||||
| 		NV_DEBUG(dev, "where's our volt map table ptr? %d %d\n", | 		NV_DEBUG(drm, "where's our volt map table ptr? %d %d\n", | ||||||
| 			 P.version, P.length); | 			 P.version, P.length); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	vmap = ROMPTR(dev, P.data[32]); | 	vmap = ROMPTR(dev, P.data[32]); | ||||||
| 	if (!vmap) { | 	if (!vmap) { | ||||||
| 		NV_DEBUG(dev, "volt map table pointer invalid\n"); | 		NV_DEBUG(drm, "volt map table pointer invalid\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -289,9 +292,9 @@ nouveau_perf_voltage(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| void | void | ||||||
| nouveau_perf_init(struct drm_device *dev) | nouveau_perf_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	u8 *perf, ver, hdr, cnt, len; | 	u8 *perf, ver, hdr, cnt, len; | ||||||
| 	int ret, vid, i = -1; | 	int ret, vid, i = -1; | ||||||
| 
 | 
 | ||||||
|  | @ -328,8 +331,8 @@ nouveau_perf_init(struct drm_device *dev) | ||||||
| 			perflvl->shader = ROM16(perf[6]) * 1000; | 			perflvl->shader = ROM16(perf[6]) * 1000; | ||||||
| 			perflvl->core = perflvl->shader; | 			perflvl->core = perflvl->shader; | ||||||
| 			perflvl->core += (signed char)perf[8] * 1000; | 			perflvl->core += (signed char)perf[8] * 1000; | ||||||
| 			if (dev_priv->chipset == 0x49 || | 			if (nv_device(drm->device)->chipset == 0x49 || | ||||||
| 			    dev_priv->chipset == 0x4b) | 			    nv_device(drm->device)->chipset == 0x4b) | ||||||
| 				perflvl->memory = ROM16(perf[11]) * 1000; | 				perflvl->memory = ROM16(perf[11]) * 1000; | ||||||
| 			else | 			else | ||||||
| 				perflvl->memory = ROM16(perf[11]) * 2000; | 				perflvl->memory = ROM16(perf[11]) * 2000; | ||||||
|  | @ -356,7 +359,7 @@ nouveau_perf_init(struct drm_device *dev) | ||||||
| #define subent(n) ((ROM16(perf[hdr + (n) * len]) & 0xfff) * 1000) | #define subent(n) ((ROM16(perf[hdr + (n) * len]) & 0xfff) * 1000) | ||||||
| 			perflvl->fanspeed = 0; /*XXX*/ | 			perflvl->fanspeed = 0; /*XXX*/ | ||||||
| 			perflvl->volt_min = perf[2]; | 			perflvl->volt_min = perf[2]; | ||||||
| 			if (dev_priv->card_type == NV_50) { | 			if (nv_device(drm->device)->card_type == NV_50) { | ||||||
| 				perflvl->core   = subent(0); | 				perflvl->core   = subent(0); | ||||||
| 				perflvl->shader = subent(1); | 				perflvl->shader = subent(1); | ||||||
| 				perflvl->memory = subent(2); | 				perflvl->memory = subent(2); | ||||||
|  | @ -382,7 +385,7 @@ nouveau_perf_init(struct drm_device *dev) | ||||||
| 		if (pm->voltage.supported && perflvl->volt_min) { | 		if (pm->voltage.supported && perflvl->volt_min) { | ||||||
| 			vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); | 			vid = nouveau_volt_vid_lookup(dev, perflvl->volt_min); | ||||||
| 			if (vid < 0) { | 			if (vid < 0) { | ||||||
| 				NV_DEBUG(dev, "perflvl %d, bad vid\n", i); | 				NV_DEBUG(drm, "perflvl %d, bad vid\n", i); | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -391,7 +394,7 @@ nouveau_perf_init(struct drm_device *dev) | ||||||
| 		ret = nouveau_mem_timing_calc(dev, perflvl->memory, | 		ret = nouveau_mem_timing_calc(dev, perflvl->memory, | ||||||
| 					          &perflvl->timing); | 					          &perflvl->timing); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			NV_DEBUG(dev, "perflvl %d, bad timing: %d\n", i, ret); | 			NV_DEBUG(drm, "perflvl %d, bad timing: %d\n", i, ret); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -22,12 +22,6 @@ | ||||||
|  * Authors: Ben Skeggs |  * Authors: Ben Skeggs | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" |  | ||||||
| 
 |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_pm.h" |  | ||||||
| #include <subdev/bios/gpio.h> |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_ACPI | #ifdef CONFIG_ACPI | ||||||
| #include <linux/acpi.h> | #include <linux/acpi.h> | ||||||
| #endif | #endif | ||||||
|  | @ -35,29 +29,48 @@ | ||||||
| #include <linux/hwmon.h> | #include <linux/hwmon.h> | ||||||
| #include <linux/hwmon-sysfs.h> | #include <linux/hwmon-sysfs.h> | ||||||
| 
 | 
 | ||||||
|  | #include "drmP.h" | ||||||
|  | 
 | ||||||
|  | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_pm.h" | ||||||
|  | 
 | ||||||
|  | #include <subdev/bios/gpio.h> | ||||||
|  | #include <subdev/gpio.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | 
 | ||||||
|  | MODULE_PARM_DESC(perflvl, "Performance level (default: boot)"); | ||||||
|  | static char *nouveau_perflvl; | ||||||
|  | module_param_named(perflvl, nouveau_perflvl, charp, 0400); | ||||||
|  | 
 | ||||||
|  | MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)"); | ||||||
|  | static int nouveau_perflvl_wr; | ||||||
|  | module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); | ||||||
|  | 
 | ||||||
| static int | static int | ||||||
| nouveau_pwmfan_get(struct drm_device *dev) | nouveau_pwmfan_get(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_gpio_func gpio; | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(device); | ||||||
|  | 	struct dcb_gpio_func func; | ||||||
| 	u32 divs, duty; | 	u32 divs, duty; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (!pm->pwm_get) | 	if (!pm->pwm_get) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); | 	ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); | ||||||
| 	if (ret == 0) { | 	if (ret == 0) { | ||||||
| 		ret = pm->pwm_get(dev, gpio.line, &divs, &duty); | 		ret = pm->pwm_get(dev, func.line, &divs, &duty); | ||||||
| 		if (ret == 0 && divs) { | 		if (ret == 0 && divs) { | ||||||
| 			divs = max(divs, duty); | 			divs = max(divs, duty); | ||||||
| 			if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) | 			if (device->card_type <= NV_40 || (func.log[0] & 1)) | ||||||
| 				duty = divs - duty; | 				duty = divs - duty; | ||||||
| 			return (duty * 100) / divs; | 			return (duty * 100) / divs; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return nouveau_gpio_func_get(dev, gpio.func) * 100; | 		return gpio->get(gpio, 0, func.func, func.line) * 100; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return -ENODEV; | 	return -ENODEV; | ||||||
|  | @ -66,30 +79,32 @@ nouveau_pwmfan_get(struct drm_device *dev) | ||||||
| static int | static int | ||||||
| nouveau_pwmfan_set(struct drm_device *dev, int percent) | nouveau_pwmfan_set(struct drm_device *dev, int percent) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_gpio_func gpio; | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(device); | ||||||
|  | 	struct dcb_gpio_func func; | ||||||
| 	u32 divs, duty; | 	u32 divs, duty; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (!pm->pwm_set) | 	if (!pm->pwm_set) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); | 	ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); | ||||||
| 	if (ret == 0) { | 	if (ret == 0) { | ||||||
| 		divs = pm->fan.pwm_divisor; | 		divs = pm->fan.pwm_divisor; | ||||||
| 		if (pm->fan.pwm_freq) { | 		if (pm->fan.pwm_freq) { | ||||||
| 			/*XXX: PNVIO clock more than likely... */ | 			/*XXX: PNVIO clock more than likely... */ | ||||||
| 			divs = 135000 / pm->fan.pwm_freq; | 			divs = 135000 / pm->fan.pwm_freq; | ||||||
| 			if (dev_priv->chipset < 0xa3) | 			if (nv_device(drm->device)->chipset < 0xa3) | ||||||
| 				divs /= 4; | 				divs /= 4; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		duty = ((divs * percent) + 99) / 100; | 		duty = ((divs * percent) + 99) / 100; | ||||||
| 		if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) | 		if (device->card_type <= NV_40 || (func.log[0] & 1)) | ||||||
| 			duty = divs - duty; | 			duty = divs - duty; | ||||||
| 
 | 
 | ||||||
| 		ret = pm->pwm_set(dev, gpio.line, divs, duty); | 		ret = pm->pwm_set(dev, func.line, divs, duty); | ||||||
| 		if (!ret) | 		if (!ret) | ||||||
| 			pm->fan.percent = percent; | 			pm->fan.percent = percent; | ||||||
| 		return ret; | 		return ret; | ||||||
|  | @ -102,8 +117,8 @@ static int | ||||||
| nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, | nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 		       struct nouveau_pm_level *a, struct nouveau_pm_level *b) | 		       struct nouveau_pm_level *a, struct nouveau_pm_level *b) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	/*XXX: not on all boards, we should control based on temperature
 | 	/*XXX: not on all boards, we should control based on temperature
 | ||||||
|  | @ -113,7 +128,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 	if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { | 	if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { | ||||||
| 		ret = nouveau_pwmfan_set(dev, perflvl->fanspeed); | 		ret = nouveau_pwmfan_set(dev, perflvl->fanspeed); | ||||||
| 		if (ret && ret != -ENODEV) { | 		if (ret && ret != -ENODEV) { | ||||||
| 			NV_ERROR(dev, "fanspeed set failed: %d\n", ret); | 			NV_ERROR(drm, "fanspeed set failed: %d\n", ret); | ||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -122,7 +137,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 		if (perflvl->volt_min && b->volt_min > a->volt_min) { | 		if (perflvl->volt_min && b->volt_min > a->volt_min) { | ||||||
| 			ret = pm->voltage_set(dev, perflvl->volt_min); | 			ret = pm->voltage_set(dev, perflvl->volt_min); | ||||||
| 			if (ret) { | 			if (ret) { | ||||||
| 				NV_ERROR(dev, "voltage set failed: %d\n", ret); | 				NV_ERROR(drm, "voltage set failed: %d\n", ret); | ||||||
| 				return ret; | 				return ret; | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | @ -134,8 +149,7 @@ nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| static int | static int | ||||||
| nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	void *state; | 	void *state; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -171,8 +185,9 @@ error: | ||||||
| void | void | ||||||
| nouveau_pm_trigger(struct drm_device *dev) | nouveau_pm_trigger(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_timer *ptimer = nouveau_timer(drm->device); | ||||||
|  | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_profile *profile = NULL; | 	struct nouveau_pm_profile *profile = NULL; | ||||||
| 	struct nouveau_pm_level *perflvl = NULL; | 	struct nouveau_pm_level *perflvl = NULL; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -194,23 +209,22 @@ nouveau_pm_trigger(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	/* change perflvl, if necessary */ | 	/* change perflvl, if necessary */ | ||||||
| 	if (perflvl != pm->cur) { | 	if (perflvl != pm->cur) { | ||||||
| 		u64 time0 = nv_timer_read(dev); | 		u64 time0 = ptimer->read(ptimer); | ||||||
| 
 | 
 | ||||||
| 		NV_INFO(dev, "setting performance level: %d", perflvl->id); | 		NV_INFO(drm, "setting performance level: %d", perflvl->id); | ||||||
| 		ret = nouveau_pm_perflvl_set(dev, perflvl); | 		ret = nouveau_pm_perflvl_set(dev, perflvl); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			NV_INFO(dev, "> reclocking failed: %d\n\n", ret); | 			NV_INFO(drm, "> reclocking failed: %d\n\n", ret); | ||||||
| 
 | 
 | ||||||
| 		NV_INFO(dev, "> reclocking took %lluns\n\n", | 		NV_INFO(drm, "> reclocking took %lluns\n\n", | ||||||
| 			     nv_timer_read(dev) - time0); | 			     ptimer->read(ptimer) - time0); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct nouveau_pm_profile * | static struct nouveau_pm_profile * | ||||||
| profile_find(struct drm_device *dev, const char *string) | profile_find(struct drm_device *dev, const char *string) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_profile *profile; | 	struct nouveau_pm_profile *profile; | ||||||
| 
 | 
 | ||||||
| 	list_for_each_entry(profile, &pm->profiles, head) { | 	list_for_each_entry(profile, &pm->profiles, head) { | ||||||
|  | @ -224,8 +238,7 @@ profile_find(struct drm_device *dev, const char *string) | ||||||
| static int | static int | ||||||
| nouveau_pm_profile_set(struct drm_device *dev, const char *profile) | nouveau_pm_profile_set(struct drm_device *dev, const char *profile) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_profile *ac = NULL, *dc = NULL; | 	struct nouveau_pm_profile *ac = NULL, *dc = NULL; | ||||||
| 	char string[16], *cur = string, *ptr; | 	char string[16], *cur = string, *ptr; | ||||||
| 
 | 
 | ||||||
|  | @ -278,8 +291,7 @@ const struct nouveau_pm_profile_func nouveau_pm_static_profile_func = { | ||||||
| static int | static int | ||||||
| nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	memset(perflvl, 0, sizeof(*perflvl)); | 	memset(perflvl, 0, sizeof(*perflvl)); | ||||||
|  | @ -361,8 +373,7 @@ static ssize_t | ||||||
| nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) | nouveau_pm_get_perflvl(struct device *d, struct device_attribute *a, char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); | 	struct drm_device *dev = pci_get_drvdata(to_pci_dev(d)); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_level cur; | 	struct nouveau_pm_level cur; | ||||||
| 	int len = PAGE_SIZE, ret; | 	int len = PAGE_SIZE, ret; | ||||||
| 	char *ptr = buf; | 	char *ptr = buf; | ||||||
|  | @ -397,8 +408,8 @@ static DEVICE_ATTR(performance_level, S_IRUGO | S_IWUSR, | ||||||
| static int | static int | ||||||
| nouveau_sysfs_init(struct drm_device *dev) | nouveau_sysfs_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct device *d = &dev->pdev->dev; | 	struct device *d = &dev->pdev->dev; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 
 | 
 | ||||||
|  | @ -417,7 +428,7 @@ nouveau_sysfs_init(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 		ret = device_create_file(d, &perflvl->dev_attr); | 		ret = device_create_file(d, &perflvl->dev_attr); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			NV_ERROR(dev, "failed pervlvl %d sysfs: %d\n", | 			NV_ERROR(drm, "failed pervlvl %d sysfs: %d\n", | ||||||
| 				 perflvl->id, i); | 				 perflvl->id, i); | ||||||
| 			perflvl->dev_attr.attr.name = NULL; | 			perflvl->dev_attr.attr.name = NULL; | ||||||
| 			nouveau_pm_fini(dev); | 			nouveau_pm_fini(dev); | ||||||
|  | @ -431,8 +442,7 @@ nouveau_sysfs_init(struct drm_device *dev) | ||||||
| static void | static void | ||||||
| nouveau_sysfs_fini(struct drm_device *dev) | nouveau_sysfs_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct device *d = &dev->pdev->dev; | 	struct device *d = &dev->pdev->dev; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
|  | @ -452,8 +462,7 @@ static ssize_t | ||||||
| nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 
 | 
 | ||||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000); | 	return snprintf(buf, PAGE_SIZE, "%d\n", pm->temp_get(dev)*1000); | ||||||
| } | } | ||||||
|  | @ -464,8 +473,7 @@ static ssize_t | ||||||
| nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) | nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||||||
| 
 | 
 | ||||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000); | 	return snprintf(buf, PAGE_SIZE, "%d\n", temp->down_clock*1000); | ||||||
|  | @ -475,8 +483,7 @@ nouveau_hwmon_set_max_temp(struct device *d, struct device_attribute *a, | ||||||
| 						const char *buf, size_t count) | 						const char *buf, size_t count) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||||||
| 	long value; | 	long value; | ||||||
| 
 | 
 | ||||||
|  | @ -498,8 +505,7 @@ nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, | ||||||
| 							char *buf) | 							char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||||||
| 
 | 
 | ||||||
| 	return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000); | 	return snprintf(buf, PAGE_SIZE, "%d\n", temp->critical*1000); | ||||||
|  | @ -510,8 +516,7 @@ nouveau_hwmon_set_critical_temp(struct device *d, struct device_attribute *a, | ||||||
| 								size_t count) | 								size_t count) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | 	struct nouveau_pm_threshold_temp *temp = &pm->threshold_temp; | ||||||
| 	long value; | 	long value; | ||||||
| 
 | 
 | ||||||
|  | @ -552,28 +557,32 @@ nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, | ||||||
| 			      char *buf) | 			      char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_timer *ptimer = nouveau_timer(drm->device); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
|  | 	struct dcb_gpio_func func; | ||||||
| 	u32 cycles, cur, prev; | 	u32 cycles, cur, prev; | ||||||
| 	u64 start; | 	u64 start; | ||||||
| 
 | 
 | ||||||
| 	if (!nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) | 	if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 
 | 
 | ||||||
| 	/* Monitor the GPIO input 0x3b for 250ms.
 | 	/* Monitor the GPIO input 0x3b for 250ms.
 | ||||||
| 	 * When the fan spins, it changes the value of GPIO FAN_SENSE. | 	 * When the fan spins, it changes the value of GPIO FAN_SENSE. | ||||||
| 	 * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. | 	 * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. | ||||||
| 	 */ | 	 */ | ||||||
| 	start = nv_timer_read(dev); | 	start = ptimer->read(ptimer); | ||||||
| 	prev = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE); | 	prev = gpio->get(gpio, 0, func.func, func.line); | ||||||
| 	cycles = 0; | 	cycles = 0; | ||||||
| 	do { | 	do { | ||||||
| 		cur = nouveau_gpio_func_get(dev, DCB_GPIO_FAN_SENSE); | 		cur = gpio->get(gpio, 0, func.func, func.line); | ||||||
| 		if (prev != cur) { | 		if (prev != cur) { | ||||||
| 			cycles++; | 			cycles++; | ||||||
| 			prev = cur; | 			prev = cur; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ | 		usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ | ||||||
| 	} while (nv_timer_read(dev) - start < 250000000); | 	} while (ptimer->read(ptimer) - start < 250000000); | ||||||
| 
 | 
 | ||||||
| 	/* interpolate to get rpm */ | 	/* interpolate to get rpm */ | ||||||
| 	return sprintf(buf, "%i\n", cycles / 4 * 4 * 60); | 	return sprintf(buf, "%i\n", cycles / 4 * 4 * 60); | ||||||
|  | @ -599,8 +608,7 @@ nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a, | ||||||
| 		       const char *buf, size_t count) | 		       const char *buf, size_t count) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	int ret = -ENODEV; | 	int ret = -ENODEV; | ||||||
| 	long value; | 	long value; | ||||||
| 
 | 
 | ||||||
|  | @ -631,8 +639,7 @@ nouveau_hwmon_get_pwm0_min(struct device *d, | ||||||
| 			   struct device_attribute *a, char *buf) | 			   struct device_attribute *a, char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 
 | 
 | ||||||
| 	return sprintf(buf, "%i\n", pm->fan.min_duty); | 	return sprintf(buf, "%i\n", pm->fan.min_duty); | ||||||
| } | } | ||||||
|  | @ -642,8 +649,7 @@ nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a, | ||||||
| 			   const char *buf, size_t count) | 			   const char *buf, size_t count) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	long value; | 	long value; | ||||||
| 
 | 
 | ||||||
| 	if (kstrtol(buf, 10, &value) == -EINVAL) | 	if (kstrtol(buf, 10, &value) == -EINVAL) | ||||||
|  | @ -672,8 +678,7 @@ nouveau_hwmon_get_pwm0_max(struct device *d, | ||||||
| 			   struct device_attribute *a, char *buf) | 			   struct device_attribute *a, char *buf) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 
 | 
 | ||||||
| 	return sprintf(buf, "%i\n", pm->fan.max_duty); | 	return sprintf(buf, "%i\n", pm->fan.max_duty); | ||||||
| } | } | ||||||
|  | @ -683,8 +688,7 @@ nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a, | ||||||
| 			   const char *buf, size_t count) | 			   const char *buf, size_t count) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = dev_get_drvdata(d); | 	struct drm_device *dev = dev_get_drvdata(d); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	long value; | 	long value; | ||||||
| 
 | 
 | ||||||
| 	if (kstrtol(buf, 10, &value) == -EINVAL) | 	if (kstrtol(buf, 10, &value) == -EINVAL) | ||||||
|  | @ -741,8 +745,11 @@ static const struct attribute_group hwmon_pwm_fan_attrgroup = { | ||||||
| static int | static int | ||||||
| nouveau_hwmon_init(struct drm_device *dev) | nouveau_hwmon_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
|  | 	struct dcb_gpio_func func; | ||||||
|  | 
 | ||||||
| #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) | #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) | ||||||
| 	struct device *hwmon_dev; | 	struct device *hwmon_dev; | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
|  | @ -753,8 +760,7 @@ nouveau_hwmon_init(struct drm_device *dev) | ||||||
| 	hwmon_dev = hwmon_device_register(&dev->pdev->dev); | 	hwmon_dev = hwmon_device_register(&dev->pdev->dev); | ||||||
| 	if (IS_ERR(hwmon_dev)) { | 	if (IS_ERR(hwmon_dev)) { | ||||||
| 		ret = PTR_ERR(hwmon_dev); | 		ret = PTR_ERR(hwmon_dev); | ||||||
| 		NV_ERROR(dev, | 		NV_ERROR(drm, "Unable to register hwmon device: %d\n", ret); | ||||||
| 			"Unable to register hwmon device: %d\n", ret); |  | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 	dev_set_drvdata(hwmon_dev, dev); | 	dev_set_drvdata(hwmon_dev, dev); | ||||||
|  | @ -778,7 +784,7 @@ nouveau_hwmon_init(struct drm_device *dev) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* if the card can read the fan rpm */ | 	/* if the card can read the fan rpm */ | ||||||
| 	if (nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) { | 	if (!gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) { | ||||||
| 		ret = sysfs_create_group(&dev->pdev->dev.kobj, | 		ret = sysfs_create_group(&dev->pdev->dev.kobj, | ||||||
| 					 &hwmon_fan_rpm_attrgroup); | 					 &hwmon_fan_rpm_attrgroup); | ||||||
| 		if (ret) | 		if (ret) | ||||||
|  | @ -790,7 +796,7 @@ nouveau_hwmon_init(struct drm_device *dev) | ||||||
| 	return 0; | 	return 0; | ||||||
| 
 | 
 | ||||||
| error: | error: | ||||||
| 	NV_ERROR(dev, "Unable to create some hwmon sysfs files: %d\n", ret); | 	NV_ERROR(drm, "Unable to create some hwmon sysfs files: %d\n", ret); | ||||||
| 	hwmon_device_unregister(hwmon_dev); | 	hwmon_device_unregister(hwmon_dev); | ||||||
| 	pm->hwmon = NULL; | 	pm->hwmon = NULL; | ||||||
| 	return ret; | 	return ret; | ||||||
|  | @ -804,8 +810,7 @@ static void | ||||||
| nouveau_hwmon_fini(struct drm_device *dev) | nouveau_hwmon_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) | #if defined(CONFIG_HWMON) || (defined(MODULE) && defined(CONFIG_HWMON_MODULE)) | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 
 | 
 | ||||||
| 	if (pm->hwmon) { | 	if (pm->hwmon) { | ||||||
| 		sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); | 		sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); | ||||||
|  | @ -823,16 +828,15 @@ nouveau_hwmon_fini(struct drm_device *dev) | ||||||
| static int | static int | ||||||
| nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) | nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = | 	struct nouveau_pm *pm = container_of(nb, struct nouveau_pm, acpi_nb); | ||||||
| 		container_of(nb, struct drm_nouveau_private, engine.pm.acpi_nb); | 	struct nouveau_drm *drm = nouveau_drm(pm->dev); | ||||||
| 	struct drm_device *dev = dev_priv->dev; |  | ||||||
| 	struct acpi_bus_event *entry = (struct acpi_bus_event *)data; | 	struct acpi_bus_event *entry = (struct acpi_bus_event *)data; | ||||||
| 
 | 
 | ||||||
| 	if (strcmp(entry->device_class, "ac_adapter") == 0) { | 	if (strcmp(entry->device_class, "ac_adapter") == 0) { | ||||||
| 		bool ac = power_supply_is_system_supplied(); | 		bool ac = power_supply_is_system_supplied(); | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG(dev, "power supply changed: %s\n", ac ? "AC" : "DC"); | 		NV_DEBUG(drm, "power supply changed: %s\n", ac ? "AC" : "DC"); | ||||||
| 		nouveau_pm_trigger(dev); | 		nouveau_pm_trigger(pm->dev); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return NOTIFY_OK; | 	return NOTIFY_OK; | ||||||
|  | @ -842,11 +846,72 @@ nouveau_pm_acpi_event(struct notifier_block *nb, unsigned long val, void *data) | ||||||
| int | int | ||||||
| nouveau_pm_init(struct drm_device *dev) | nouveau_pm_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_pm *pm; | ||||||
| 	char info[256]; | 	char info[256]; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 
 | 
 | ||||||
|  | 	pm = drm->pm = kzalloc(sizeof(*pm), GFP_KERNEL); | ||||||
|  | 	if (!pm) | ||||||
|  | 		return -ENOMEM; | ||||||
|  | 
 | ||||||
|  | 	pm->dev = dev; | ||||||
|  | 
 | ||||||
|  | 	if (device->card_type < NV_40) { | ||||||
|  | 		pm->clocks_get = nv04_pm_clocks_get; | ||||||
|  | 		pm->clocks_pre = nv04_pm_clocks_pre; | ||||||
|  | 		pm->clocks_set = nv04_pm_clocks_set; | ||||||
|  | 		if (nouveau_gpio(drm->device)) { | ||||||
|  | 			pm->voltage_get = nouveau_voltage_gpio_get; | ||||||
|  | 			pm->voltage_set = nouveau_voltage_gpio_set; | ||||||
|  | 		} | ||||||
|  | 	} else | ||||||
|  | 	if (device->card_type < NV_50) { | ||||||
|  | 		pm->clocks_get = nv40_pm_clocks_get; | ||||||
|  | 		pm->clocks_pre = nv40_pm_clocks_pre; | ||||||
|  | 		pm->clocks_set = nv40_pm_clocks_set; | ||||||
|  | 		pm->voltage_get = nouveau_voltage_gpio_get; | ||||||
|  | 		pm->voltage_set = nouveau_voltage_gpio_set; | ||||||
|  | 		pm->temp_get = nv40_temp_get; | ||||||
|  | 		pm->pwm_get = nv40_pm_pwm_get; | ||||||
|  | 		pm->pwm_set = nv40_pm_pwm_set; | ||||||
|  | 	} else | ||||||
|  | 	if (device->card_type < NV_C0) { | ||||||
|  | 		if (device->chipset <  0xa3 || | ||||||
|  | 		    device->chipset == 0xaa || | ||||||
|  | 		    device->chipset == 0xac) { | ||||||
|  | 			pm->clocks_get = nv50_pm_clocks_get; | ||||||
|  | 			pm->clocks_pre = nv50_pm_clocks_pre; | ||||||
|  | 			pm->clocks_set = nv50_pm_clocks_set; | ||||||
|  | 		} else { | ||||||
|  | 			pm->clocks_get = nva3_pm_clocks_get; | ||||||
|  | 			pm->clocks_pre = nva3_pm_clocks_pre; | ||||||
|  | 			pm->clocks_set = nva3_pm_clocks_set; | ||||||
|  | 		} | ||||||
|  | 		pm->voltage_get = nouveau_voltage_gpio_get; | ||||||
|  | 		pm->voltage_set = nouveau_voltage_gpio_set; | ||||||
|  | 		if (device->chipset == 0x50) | ||||||
|  | 			pm->temp_get = nv40_temp_get; | ||||||
|  | 		else | ||||||
|  | 			pm->temp_get = nv84_temp_get; | ||||||
|  | 		pm->pwm_get = nv50_pm_pwm_get; | ||||||
|  | 		pm->pwm_set = nv50_pm_pwm_set; | ||||||
|  | 	} else | ||||||
|  | 	if (device->card_type < NV_E0) { | ||||||
|  | 		pm->clocks_get = nvc0_pm_clocks_get; | ||||||
|  | 		pm->clocks_pre = nvc0_pm_clocks_pre; | ||||||
|  | 		pm->clocks_set = nvc0_pm_clocks_set; | ||||||
|  | 		pm->voltage_get = nouveau_voltage_gpio_get; | ||||||
|  | 		pm->voltage_set = nouveau_voltage_gpio_set; | ||||||
|  | 		pm->temp_get = nv84_temp_get; | ||||||
|  | 		if (device->card_type < NV_D0) { | ||||||
|  | 			pm->pwm_get = nv50_pm_pwm_get; | ||||||
|  | 			pm->pwm_set = nv50_pm_pwm_set; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| 	/* parse aux tables from vbios */ | 	/* parse aux tables from vbios */ | ||||||
| 	nouveau_volt_init(dev); | 	nouveau_volt_init(dev); | ||||||
| 	nouveau_temp_init(dev); | 	nouveau_temp_init(dev); | ||||||
|  | @ -854,7 +919,7 @@ nouveau_pm_init(struct drm_device *dev) | ||||||
| 	/* determine current ("boot") performance level */ | 	/* determine current ("boot") performance level */ | ||||||
| 	ret = nouveau_pm_perflvl_get(dev, &pm->boot); | 	ret = nouveau_pm_perflvl_get(dev, &pm->boot); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "failed to determine boot perflvl\n"); | 		NV_ERROR(drm, "failed to determine boot perflvl\n"); | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -874,14 +939,14 @@ nouveau_pm_init(struct drm_device *dev) | ||||||
| 	nouveau_perf_init(dev); | 	nouveau_perf_init(dev); | ||||||
| 
 | 
 | ||||||
| 	/* display available performance levels */ | 	/* display available performance levels */ | ||||||
| 	NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl); | 	NV_INFO(drm, "%d available performance level(s)\n", pm->nr_perflvl); | ||||||
| 	for (i = 0; i < pm->nr_perflvl; i++) { | 	for (i = 0; i < pm->nr_perflvl; i++) { | ||||||
| 		nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); | 		nouveau_pm_perflvl_info(&pm->perflvl[i], info, sizeof(info)); | ||||||
| 		NV_INFO(dev, "%d:%s", pm->perflvl[i].id, info); | 		NV_INFO(drm, "%d:%s", pm->perflvl[i].id, info); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); | 	nouveau_pm_perflvl_info(&pm->boot, info, sizeof(info)); | ||||||
| 	NV_INFO(dev, "c:%s", info); | 	NV_INFO(drm, "c:%s", info); | ||||||
| 
 | 
 | ||||||
| 	/* switch performance levels now if requested */ | 	/* switch performance levels now if requested */ | ||||||
| 	if (nouveau_perflvl != NULL) | 	if (nouveau_perflvl != NULL) | ||||||
|  | @ -903,8 +968,7 @@ nouveau_pm_init(struct drm_device *dev) | ||||||
| void | void | ||||||
| nouveau_pm_fini(struct drm_device *dev) | nouveau_pm_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_profile *profile, *tmp; | 	struct nouveau_pm_profile *profile, *tmp; | ||||||
| 
 | 
 | ||||||
| 	list_for_each_entry_safe(profile, tmp, &pm->profiles, head) { | 	list_for_each_entry_safe(profile, tmp, &pm->profiles, head) { | ||||||
|  | @ -924,13 +988,15 @@ nouveau_pm_fini(struct drm_device *dev) | ||||||
| #endif | #endif | ||||||
| 	nouveau_hwmon_fini(dev); | 	nouveau_hwmon_fini(dev); | ||||||
| 	nouveau_sysfs_fini(dev); | 	nouveau_sysfs_fini(dev); | ||||||
|  | 
 | ||||||
|  | 	nouveau_drm(dev)->pm = NULL; | ||||||
|  | 	kfree(pm); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| nouveau_pm_resume(struct drm_device *dev) | nouveau_pm_resume(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_level *perflvl; | 	struct nouveau_pm_level *perflvl; | ||||||
| 
 | 
 | ||||||
| 	if (!pm->cur || pm->cur == &pm->boot) | 	if (!pm->cur || pm->cur == &pm->boot) | ||||||
|  |  | ||||||
|  | @ -25,6 +25,178 @@ | ||||||
| #ifndef __NOUVEAU_PM_H__ | #ifndef __NOUVEAU_PM_H__ | ||||||
| #define __NOUVEAU_PM_H__ | #define __NOUVEAU_PM_H__ | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_voltage_level { | ||||||
|  | 	u32 voltage; /* microvolts */ | ||||||
|  | 	u8  vid; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_voltage { | ||||||
|  | 	bool supported; | ||||||
|  | 	u8 version; | ||||||
|  | 	u8 vid_mask; | ||||||
|  | 
 | ||||||
|  | 	struct nouveau_pm_voltage_level *level; | ||||||
|  | 	int nr_level; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* Exclusive upper limits */ | ||||||
|  | #define NV_MEM_CL_DDR2_MAX 8 | ||||||
|  | #define NV_MEM_WR_DDR2_MAX 9 | ||||||
|  | #define NV_MEM_CL_DDR3_MAX 17 | ||||||
|  | #define NV_MEM_WR_DDR3_MAX 17 | ||||||
|  | #define NV_MEM_CL_GDDR3_MAX 16 | ||||||
|  | #define NV_MEM_WR_GDDR3_MAX 18 | ||||||
|  | #define NV_MEM_CL_GDDR5_MAX 21 | ||||||
|  | #define NV_MEM_WR_GDDR5_MAX 20 | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_memtiming { | ||||||
|  | 	int id; | ||||||
|  | 
 | ||||||
|  | 	u32 reg[9]; | ||||||
|  | 	u32 mr[4]; | ||||||
|  | 
 | ||||||
|  | 	u8 tCWL; | ||||||
|  | 
 | ||||||
|  | 	u8 odt; | ||||||
|  | 	u8 drive_strength; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_tbl_header { | ||||||
|  | 	u8 version; | ||||||
|  | 	u8 header_len; | ||||||
|  | 	u8 entry_cnt; | ||||||
|  | 	u8 entry_len; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_tbl_entry { | ||||||
|  | 	u8 tWR; | ||||||
|  | 	u8 tWTR; | ||||||
|  | 	u8 tCL; | ||||||
|  | 	u8 tRC; | ||||||
|  | 	u8 empty_4; | ||||||
|  | 	u8 tRFC;	/* Byte 5 */ | ||||||
|  | 	u8 empty_6; | ||||||
|  | 	u8 tRAS;	/* Byte 7 */ | ||||||
|  | 	u8 empty_8; | ||||||
|  | 	u8 tRP;		/* Byte 9 */ | ||||||
|  | 	u8 tRCDRD; | ||||||
|  | 	u8 tRCDWR; | ||||||
|  | 	u8 tRRD; | ||||||
|  | 	u8 tUNK_13; | ||||||
|  | 	u8 RAM_FT1;		/* 14, a bitmask of random RAM features */ | ||||||
|  | 	u8 empty_15; | ||||||
|  | 	u8 tUNK_16; | ||||||
|  | 	u8 empty_17; | ||||||
|  | 	u8 tUNK_18; | ||||||
|  | 	u8 tCWL; | ||||||
|  | 	u8 tUNK_20, tUNK_21; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_profile; | ||||||
|  | struct nouveau_pm_profile_func { | ||||||
|  | 	void (*destroy)(struct nouveau_pm_profile *); | ||||||
|  | 	void (*init)(struct nouveau_pm_profile *); | ||||||
|  | 	void (*fini)(struct nouveau_pm_profile *); | ||||||
|  | 	struct nouveau_pm_level *(*select)(struct nouveau_pm_profile *); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_profile { | ||||||
|  | 	const struct nouveau_pm_profile_func *func; | ||||||
|  | 	struct list_head head; | ||||||
|  | 	char name[8]; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define NOUVEAU_PM_MAX_LEVEL 8 | ||||||
|  | struct nouveau_pm_level { | ||||||
|  | 	struct nouveau_pm_profile profile; | ||||||
|  | 	struct device_attribute dev_attr; | ||||||
|  | 	char name[32]; | ||||||
|  | 	int id; | ||||||
|  | 
 | ||||||
|  | 	struct nouveau_pm_memtiming timing; | ||||||
|  | 	u32 memory; | ||||||
|  | 	u16 memscript; | ||||||
|  | 
 | ||||||
|  | 	u32 core; | ||||||
|  | 	u32 shader; | ||||||
|  | 	u32 rop; | ||||||
|  | 	u32 copy; | ||||||
|  | 	u32 daemon; | ||||||
|  | 	u32 vdec; | ||||||
|  | 	u32 dom6; | ||||||
|  | 	u32 unka0;	/* nva3:nvc0 */ | ||||||
|  | 	u32 hub01;	/* nvc0- */ | ||||||
|  | 	u32 hub06;	/* nvc0- */ | ||||||
|  | 	u32 hub07;	/* nvc0- */ | ||||||
|  | 
 | ||||||
|  | 	u32 volt_min; /* microvolts */ | ||||||
|  | 	u32 volt_max; | ||||||
|  | 	u8  fanspeed; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_temp_sensor_constants { | ||||||
|  | 	u16 offset_constant; | ||||||
|  | 	s16 offset_mult; | ||||||
|  | 	s16 offset_div; | ||||||
|  | 	s16 slope_mult; | ||||||
|  | 	s16 slope_div; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_threshold_temp { | ||||||
|  | 	s16 critical; | ||||||
|  | 	s16 down_clock; | ||||||
|  | 	s16 fan_boost; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm_fan { | ||||||
|  | 	u32 percent; | ||||||
|  | 	u32 min_duty; | ||||||
|  | 	u32 max_duty; | ||||||
|  | 	u32 pwm_freq; | ||||||
|  | 	u32 pwm_divisor; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct nouveau_pm { | ||||||
|  | 	struct drm_device *dev; | ||||||
|  | 
 | ||||||
|  | 	struct nouveau_pm_voltage voltage; | ||||||
|  | 	struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; | ||||||
|  | 	int nr_perflvl; | ||||||
|  | 	struct nouveau_pm_temp_sensor_constants sensor_constants; | ||||||
|  | 	struct nouveau_pm_threshold_temp threshold_temp; | ||||||
|  | 	struct nouveau_pm_fan fan; | ||||||
|  | 
 | ||||||
|  | 	struct nouveau_pm_profile *profile_ac; | ||||||
|  | 	struct nouveau_pm_profile *profile_dc; | ||||||
|  | 	struct nouveau_pm_profile *profile; | ||||||
|  | 	struct list_head profiles; | ||||||
|  | 
 | ||||||
|  | 	struct nouveau_pm_level boot; | ||||||
|  | 	struct nouveau_pm_level *cur; | ||||||
|  | 
 | ||||||
|  | 	struct device *hwmon; | ||||||
|  | 	struct notifier_block acpi_nb; | ||||||
|  | 
 | ||||||
|  | 	int  (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); | ||||||
|  | 	void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); | ||||||
|  | 	int (*clocks_set)(struct drm_device *, void *); | ||||||
|  | 
 | ||||||
|  | 	int (*voltage_get)(struct drm_device *); | ||||||
|  | 	int (*voltage_set)(struct drm_device *, int voltage); | ||||||
|  | 	int (*pwm_get)(struct drm_device *, int line, u32*, u32*); | ||||||
|  | 	int (*pwm_set)(struct drm_device *, int line, u32, u32); | ||||||
|  | 	int (*temp_get)(struct drm_device *); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static inline struct nouveau_pm * | ||||||
|  | nouveau_pm(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	return nouveau_drm(dev)->pm; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| struct nouveau_mem_exec_func { | struct nouveau_mem_exec_func { | ||||||
| 	struct drm_device *dev; | 	struct drm_device *dev; | ||||||
| 	void (*precharge)(struct nouveau_mem_exec_func *); | 	void (*precharge)(struct nouveau_mem_exec_func *); | ||||||
|  | @ -106,4 +278,26 @@ void nouveau_temp_safety_checks(struct drm_device *dev); | ||||||
| int nv40_temp_get(struct drm_device *dev); | int nv40_temp_get(struct drm_device *dev); | ||||||
| int nv84_temp_get(struct drm_device *dev); | int nv84_temp_get(struct drm_device *dev); | ||||||
| 
 | 
 | ||||||
|  | /* nouveau_mem.c */ | ||||||
|  | int  nouveau_mem_timing_calc(struct drm_device *, u32 freq, | ||||||
|  | 			     struct nouveau_pm_memtiming *); | ||||||
|  | void nouveau_mem_timing_read(struct drm_device *, | ||||||
|  | 			     struct nouveau_pm_memtiming *); | ||||||
|  | 
 | ||||||
|  | static inline int | ||||||
|  | nva3_calc_pll(struct drm_device *dev, struct nvbios_pll *pll, u32 freq, | ||||||
|  | 	      int *N, int *fN, int *M, int *P) | ||||||
|  | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_clock *clk = nouveau_clock(device); | ||||||
|  | 	struct nouveau_pll_vals pv; | ||||||
|  | 	int ret; | ||||||
|  | 
 | ||||||
|  | 	ret = clk->pll_calc(clk, pll, freq, &pv); | ||||||
|  | 	*N = pv.N1; | ||||||
|  | 	*M = pv.M1; | ||||||
|  | 	*P = pv.log2P; | ||||||
|  | 	return ret; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -22,13 +22,13 @@ | ||||||
|  * Authors: Dave Airlie |  * Authors: Dave Airlie | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <linux/dma-buf.h> | ||||||
|  | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm.h" | #include "drm.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include <nouveau_drm.h> | #include "nouveau_gem.h" | ||||||
| 
 |  | ||||||
| #include <linux/dma-buf.h> |  | ||||||
| 
 | 
 | ||||||
| static struct sg_table *nouveau_gem_map_dma_buf(struct dma_buf_attachment *attachment, | static struct sg_table *nouveau_gem_map_dma_buf(struct dma_buf_attachment *attachment, | ||||||
| 					  enum dma_data_direction dir) | 					  enum dma_data_direction dir) | ||||||
|  |  | ||||||
|  | @ -1,22 +0,0 @@ | ||||||
| #include "nouveau_revcompat.h" |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nv50_display.h" |  | ||||||
| 
 |  | ||||||
| struct nouveau_drm * |  | ||||||
| nouveau_newpriv(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	return dev_priv->newpriv; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_bo * |  | ||||||
| nv50sema(struct drm_device *dev, int crtc) |  | ||||||
| { |  | ||||||
| 	return nv50_display(dev)->crtc[crtc].sem.bo; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct nouveau_bo * |  | ||||||
| nvd0sema(struct drm_device *dev, int crtc) |  | ||||||
| { |  | ||||||
| 	return nvd0_display_crtc_sema(dev, crtc); |  | ||||||
| } |  | ||||||
|  | @ -1,12 +0,0 @@ | ||||||
| #ifndef __NOUVEAU_REVCOMPAT_H__ |  | ||||||
| #define __NOUVEAU_REVCOMPAT_H__ |  | ||||||
| 
 |  | ||||||
| #include "drmP.h" |  | ||||||
| 
 |  | ||||||
| struct nouveau_drm * |  | ||||||
| nouveau_newpriv(struct drm_device *); |  | ||||||
| 
 |  | ||||||
| struct nouveau_bo *nv50sema(struct drm_device *dev, int crtc); |  | ||||||
| struct nouveau_bo *nvd0sema(struct drm_device *dev, int crtc); |  | ||||||
| 
 |  | ||||||
| #endif |  | ||||||
|  | @ -1,508 +0,0 @@ | ||||||
| /*
 |  | ||||||
|  * Copyright 2005 Stephane Marchesin |  | ||||||
|  * Copyright 2008 Stuart Bennett |  | ||||||
|  * All Rights Reserved. |  | ||||||
|  * |  | ||||||
|  * Permission is hereby granted, free of charge, to any person obtaining a |  | ||||||
|  * copy of this software and associated documentation files (the "Software"), |  | ||||||
|  * to deal in the Software without restriction, including without limitation |  | ||||||
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense, |  | ||||||
|  * and/or sell copies of the Software, and to permit persons to whom the |  | ||||||
|  * Software is furnished to do so, subject to the following conditions: |  | ||||||
|  * |  | ||||||
|  * The above copyright notice and this permission notice (including the next |  | ||||||
|  * paragraph) shall be included in all copies or substantial portions of the |  | ||||||
|  * Software. |  | ||||||
|  * |  | ||||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |  | ||||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |  | ||||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL |  | ||||||
|  * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |  | ||||||
|  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |  | ||||||
|  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |  | ||||||
|  * DEALINGS IN THE SOFTWARE. |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #include <linux/swab.h> |  | ||||||
| #include <linux/slab.h> |  | ||||||
| #include "drmP.h" |  | ||||||
| #include "drm.h" |  | ||||||
| #include "drm_sarea.h" |  | ||||||
| #include "drm_crtc_helper.h" |  | ||||||
| #include <linux/vgaarb.h> |  | ||||||
| #include <linux/vga_switcheroo.h> |  | ||||||
| 
 |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include <nouveau_drm.h> |  | ||||||
| #include "nouveau_fbcon.h" |  | ||||||
| #include "nouveau_pm.h" |  | ||||||
| #include "nv04_display.h" |  | ||||||
| #include "nv50_display.h" |  | ||||||
| #include "nouveau_acpi.h" |  | ||||||
| 
 |  | ||||||
| static void nouveau_stub_takedown(struct drm_device *dev) {} |  | ||||||
| static int nouveau_stub_init(struct drm_device *dev) { return 0; } |  | ||||||
| 
 |  | ||||||
| static int nouveau_init_engine_ptrs(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	struct nouveau_engine *engine = &dev_priv->engine; |  | ||||||
| 
 |  | ||||||
| 	switch (dev_priv->chipset & 0xf0) { |  | ||||||
| 	case 0x00: |  | ||||||
| 		engine->display.early_init	= nv04_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv04_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv04_display_create; |  | ||||||
| 		engine->display.destroy		= nv04_display_destroy; |  | ||||||
| 		engine->display.init		= nv04_display_init; |  | ||||||
| 		engine->display.fini		= nv04_display_fini; |  | ||||||
| 		engine->pm.clocks_get		= nv04_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nv04_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nv04_pm_clocks_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0x10: |  | ||||||
| 		engine->display.early_init	= nv04_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv04_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv04_display_create; |  | ||||||
| 		engine->display.destroy		= nv04_display_destroy; |  | ||||||
| 		engine->display.init		= nv04_display_init; |  | ||||||
| 		engine->display.fini		= nv04_display_fini; |  | ||||||
| 		engine->pm.clocks_get		= nv04_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nv04_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nv04_pm_clocks_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0x20: |  | ||||||
| 		engine->display.early_init	= nv04_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv04_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv04_display_create; |  | ||||||
| 		engine->display.destroy		= nv04_display_destroy; |  | ||||||
| 		engine->display.init		= nv04_display_init; |  | ||||||
| 		engine->display.fini		= nv04_display_fini; |  | ||||||
| 		engine->pm.clocks_get		= nv04_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nv04_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nv04_pm_clocks_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0x30: |  | ||||||
| 		engine->display.early_init	= nv04_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv04_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv04_display_create; |  | ||||||
| 		engine->display.destroy		= nv04_display_destroy; |  | ||||||
| 		engine->display.init		= nv04_display_init; |  | ||||||
| 		engine->display.fini		= nv04_display_fini; |  | ||||||
| 		engine->pm.clocks_get		= nv04_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nv04_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nv04_pm_clocks_set; |  | ||||||
| 		engine->pm.voltage_get		= nouveau_voltage_gpio_get; |  | ||||||
| 		engine->pm.voltage_set		= nouveau_voltage_gpio_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0x40: |  | ||||||
| 	case 0x60: |  | ||||||
| 		engine->display.early_init	= nv04_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv04_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv04_display_create; |  | ||||||
| 		engine->display.destroy		= nv04_display_destroy; |  | ||||||
| 		engine->display.init		= nv04_display_init; |  | ||||||
| 		engine->display.fini		= nv04_display_fini; |  | ||||||
| 		engine->pm.clocks_get		= nv40_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nv40_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nv40_pm_clocks_set; |  | ||||||
| 		engine->pm.voltage_get		= nouveau_voltage_gpio_get; |  | ||||||
| 		engine->pm.voltage_set		= nouveau_voltage_gpio_set; |  | ||||||
| 		engine->pm.temp_get		= nv40_temp_get; |  | ||||||
| 		engine->pm.pwm_get		= nv40_pm_pwm_get; |  | ||||||
| 		engine->pm.pwm_set		= nv40_pm_pwm_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0x50: |  | ||||||
| 	case 0x80: /* gotta love NVIDIA's consistency.. */ |  | ||||||
| 	case 0x90: |  | ||||||
| 	case 0xa0: |  | ||||||
| 		engine->display.early_init	= nv50_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv50_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv50_display_create; |  | ||||||
| 		engine->display.destroy		= nv50_display_destroy; |  | ||||||
| 		engine->display.init		= nv50_display_init; |  | ||||||
| 		engine->display.fini		= nv50_display_fini; |  | ||||||
| 		switch (dev_priv->chipset) { |  | ||||||
| 		case 0x84: |  | ||||||
| 		case 0x86: |  | ||||||
| 		case 0x92: |  | ||||||
| 		case 0x94: |  | ||||||
| 		case 0x96: |  | ||||||
| 		case 0x98: |  | ||||||
| 		case 0xa0: |  | ||||||
| 		case 0xaa: |  | ||||||
| 		case 0xac: |  | ||||||
| 		case 0x50: |  | ||||||
| 			engine->pm.clocks_get	= nv50_pm_clocks_get; |  | ||||||
| 			engine->pm.clocks_pre	= nv50_pm_clocks_pre; |  | ||||||
| 			engine->pm.clocks_set	= nv50_pm_clocks_set; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			engine->pm.clocks_get	= nva3_pm_clocks_get; |  | ||||||
| 			engine->pm.clocks_pre	= nva3_pm_clocks_pre; |  | ||||||
| 			engine->pm.clocks_set	= nva3_pm_clocks_set; |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 		engine->pm.voltage_get		= nouveau_voltage_gpio_get; |  | ||||||
| 		engine->pm.voltage_set		= nouveau_voltage_gpio_set; |  | ||||||
| 		if (dev_priv->chipset >= 0x84) |  | ||||||
| 			engine->pm.temp_get	= nv84_temp_get; |  | ||||||
| 		else |  | ||||||
| 			engine->pm.temp_get	= nv40_temp_get; |  | ||||||
| 		engine->pm.pwm_get		= nv50_pm_pwm_get; |  | ||||||
| 		engine->pm.pwm_set		= nv50_pm_pwm_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0xc0: |  | ||||||
| 		engine->display.early_init	= nv50_display_early_init; |  | ||||||
| 		engine->display.late_takedown	= nv50_display_late_takedown; |  | ||||||
| 		engine->display.create		= nv50_display_create; |  | ||||||
| 		engine->display.destroy		= nv50_display_destroy; |  | ||||||
| 		engine->display.init		= nv50_display_init; |  | ||||||
| 		engine->display.fini		= nv50_display_fini; |  | ||||||
| 		engine->pm.temp_get		= nv84_temp_get; |  | ||||||
| 		engine->pm.clocks_get		= nvc0_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nvc0_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nvc0_pm_clocks_set; |  | ||||||
| 		engine->pm.voltage_get		= nouveau_voltage_gpio_get; |  | ||||||
| 		engine->pm.voltage_set		= nouveau_voltage_gpio_set; |  | ||||||
| 		engine->pm.pwm_get		= nv50_pm_pwm_get; |  | ||||||
| 		engine->pm.pwm_set		= nv50_pm_pwm_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0xd0: |  | ||||||
| 		engine->display.early_init	= nouveau_stub_init; |  | ||||||
| 		engine->display.late_takedown	= nouveau_stub_takedown; |  | ||||||
| 		engine->display.create		= nvd0_display_create; |  | ||||||
| 		engine->display.destroy		= nvd0_display_destroy; |  | ||||||
| 		engine->display.init		= nvd0_display_init; |  | ||||||
| 		engine->display.fini		= nvd0_display_fini; |  | ||||||
| 		engine->pm.temp_get		= nv84_temp_get; |  | ||||||
| 		engine->pm.clocks_get		= nvc0_pm_clocks_get; |  | ||||||
| 		engine->pm.clocks_pre		= nvc0_pm_clocks_pre; |  | ||||||
| 		engine->pm.clocks_set		= nvc0_pm_clocks_set; |  | ||||||
| 		engine->pm.voltage_get		= nouveau_voltage_gpio_get; |  | ||||||
| 		engine->pm.voltage_set		= nouveau_voltage_gpio_set; |  | ||||||
| 		break; |  | ||||||
| 	case 0xe0: |  | ||||||
| 		engine->display.early_init	= nouveau_stub_init; |  | ||||||
| 		engine->display.late_takedown	= nouveau_stub_takedown; |  | ||||||
| 		engine->display.create		= nvd0_display_create; |  | ||||||
| 		engine->display.destroy		= nvd0_display_destroy; |  | ||||||
| 		engine->display.init		= nvd0_display_init; |  | ||||||
| 		engine->display.fini		= nvd0_display_fini; |  | ||||||
| 		break; |  | ||||||
| 	default: |  | ||||||
| 		NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); |  | ||||||
| 		return 1; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/* headless mode */ |  | ||||||
| 	if (nouveau_modeset == 2) { |  | ||||||
| 		engine->display.early_init = nouveau_stub_init; |  | ||||||
| 		engine->display.late_takedown = nouveau_stub_takedown; |  | ||||||
| 		engine->display.create = nouveau_stub_init; |  | ||||||
| 		engine->display.init = nouveau_stub_init; |  | ||||||
| 		engine->display.destroy = nouveau_stub_takedown; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static unsigned int |  | ||||||
| nouveau_vga_set_decode(void *priv, bool state) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = priv; |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 
 |  | ||||||
| 	if (dev_priv->chipset >= 0x40) |  | ||||||
| 		nv_wr32(dev, 0x88054, state); |  | ||||||
| 	else |  | ||||||
| 		nv_wr32(dev, 0x1854, state); |  | ||||||
| 
 |  | ||||||
| 	if (state) |  | ||||||
| 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | |  | ||||||
| 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |  | ||||||
| 	else |  | ||||||
| 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void nouveau_switcheroo_set_state(struct pci_dev *pdev, |  | ||||||
| 					 enum vga_switcheroo_state state) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); |  | ||||||
| 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; |  | ||||||
| 	if (state == VGA_SWITCHEROO_ON) { |  | ||||||
| 		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); |  | ||||||
| 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; |  | ||||||
| 		nouveau_pci_resume(pdev); |  | ||||||
| 		drm_kms_helper_poll_enable(dev); |  | ||||||
| 		dev->switch_power_state = DRM_SWITCH_POWER_ON; |  | ||||||
| 	} else { |  | ||||||
| 		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); |  | ||||||
| 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; |  | ||||||
| 		drm_kms_helper_poll_disable(dev); |  | ||||||
| 		nouveau_switcheroo_optimus_dsm(); |  | ||||||
| 		nouveau_pci_suspend(pdev, pmm); |  | ||||||
| 		dev->switch_power_state = DRM_SWITCH_POWER_OFF; |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void nouveau_switcheroo_reprobe(struct pci_dev *pdev) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); |  | ||||||
| 	nouveau_fbcon_output_poll_changed(dev); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool nouveau_switcheroo_can_switch(struct pci_dev *pdev) |  | ||||||
| { |  | ||||||
| 	struct drm_device *dev = pci_get_drvdata(pdev); |  | ||||||
| 	bool can_switch; |  | ||||||
| 
 |  | ||||||
| 	spin_lock(&dev->count_lock); |  | ||||||
| 	can_switch = (dev->open_count == 0); |  | ||||||
| 	spin_unlock(&dev->count_lock); |  | ||||||
| 	return can_switch; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static const struct vga_switcheroo_client_ops nouveau_switcheroo_ops = { |  | ||||||
| 	.set_gpu_state = nouveau_switcheroo_set_state, |  | ||||||
| 	.reprobe = nouveau_switcheroo_reprobe, |  | ||||||
| 	.can_switch = nouveau_switcheroo_can_switch, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| int |  | ||||||
| nouveau_card_init(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	struct nouveau_engine *engine; |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); |  | ||||||
| 	vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops); |  | ||||||
| 
 |  | ||||||
| 	/* Initialise internal driver API hooks */ |  | ||||||
| 	ret = nouveau_init_engine_ptrs(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto out; |  | ||||||
| 	engine = &dev_priv->engine; |  | ||||||
| 	spin_lock_init(&dev_priv->context_switch_lock); |  | ||||||
| 
 |  | ||||||
| 	/* Make the CRTCs and I2C buses accessible */ |  | ||||||
| 	ret = engine->display.early_init(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto out; |  | ||||||
| 
 |  | ||||||
| 	/* Parse BIOS tables / Run init tables if card not POSTed */ |  | ||||||
| 	ret = nouveau_bios_init(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto out_display_early; |  | ||||||
| 
 |  | ||||||
| 	/* workaround an odd issue on nvc1 by disabling the device's
 |  | ||||||
| 	 * nosnoop capability.  hopefully won't cause issues until a |  | ||||||
| 	 * better fix is found - assuming there is one... |  | ||||||
| 	 */ |  | ||||||
| 	if (dev_priv->chipset == 0xc1) { |  | ||||||
| 		nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	ret = nouveau_irq_init(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto out_bios; |  | ||||||
| 
 |  | ||||||
| 	ret = nouveau_display_create(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto out_irq; |  | ||||||
| 
 |  | ||||||
| 	nouveau_backlight_init(dev); |  | ||||||
| 	nouveau_pm_init(dev); |  | ||||||
| 
 |  | ||||||
| 	if (dev->mode_config.num_crtc) { |  | ||||||
| 		ret = nouveau_display_init(dev); |  | ||||||
| 		if (ret) |  | ||||||
| 			goto out_pm; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| 
 |  | ||||||
| out_pm: |  | ||||||
| 	nouveau_pm_fini(dev); |  | ||||||
| 	nouveau_backlight_exit(dev); |  | ||||||
| 	nouveau_display_destroy(dev); |  | ||||||
| out_irq: |  | ||||||
| 	nouveau_irq_fini(dev); |  | ||||||
| out_bios: |  | ||||||
| 	nouveau_bios_takedown(dev); |  | ||||||
| out_display_early: |  | ||||||
| 	engine->display.late_takedown(dev); |  | ||||||
| out: |  | ||||||
| 	vga_switcheroo_unregister_client(dev->pdev); |  | ||||||
| 	vga_client_register(dev->pdev, NULL, NULL, NULL); |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void nouveau_card_takedown(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	struct nouveau_engine *engine = &dev_priv->engine; |  | ||||||
| 
 |  | ||||||
| 	if (dev->mode_config.num_crtc) |  | ||||||
| 		nouveau_display_fini(dev); |  | ||||||
| 
 |  | ||||||
| 	nouveau_pm_fini(dev); |  | ||||||
| 	nouveau_backlight_exit(dev); |  | ||||||
| 	nouveau_display_destroy(dev); |  | ||||||
| 
 |  | ||||||
| 	nouveau_bios_takedown(dev); |  | ||||||
| 	engine->display.late_takedown(dev); |  | ||||||
| 
 |  | ||||||
| 	nouveau_irq_fini(dev); |  | ||||||
| 
 |  | ||||||
| 	vga_switcheroo_unregister_client(dev->pdev); |  | ||||||
| 	vga_client_register(dev->pdev, NULL, NULL, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* 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) |  | ||||||
| { |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* if we have an OF card, copy vbios to RAMIN */ |  | ||||||
| static void nouveau_OF_copy_vbios_to_ramin(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| #if defined(__powerpc__) |  | ||||||
| 	int size, i; |  | ||||||
| 	const uint32_t *bios; |  | ||||||
| 	struct device_node *dn = pci_device_to_OF_node(dev->pdev); |  | ||||||
| 	if (!dn) { |  | ||||||
| 		NV_INFO(dev, "Unable to get the OF node\n"); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	bios = of_get_property(dn, "NVDA,BMP", &size); |  | ||||||
| 	if (bios) { |  | ||||||
| 		for (i = 0; i < size; i += 4) |  | ||||||
| 			nv_wi32(dev, i, bios[i/4]); |  | ||||||
| 		NV_INFO(dev, "OF bios successfully copied (%d bytes)\n", size); |  | ||||||
| 	} else { |  | ||||||
| 		NV_INFO(dev, "Unable to get the OF bios\n"); |  | ||||||
| 	} |  | ||||||
| #endif |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int nouveau_load(struct drm_device *dev, unsigned long flags) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv; |  | ||||||
| 	uint32_t reg0 = ~0, strap; |  | ||||||
| 	int ret; |  | ||||||
| 
 |  | ||||||
| 	dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |  | ||||||
| 	if (!dev_priv) { |  | ||||||
| 		ret = -ENOMEM; |  | ||||||
| 		goto err_out; |  | ||||||
| 	} |  | ||||||
| 	dev_priv->newpriv = dev->dev_private; |  | ||||||
| 	dev->dev_private = dev_priv; |  | ||||||
| 	dev_priv->dev = dev; |  | ||||||
| 
 |  | ||||||
| 	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", |  | ||||||
| 		 dev->pci_vendor, dev->pci_device, dev->pdev->class); |  | ||||||
| 
 |  | ||||||
| 	/* determine chipset and derive architecture from it */ |  | ||||||
| 	reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); |  | ||||||
| 	if ((reg0 & 0x0f000000) > 0) { |  | ||||||
| 		dev_priv->chipset = (reg0 & 0xff00000) >> 20; |  | ||||||
| 		switch (dev_priv->chipset & 0xf0) { |  | ||||||
| 		case 0x10: |  | ||||||
| 		case 0x20: |  | ||||||
| 		case 0x30: |  | ||||||
| 			dev_priv->card_type = dev_priv->chipset & 0xf0; |  | ||||||
| 			break; |  | ||||||
| 		case 0x40: |  | ||||||
| 		case 0x60: |  | ||||||
| 			dev_priv->card_type = NV_40; |  | ||||||
| 			break; |  | ||||||
| 		case 0x50: |  | ||||||
| 		case 0x80: |  | ||||||
| 		case 0x90: |  | ||||||
| 		case 0xa0: |  | ||||||
| 			dev_priv->card_type = NV_50; |  | ||||||
| 			break; |  | ||||||
| 		case 0xc0: |  | ||||||
| 			dev_priv->card_type = NV_C0; |  | ||||||
| 			break; |  | ||||||
| 		case 0xd0: |  | ||||||
| 			dev_priv->card_type = NV_D0; |  | ||||||
| 			break; |  | ||||||
| 		case 0xe0: |  | ||||||
| 			dev_priv->card_type = NV_E0; |  | ||||||
| 			break; |  | ||||||
| 		default: |  | ||||||
| 			break; |  | ||||||
| 		} |  | ||||||
| 	} else |  | ||||||
| 	if ((reg0 & 0xff00fff0) == 0x20004000) { |  | ||||||
| 		if (reg0 & 0x00f00000) |  | ||||||
| 			dev_priv->chipset = 0x05; |  | ||||||
| 		else |  | ||||||
| 			dev_priv->chipset = 0x04; |  | ||||||
| 		dev_priv->card_type = NV_04; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (!dev_priv->card_type) { |  | ||||||
| 		NV_ERROR(dev, "unsupported chipset 0x%08x\n", reg0); |  | ||||||
| 		ret = -EINVAL; |  | ||||||
| 		goto err_priv; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	NV_INFO(dev, "Detected an NV%02x generation card (0x%08x)\n", |  | ||||||
| 		     dev_priv->card_type, reg0); |  | ||||||
| 
 |  | ||||||
| 	/* determine frequency of timing crystal */ |  | ||||||
| 	strap = nv_rd32(dev, 0x101000); |  | ||||||
| 	if ( dev_priv->chipset < 0x17 || |  | ||||||
| 	    (dev_priv->chipset >= 0x20 && dev_priv->chipset <= 0x25)) |  | ||||||
| 		strap &= 0x00000040; |  | ||||||
| 	else |  | ||||||
| 		strap &= 0x00400040; |  | ||||||
| 
 |  | ||||||
| 	switch (strap) { |  | ||||||
| 	case 0x00000000: dev_priv->crystal = 13500; break; |  | ||||||
| 	case 0x00000040: dev_priv->crystal = 14318; break; |  | ||||||
| 	case 0x00400000: dev_priv->crystal = 27000; break; |  | ||||||
| 	case 0x00400040: dev_priv->crystal = 25000; break; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	NV_DEBUG(dev, "crystal freq: %dKHz\n", dev_priv->crystal); |  | ||||||
| 
 |  | ||||||
| 	nouveau_OF_copy_vbios_to_ramin(dev); |  | ||||||
| 
 |  | ||||||
| 	/* For kernel modesetting, init card now and bring up fbcon */ |  | ||||||
| 	ret = nouveau_card_init(dev); |  | ||||||
| 	if (ret) |  | ||||||
| 		goto err_priv; |  | ||||||
| 
 |  | ||||||
| 	return 0; |  | ||||||
| 
 |  | ||||||
| err_priv: |  | ||||||
| 	dev->dev_private = dev_priv->newpriv; |  | ||||||
| 	kfree(dev_priv); |  | ||||||
| err_out: |  | ||||||
| 	return ret; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void nouveau_lastclose(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	vga_switcheroo_process_delayed_switch(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| int nouveau_unload(struct drm_device *dev) |  | ||||||
| { |  | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 
 |  | ||||||
| 	nouveau_card_takedown(dev); |  | ||||||
| 
 |  | ||||||
| 	dev->dev_private = dev_priv->newpriv; |  | ||||||
| 	kfree(dev_priv); |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
|  | @ -26,20 +26,22 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/i2c.h> | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) | nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||||||
| 	struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | 	struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | ||||||
| 	int i, headerlen, recordlen, entries; | 	int i, headerlen, recordlen, entries; | ||||||
| 
 | 
 | ||||||
| 	if (!temp) { | 	if (!temp) { | ||||||
| 		NV_DEBUG(dev, "temperature table pointer invalid\n"); | 		NV_DEBUG(drm, "temperature table pointer invalid\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -60,8 +62,8 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) | ||||||
| 	pm->fan.max_duty = 100; | 	pm->fan.max_duty = 100; | ||||||
| 
 | 
 | ||||||
| 	/* Set the known default values to setup the temperature sensor */ | 	/* Set the known default values to setup the temperature sensor */ | ||||||
| 	if (dev_priv->card_type >= NV_40) { | 	if (nv_device(drm->device)->card_type >= NV_40) { | ||||||
| 		switch (dev_priv->chipset) { | 		switch (nv_device(drm->device)->chipset) { | ||||||
| 		case 0x43: | 		case 0x43: | ||||||
| 			sensor->offset_mult = 32060; | 			sensor->offset_mult = 32060; | ||||||
| 			sensor->offset_div = 1000; | 			sensor->offset_div = 1000; | ||||||
|  | @ -185,8 +187,9 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) | ||||||
| static int | static int | ||||||
| nv40_sensor_setup(struct drm_device *dev) | nv40_sensor_setup(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||||||
| 	s32 offset = sensor->offset_mult / sensor->offset_div; | 	s32 offset = sensor->offset_mult / sensor->offset_div; | ||||||
| 	s32 sensor_calibration; | 	s32 sensor_calibration; | ||||||
|  | @ -196,33 +199,34 @@ nv40_sensor_setup(struct drm_device *dev) | ||||||
| 	sensor_calibration = sensor_calibration * sensor->slope_div / | 	sensor_calibration = sensor_calibration * sensor->slope_div / | ||||||
| 				sensor->slope_mult; | 				sensor->slope_mult; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset >= 0x46) | 	if (nv_device(drm->device)->chipset >= 0x46) | ||||||
| 		sensor_calibration |= 0x80000000; | 		sensor_calibration |= 0x80000000; | ||||||
| 	else | 	else | ||||||
| 		sensor_calibration |= 0x10000000; | 		sensor_calibration |= 0x10000000; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x0015b0, sensor_calibration); | 	nv_wr32(device, 0x0015b0, sensor_calibration); | ||||||
| 
 | 
 | ||||||
| 	/* Wait for the sensor to update */ | 	/* Wait for the sensor to update */ | ||||||
| 	msleep(5); | 	msleep(5); | ||||||
| 
 | 
 | ||||||
| 	/* read */ | 	/* read */ | ||||||
| 	return nv_rd32(dev, 0x0015b4) & 0x1fff; | 	return nv_rd32(device, 0x0015b4) & 0x1fff; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nv40_temp_get(struct drm_device *dev) | nv40_temp_get(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | 	struct nouveau_pm_temp_sensor_constants *sensor = &pm->sensor_constants; | ||||||
| 	int offset = sensor->offset_mult / sensor->offset_div; | 	int offset = sensor->offset_mult / sensor->offset_div; | ||||||
| 	int core_temp; | 	int core_temp; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_50) { | 	if (nv_device(drm->device)->card_type >= NV_50) { | ||||||
| 		core_temp = nv_rd32(dev, 0x20008); | 		core_temp = nv_rd32(device, 0x20008); | ||||||
| 	} else { | 	} else { | ||||||
| 		core_temp = nv_rd32(dev, 0x0015b4) & 0x1fff; | 		core_temp = nv_rd32(device, 0x0015b4) & 0x1fff; | ||||||
| 		/* Setup the sensor if the temperature is 0 */ | 		/* Setup the sensor if the temperature is 0 */ | ||||||
| 		if (core_temp == 0) | 		if (core_temp == 0) | ||||||
| 			core_temp = nv40_sensor_setup(dev); | 			core_temp = nv40_sensor_setup(dev); | ||||||
|  | @ -237,14 +241,14 @@ nv40_temp_get(struct drm_device *dev) | ||||||
| int | int | ||||||
| nv84_temp_get(struct drm_device *dev) | nv84_temp_get(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	return nv_rd32(dev, 0x20400); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	return nv_rd32(device, 0x20400); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| nouveau_temp_safety_checks(struct drm_device *dev) | nouveau_temp_safety_checks(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; |  | ||||||
| 	struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | 	struct nouveau_pm_threshold_temp *temps = &pm->threshold_temp; | ||||||
| 
 | 
 | ||||||
| 	if (temps->critical > 120) | 	if (temps->critical > 120) | ||||||
|  | @ -271,7 +275,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, | ||||||
| 
 | 
 | ||||||
| 	request_module("%s%s", I2C_MODULE_PREFIX, info->type); | 	request_module("%s%s", I2C_MODULE_PREFIX, info->type); | ||||||
| 
 | 
 | ||||||
| 	client = i2c_new_device(nouveau_i2c_adapter(i2c), info); | 	client = i2c_new_device(&i2c->adapter, info); | ||||||
| 	if (!client) | 	if (!client) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
|  | @ -286,6 +290,8 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, | ||||||
| static void | static void | ||||||
| nouveau_temp_probe_i2c(struct drm_device *dev) | nouveau_temp_probe_i2c(struct drm_device *dev) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_i2c *i2c = nouveau_i2c(device); | ||||||
| 	struct i2c_board_info info[] = { | 	struct i2c_board_info info[] = { | ||||||
| 		{ I2C_BOARD_INFO("w83l785ts", 0x2d) }, | 		{ I2C_BOARD_INFO("w83l785ts", 0x2d) }, | ||||||
| 		{ I2C_BOARD_INFO("w83781d", 0x2d) }, | 		{ I2C_BOARD_INFO("w83781d", 0x2d) }, | ||||||
|  | @ -295,15 +301,15 @@ nouveau_temp_probe_i2c(struct drm_device *dev) | ||||||
| 		{ } | 		{ } | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	nouveau_i2c_identify(dev, "monitoring device", info, | 	i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, | ||||||
| 			     probe_monitoring_device, 0x80); //NV_I2C_DEFAULT(0));
 | 		      probe_monitoring_device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
| nouveau_temp_init(struct drm_device *dev) | nouveau_temp_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 	u8 *temp = NULL; | 	u8 *temp = NULL; | ||||||
| 
 | 
 | ||||||
|  | @ -316,7 +322,7 @@ nouveau_temp_init(struct drm_device *dev) | ||||||
| 		else if (P.version == 2) | 		else if (P.version == 2) | ||||||
| 			temp = ROMPTR(dev, P.data[16]); | 			temp = ROMPTR(dev, P.data[16]); | ||||||
| 		else | 		else | ||||||
| 			NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); | 			NV_WARN(drm, "unknown temp for BIT P %d\n", P.version); | ||||||
| 
 | 
 | ||||||
| 		nouveau_temp_vbios_parse(dev, temp); | 		nouveau_temp_vbios_parse(dev, temp); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -265,7 +265,7 @@ int | ||||||
| nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) | nouveau_ttm_mmap(struct file *filp, struct vm_area_struct *vma) | ||||||
| { | { | ||||||
| 	struct drm_file *file_priv = filp->private_data; | 	struct drm_file *file_priv = filp->private_data; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(file_priv->minor->dev); | 	struct nouveau_drm *drm = nouveau_drm(file_priv->minor->dev); | ||||||
| 
 | 
 | ||||||
| 	if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) | 	if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET)) | ||||||
| 		return drm_mmap(filp, vma); | 		return drm_mmap(filp, vma); | ||||||
|  |  | ||||||
|  | @ -17,5 +17,9 @@ struct ttm_tt *nouveau_sgdma_create_ttm(struct ttm_bo_device *, | ||||||
| 
 | 
 | ||||||
| int  nouveau_ttm_init(struct nouveau_drm *drm); | int  nouveau_ttm_init(struct nouveau_drm *drm); | ||||||
| void nouveau_ttm_fini(struct nouveau_drm *drm); | void nouveau_ttm_fini(struct nouveau_drm *drm); | ||||||
|  | int  nouveau_ttm_mmap(struct file *, struct vm_area_struct *); | ||||||
|  | 
 | ||||||
|  | int  nouveau_ttm_global_init(struct nouveau_drm *); | ||||||
|  | void nouveau_ttm_global_release(struct nouveau_drm *); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
							
								
								
									
										98
									
								
								drivers/gpu/drm/nouveau/nouveau_vga.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								drivers/gpu/drm/nouveau/nouveau_vga.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,98 @@ | ||||||
|  | #include <linux/vgaarb.h> | ||||||
|  | #include <linux/vga_switcheroo.h> | ||||||
|  | 
 | ||||||
|  | #include "drmP.h" | ||||||
|  | #include "drm_crtc_helper.h" | ||||||
|  | 
 | ||||||
|  | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_acpi.h" | ||||||
|  | #include "nouveau_fbcon.h" | ||||||
|  | 
 | ||||||
|  | static unsigned int | ||||||
|  | nouveau_vga_set_decode(void *priv, bool state) | ||||||
|  | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(priv); | ||||||
|  | 
 | ||||||
|  | 	if (device->chipset >= 0x40) | ||||||
|  | 		nv_wr32(device, 0x088054, state); | ||||||
|  | 	else | ||||||
|  | 		nv_wr32(device, 0x001854, state); | ||||||
|  | 
 | ||||||
|  | 	if (state) | ||||||
|  | 		return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | | ||||||
|  | 		       VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | ||||||
|  | 	else | ||||||
|  | 		return VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | nouveau_switcheroo_set_state(struct pci_dev *pdev, | ||||||
|  | 			     enum vga_switcheroo_state state) | ||||||
|  | { | ||||||
|  | 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||||
|  | 	pm_message_t pmm = { .event = PM_EVENT_SUSPEND }; | ||||||
|  | 
 | ||||||
|  | 	if (state == VGA_SWITCHEROO_ON) { | ||||||
|  | 		printk(KERN_ERR "VGA switcheroo: switched nouveau on\n"); | ||||||
|  | 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | ||||||
|  | 		nouveau_drm_resume(pdev); | ||||||
|  | 		drm_kms_helper_poll_enable(dev); | ||||||
|  | 		dev->switch_power_state = DRM_SWITCH_POWER_ON; | ||||||
|  | 	} else { | ||||||
|  | 		printk(KERN_ERR "VGA switcheroo: switched nouveau off\n"); | ||||||
|  | 		dev->switch_power_state = DRM_SWITCH_POWER_CHANGING; | ||||||
|  | 		drm_kms_helper_poll_disable(dev); | ||||||
|  | 		nouveau_switcheroo_optimus_dsm(); | ||||||
|  | 		nouveau_drm_suspend(pdev, pmm); | ||||||
|  | 		dev->switch_power_state = DRM_SWITCH_POWER_OFF; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | nouveau_switcheroo_reprobe(struct pci_dev *pdev) | ||||||
|  | { | ||||||
|  | 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||||
|  | 	nouveau_fbcon_output_poll_changed(dev); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool | ||||||
|  | nouveau_switcheroo_can_switch(struct pci_dev *pdev) | ||||||
|  | { | ||||||
|  | 	struct drm_device *dev = pci_get_drvdata(pdev); | ||||||
|  | 	bool can_switch; | ||||||
|  | 
 | ||||||
|  | 	spin_lock(&dev->count_lock); | ||||||
|  | 	can_switch = (dev->open_count == 0); | ||||||
|  | 	spin_unlock(&dev->count_lock); | ||||||
|  | 	return can_switch; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct vga_switcheroo_client_ops | ||||||
|  | nouveau_switcheroo_ops = { | ||||||
|  | 	.set_gpu_state = nouveau_switcheroo_set_state, | ||||||
|  | 	.reprobe = nouveau_switcheroo_reprobe, | ||||||
|  | 	.can_switch = nouveau_switcheroo_can_switch, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | nouveau_vga_init(struct nouveau_drm *drm) | ||||||
|  | { | ||||||
|  | 	struct drm_device *dev = drm->dev; | ||||||
|  | 	vga_client_register(dev->pdev, dev, NULL, nouveau_vga_set_decode); | ||||||
|  | 	vga_switcheroo_register_client(dev->pdev, &nouveau_switcheroo_ops); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | nouveau_vga_fini(struct nouveau_drm *drm) | ||||||
|  | { | ||||||
|  | 	struct drm_device *dev = drm->dev; | ||||||
|  | 	vga_switcheroo_unregister_client(dev->pdev); | ||||||
|  | 	vga_client_register(dev->pdev, NULL, NULL, NULL); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | void | ||||||
|  | nouveau_vga_lastclose(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	vga_switcheroo_process_delayed_switch(); | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								drivers/gpu/drm/nouveau/nouveau_vga.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								drivers/gpu/drm/nouveau/nouveau_vga.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | #ifndef __NOUVEAU_VGA_H__ | ||||||
|  | #define __NOUVEAU_VGA_H__ | ||||||
|  | 
 | ||||||
|  | void nouveau_vga_init(struct nouveau_drm *); | ||||||
|  | void nouveau_vga_fini(struct nouveau_drm *); | ||||||
|  | void nouveau_vga_lastclose(struct drm_device *dev); | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -24,10 +24,11 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/gpio.h> | #include <subdev/bios/gpio.h> | ||||||
|  | #include <subdev/gpio.h> | ||||||
| 
 | 
 | ||||||
| static const enum dcb_gpio_func_name vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; | static const enum dcb_gpio_func_name vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; | ||||||
| static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); | static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); | ||||||
|  | @ -35,8 +36,9 @@ static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); | ||||||
| int | int | ||||||
| nouveau_voltage_gpio_get(struct drm_device *dev) | nouveau_voltage_gpio_get(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; | ||||||
| 	struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(device); | ||||||
| 	u8 vid = 0; | 	u8 vid = 0; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
|  | @ -44,7 +46,7 @@ nouveau_voltage_gpio_get(struct drm_device *dev) | ||||||
| 		if (!(volt->vid_mask & (1 << i))) | 		if (!(volt->vid_mask & (1 << i))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		vid |= nouveau_gpio_func_get(dev, vidtag[i]) << i; | 		vid |= gpio->get(gpio, 0, vidtag[i], 0xff) << i; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nouveau_volt_lvl_lookup(dev, vid); | 	return nouveau_volt_lvl_lookup(dev, vid); | ||||||
|  | @ -53,8 +55,9 @@ nouveau_voltage_gpio_get(struct drm_device *dev) | ||||||
| int | int | ||||||
| nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) | nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; | 	struct nouveau_gpio *gpio = nouveau_gpio(device); | ||||||
|  | 	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; | ||||||
| 	int vid, i; | 	int vid, i; | ||||||
| 
 | 
 | ||||||
| 	vid = nouveau_volt_vid_lookup(dev, voltage); | 	vid = nouveau_volt_vid_lookup(dev, voltage); | ||||||
|  | @ -65,7 +68,7 @@ nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) | ||||||
| 		if (!(volt->vid_mask & (1 << i))) | 		if (!(volt->vid_mask & (1 << i))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		nouveau_gpio_func_set(dev, vidtag[i], !!(vid & (1 << i))); | 		gpio->set(gpio, 0, vidtag[i], 0xff, !!(vid & (1 << i))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -74,8 +77,7 @@ nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) | ||||||
| int | int | ||||||
| nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) | nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; | ||||||
| 	struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; |  | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < volt->nr_level; i++) { | 	for (i = 0; i < volt->nr_level; i++) { | ||||||
|  | @ -89,8 +91,7 @@ nouveau_volt_vid_lookup(struct drm_device *dev, int voltage) | ||||||
| int | int | ||||||
| nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) | nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; | ||||||
| 	struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; |  | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < volt->nr_level; i++) { | 	for (i = 0; i < volt->nr_level; i++) { | ||||||
|  | @ -104,10 +105,12 @@ nouveau_volt_lvl_lookup(struct drm_device *dev, int vid) | ||||||
| void | void | ||||||
| nouveau_volt_init(struct drm_device *dev) | nouveau_volt_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_pm_engine *pm = &dev_priv->engine.pm; | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
|  | 	struct nouveau_pm *pm = nouveau_pm(dev); | ||||||
| 	struct nouveau_pm_voltage *voltage = &pm->voltage; | 	struct nouveau_pm_voltage *voltage = &pm->voltage; | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
|  | 	struct dcb_gpio_func func; | ||||||
| 	struct bit_entry P; | 	struct bit_entry P; | ||||||
| 	u8 *volt = NULL, *entry; | 	u8 *volt = NULL, *entry; | ||||||
| 	int i, headerlen, recordlen, entries, vidmask, vidshift; | 	int i, headerlen, recordlen, entries, vidmask, vidshift; | ||||||
|  | @ -122,11 +125,11 @@ nouveau_volt_init(struct drm_device *dev) | ||||||
| 		if (P.version == 2) | 		if (P.version == 2) | ||||||
| 			volt = ROMPTR(dev, P.data[12]); | 			volt = ROMPTR(dev, P.data[12]); | ||||||
| 		else { | 		else { | ||||||
| 			NV_WARN(dev, "unknown volt for BIT P %d\n", P.version); | 			NV_WARN(drm, "unknown volt for BIT P %d\n", P.version); | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		if (bios->data[bios->offset + 6] < 0x27) { | 		if (bios->data[bios->offset + 6] < 0x27) { | ||||||
| 			NV_DEBUG(dev, "BMP version too old for voltage\n"); | 			NV_DEBUG(drm, "BMP version too old for voltage\n"); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -134,7 +137,7 @@ nouveau_volt_init(struct drm_device *dev) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!volt) { | 	if (!volt) { | ||||||
| 		NV_DEBUG(dev, "voltage table pointer invalid\n"); | 		NV_DEBUG(drm, "voltage table pointer invalid\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -178,7 +181,7 @@ nouveau_volt_init(struct drm_device *dev) | ||||||
| 		vidshift  = 0; | 		vidshift  = 0; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_WARN(dev, "voltage table 0x%02x unknown\n", volt[0]); | 		NV_WARN(drm, "voltage table 0x%02x unknown\n", volt[0]); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -190,12 +193,12 @@ nouveau_volt_init(struct drm_device *dev) | ||||||
| 	i = 0; | 	i = 0; | ||||||
| 	while (vidmask) { | 	while (vidmask) { | ||||||
| 		if (i > nr_vidtag) { | 		if (i > nr_vidtag) { | ||||||
| 			NV_DEBUG(dev, "vid bit %d unknown\n", i); | 			NV_DEBUG(drm, "vid bit %d unknown\n", i); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!nouveau_gpio_func_valid(dev, vidtag[i])) { | 		if (gpio && gpio->find(gpio, 0, vidtag[i], 0xff, &func)) { | ||||||
| 			NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); | 			NV_DEBUG(drm, "vid bit %d has no gpio tag\n", i); | ||||||
| 			return; | 			return; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -241,8 +244,7 @@ nouveau_volt_init(struct drm_device *dev) | ||||||
| void | void | ||||||
| nouveau_volt_fini(struct drm_device *dev) | nouveau_volt_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_pm_voltage *volt = &nouveau_pm(dev)->voltage; | ||||||
| 	struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; |  | ||||||
| 
 | 
 | ||||||
| 	kfree(volt->level); | 	kfree(volt->level); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -26,14 +26,20 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
|  | #include "nouveau_bo.h" | ||||||
|  | #include "nouveau_gem.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nvreg.h" | #include "nvreg.h" | ||||||
| #include "nouveau_fbcon.h" | #include "nouveau_fbcon.h" | ||||||
|  | #include "nv04_display.h" | ||||||
|  | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | nv04_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | ||||||
|  | @ -103,14 +109,17 @@ static void nv_crtc_set_image_sharpening(struct drm_crtc *crtc, int level) | ||||||
| static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock) | static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mode * mode, int dot_clock) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(drm->device); | ||||||
|  | 	struct nouveau_clock *clk = nouveau_clock(drm->device); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; | 	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; | ||||||
| 	struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *regp = &state->crtc_reg[nv_crtc->index]; | ||||||
| 	struct nouveau_pll_vals *pv = ®p->pllvals; | 	struct nouveau_pll_vals *pv = ®p->pllvals; | ||||||
| 	struct nvbios_pll pll_lim; | 	struct nvbios_pll pll_lim; | ||||||
| 
 | 
 | ||||||
| 	if (get_pll_limits(dev, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, &pll_lim)) | 	if (nvbios_pll_parse(bios, nv_crtc->index ? PLL_VPLL1 : PLL_VPLL0, | ||||||
|  | 			    &pll_lim)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	/* NM2 == 0 is used to determine single stage mode on two stage plls */ | 	/* NM2 == 0 is used to determine single stage mode on two stage plls */ | ||||||
|  | @ -126,28 +135,29 @@ static void nv_crtc_calc_state_ext(struct drm_crtc *crtc, struct drm_display_mod | ||||||
| 	 * has yet been observed in allowing the use a single stage pll on all | 	 * has yet been observed in allowing the use a single stage pll on all | ||||||
| 	 * nv43 however.  the behaviour of single stage use is untested on nv40 | 	 * nv43 however.  the behaviour of single stage use is untested on nv40 | ||||||
| 	 */ | 	 */ | ||||||
| 	if (dev_priv->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2)) | 	if (nv_device(drm->device)->chipset > 0x40 && dot_clock <= (pll_lim.vco1.max_freq / 2)) | ||||||
| 		memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); | 		memset(&pll_lim.vco2, 0, sizeof(pll_lim.vco2)); | ||||||
| 
 | 
 | ||||||
| 	if (!nouveau_calc_pll_mnp(dev, &pll_lim, dot_clock, pv)) | 
 | ||||||
|  | 	if (!clk->pll_calc(clk, &pll_lim, dot_clock, pv)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK; | 	state->pllsel &= PLLSEL_VPLL1_MASK | PLLSEL_VPLL2_MASK | PLLSEL_TV_MASK; | ||||||
| 
 | 
 | ||||||
| 	/* The blob uses this always, so let's do the same */ | 	/* The blob uses this always, so let's do the same */ | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE; | 		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_USE_VPLL2_TRUE; | ||||||
| 	/* again nv40 and some nv43 act more like nv3x as described above */ | 	/* again nv40 and some nv43 act more like nv3x as described above */ | ||||||
| 	if (dev_priv->chipset < 0x41) | 	if (nv_device(drm->device)->chipset < 0x41) | ||||||
| 		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL | | 		state->pllsel |= NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_MPLL | | ||||||
| 				 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL; | 				 NV_PRAMDAC_PLL_COEFF_SELECT_SOURCE_PROG_NVPLL; | ||||||
| 	state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK; | 	state->pllsel |= nv_crtc->index ? PLLSEL_VPLL2_MASK : PLLSEL_VPLL1_MASK; | ||||||
| 
 | 
 | ||||||
| 	if (pv->NM2) | 	if (pv->NM2) | ||||||
| 		NV_DEBUG_KMS(dev, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", | 		NV_DEBUG(drm, "vpll: n1 %d n2 %d m1 %d m2 %d log2p %d\n", | ||||||
| 			 pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P); | 			 pv->N1, pv->N2, pv->M1, pv->M2, pv->log2P); | ||||||
| 	else | 	else | ||||||
| 		NV_DEBUG_KMS(dev, "vpll: n %d m %d log2p %d\n", | 		NV_DEBUG(drm, "vpll: n %d m %d log2p %d\n", | ||||||
| 			 pv->N1, pv->M1, pv->log2P); | 			 pv->N1, pv->M1, pv->log2P); | ||||||
| 
 | 
 | ||||||
| 	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); | 	nv_crtc->cursor.set_offset(nv_crtc, nv_crtc->cursor.offset); | ||||||
|  | @ -158,10 +168,11 @@ nv_crtc_dpms(struct drm_crtc *crtc, int mode) | ||||||
| { | { | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	unsigned char seq1 = 0, crtc17 = 0; | 	unsigned char seq1 = 0, crtc17 = 0; | ||||||
| 	unsigned char crtc1A; | 	unsigned char crtc1A; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode, | 	NV_DEBUG(drm, "Setting dpms mode %d on CRTC %d\n", mode, | ||||||
| 							nv_crtc->index); | 							nv_crtc->index); | ||||||
| 
 | 
 | ||||||
| 	if (nv_crtc->last_dpms == mode) /* Don't do unnecessary mode changes. */ | 	if (nv_crtc->last_dpms == mode) /* Don't do unnecessary mode changes. */ | ||||||
|  | @ -263,7 +274,7 @@ nv_crtc_mode_set_vga(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||||||
| 		horizEnd = horizTotal - 2; | 		horizEnd = horizTotal - 2; | ||||||
| 		horizBlankEnd = horizTotal + 4; | 		horizBlankEnd = horizTotal + 4; | ||||||
| #if 0 | #if 0 | ||||||
| 		if (dev->overlayAdaptor && dev_priv->card_type >= NV_10) | 		if (dev->overlayAdaptor && nv_device(drm->device)->card_type >= NV_10) | ||||||
| 			/* This reportedly works around some video overlay bandwidth problems */ | 			/* This reportedly works around some video overlay bandwidth problems */ | ||||||
| 			horizTotal += 2; | 			horizTotal += 2; | ||||||
| #endif | #endif | ||||||
|  | @ -451,7 +462,7 @@ static void | ||||||
| nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | ||||||
| 	struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index]; | ||||||
|  | @ -499,7 +510,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | ||||||
| 	regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 | | 	regp->cursor_cfg = NV_PCRTC_CURSOR_CONFIG_CUR_LINES_64 | | ||||||
| 			     NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 | | 			     NV_PCRTC_CURSOR_CONFIG_CUR_PIXELS_64 | | ||||||
| 			     NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM; | 			     NV_PCRTC_CURSOR_CONFIG_ADDRESS_SPACE_PNVM; | ||||||
| 	if (dev_priv->chipset >= 0x11) | 	if (nv_device(drm->device)->chipset >= 0x11) | ||||||
| 		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32; | 		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_CUR_BPP_32; | ||||||
| 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 	if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||||||
| 		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE; | 		regp->cursor_cfg |= NV_PCRTC_CURSOR_CONFIG_DOUBLE_SCAN_ENABLE; | ||||||
|  | @ -540,26 +551,26 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | ||||||
| 	 * 1 << 30 on 0x60.830), for no apparent reason */ | 	 * 1 << 30 on 0x60.830), for no apparent reason */ | ||||||
| 	regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; | 	regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_30) | 	if (nv_device(drm->device)->card_type >= NV_30) | ||||||
| 		regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1; | 		regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1; | ||||||
| 
 | 
 | ||||||
| 	regp->crtc_830 = mode->crtc_vdisplay - 3; | 	regp->crtc_830 = mode->crtc_vdisplay - 3; | ||||||
| 	regp->crtc_834 = mode->crtc_vdisplay - 1; | 	regp->crtc_834 = mode->crtc_vdisplay - 1; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		/* This is what the blob does */ | 		/* This is what the blob does */ | ||||||
| 		regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850); | 		regp->crtc_850 = NVReadCRTC(dev, 0, NV_PCRTC_850); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_30) | 	if (nv_device(drm->device)->card_type >= NV_30) | ||||||
| 		regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); | 		regp->gpio_ext = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_10) | 	if (nv_device(drm->device)->card_type >= NV_10) | ||||||
| 		regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC; | 		regp->crtc_cfg = NV10_PCRTC_CONFIG_START_ADDRESS_HSYNC; | ||||||
| 	else | 	else | ||||||
| 		regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC; | 		regp->crtc_cfg = NV04_PCRTC_CONFIG_START_ADDRESS_HSYNC; | ||||||
| 
 | 
 | ||||||
| 	/* Some misc regs */ | 	/* Some misc regs */ | ||||||
| 	if (dev_priv->card_type == NV_40) { | 	if (nv_device(drm->device)->card_type == NV_40) { | ||||||
| 		regp->CRTC[NV_CIO_CRE_85] = 0xFF; | 		regp->CRTC[NV_CIO_CRE_85] = 0xFF; | ||||||
| 		regp->CRTC[NV_CIO_CRE_86] = 0x1; | 		regp->CRTC[NV_CIO_CRE_86] = 0x1; | ||||||
| 	} | 	} | ||||||
|  | @ -571,7 +582,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | ||||||
| 
 | 
 | ||||||
| 	/* Generic PRAMDAC regs */ | 	/* Generic PRAMDAC regs */ | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_10) | 	if (nv_device(drm->device)->card_type >= NV_10) | ||||||
| 		/* Only bit that bios and blob set. */ | 		/* Only bit that bios and blob set. */ | ||||||
| 		regp->nv10_cursync = (1 << 25); | 		regp->nv10_cursync = (1 << 25); | ||||||
| 
 | 
 | ||||||
|  | @ -580,7 +591,7 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | ||||||
| 				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; | 				NV_PRAMDAC_GENERAL_CONTROL_PIXMIX_ON; | ||||||
| 	if (crtc->fb->depth == 16) | 	if (crtc->fb->depth == 16) | ||||||
| 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; | 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_ALT_MODE_SEL; | ||||||
| 	if (dev_priv->chipset >= 0x11) | 	if (nv_device(drm->device)->chipset >= 0x11) | ||||||
| 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; | 		regp->ramdac_gen_ctrl |= NV_PRAMDAC_GENERAL_CONTROL_PIPE_LONG; | ||||||
| 
 | 
 | ||||||
| 	regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */ | 	regp->ramdac_630 = 0; /* turn off green mode (tv test pattern?) */ | ||||||
|  | @ -610,9 +621,9 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||||||
| { | { | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "CTRC mode on CRTC %d:\n", nv_crtc->index); | 	NV_DEBUG(drm, "CTRC mode on CRTC %d:\n", nv_crtc->index); | ||||||
| 	drm_mode_debug_printmodeline(adjusted_mode); | 	drm_mode_debug_printmodeline(adjusted_mode); | ||||||
| 
 | 
 | ||||||
| 	/* unlock must come after turning off FP_TG_CONTROL in output_prepare */ | 	/* unlock must come after turning off FP_TG_CONTROL in output_prepare */ | ||||||
|  | @ -620,7 +631,7 @@ nv_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, | ||||||
| 
 | 
 | ||||||
| 	nv_crtc_mode_set_vga(crtc, adjusted_mode); | 	nv_crtc_mode_set_vga(crtc, adjusted_mode); | ||||||
| 	/* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */ | 	/* calculated in nv04_dfp_prepare, nv40 needs it written before calculating PLLs */ | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, nv04_display(dev)->mode_reg.sel_clk); | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_SEL_CLK, nv04_display(dev)->mode_reg.sel_clk); | ||||||
| 	nv_crtc_mode_set_regs(crtc, adjusted_mode); | 	nv_crtc_mode_set_regs(crtc, adjusted_mode); | ||||||
| 	nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock); | 	nv_crtc_calc_state_ext(crtc, mode, adjusted_mode->clock); | ||||||
|  | @ -667,7 +678,7 @@ static void nv_crtc_restore(struct drm_crtc *crtc) | ||||||
| static void nv_crtc_prepare(struct drm_crtc *crtc) | static void nv_crtc_prepare(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct drm_crtc_helper_funcs *funcs = crtc->helper_private; | 	struct drm_crtc_helper_funcs *funcs = crtc->helper_private; | ||||||
| 
 | 
 | ||||||
|  | @ -681,7 +692,7 @@ static void nv_crtc_prepare(struct drm_crtc *crtc) | ||||||
| 
 | 
 | ||||||
| 	/* Some more preparation. */ | 	/* Some more preparation. */ | ||||||
| 	NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA); | 	NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA); | ||||||
| 	if (dev_priv->card_type == NV_40) { | 	if (nv_device(drm->device)->card_type == NV_40) { | ||||||
| 		uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900); | 		uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900); | ||||||
| 		NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000); | 		NVWriteRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900, reg900 & ~0x10000); | ||||||
| 	} | 	} | ||||||
|  | @ -713,8 +724,6 @@ static void nv_crtc_destroy(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(crtc->dev, "\n"); |  | ||||||
| 
 |  | ||||||
| 	if (!nv_crtc) | 	if (!nv_crtc) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  | @ -776,18 +785,18 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | ||||||
| { | { | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | ||||||
| 	struct drm_framebuffer *drm_fb; | 	struct drm_framebuffer *drm_fb; | ||||||
| 	struct nouveau_framebuffer *fb; | 	struct nouveau_framebuffer *fb; | ||||||
| 	int arb_burst, arb_lwm; | 	int arb_burst, arb_lwm; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 	NV_DEBUG(drm, "index %d\n", nv_crtc->index); | ||||||
| 
 | 
 | ||||||
| 	/* no fb bound */ | 	/* no fb bound */ | ||||||
| 	if (!atomic && !crtc->fb) { | 	if (!atomic && !crtc->fb) { | ||||||
| 		NV_DEBUG_KMS(dev, "No FB bound\n"); | 		NV_DEBUG(drm, "No FB bound\n"); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -855,7 +864,7 @@ nv04_crtc_do_mode_set_base(struct drm_crtc *crtc, | ||||||
| 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); | 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FF_INDEX); | ||||||
| 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); | 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_FFLWM__INDEX); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_20) { | 	if (nv_device(drm->device)->card_type >= NV_20) { | ||||||
| 		regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; | 		regp->CRTC[NV_CIO_CRE_47] = arb_lwm >> 8; | ||||||
| 		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); | 		crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_47); | ||||||
| 	} | 	} | ||||||
|  | @ -875,8 +884,8 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc, | ||||||
| 			       struct drm_framebuffer *fb, | 			       struct drm_framebuffer *fb, | ||||||
| 			       int x, int y, enum mode_set_atomic state) | 			       int x, int y, enum mode_set_atomic state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
| 	struct drm_device *dev = dev_priv->dev; | 	struct drm_device *dev = drm->dev; | ||||||
| 
 | 
 | ||||||
| 	if (state == ENTER_ATOMIC_MODE_SET) | 	if (state == ENTER_ATOMIC_MODE_SET) | ||||||
| 		nouveau_fbcon_save_disable_accel(dev); | 		nouveau_fbcon_save_disable_accel(dev); | ||||||
|  | @ -931,9 +940,9 @@ static void nv11_cursor_upload(struct drm_device *dev, struct nouveau_bo *src, | ||||||
| 
 | 
 | ||||||
| #ifdef __BIG_ENDIAN | #ifdef __BIG_ENDIAN | ||||||
| 		{ | 		{ | ||||||
| 			struct drm_nouveau_private *dev_priv = dev->dev_private; | 			struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 			if (dev_priv->chipset == 0x11) { | 			if (nv_device(drm->device)->chipset == 0x11) { | ||||||
| 				pixel = ((pixel & 0x000000ff) << 24) | | 				pixel = ((pixel & 0x000000ff) << 24) | | ||||||
| 					((pixel & 0x0000ff00) << 8) | | 					((pixel & 0x0000ff00) << 8) | | ||||||
| 					((pixel & 0x00ff0000) >> 8) | | 					((pixel & 0x00ff0000) >> 8) | | ||||||
|  | @ -950,8 +959,8 @@ static int | ||||||
| nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | ||||||
| 		     uint32_t buffer_handle, uint32_t width, uint32_t height) | 		     uint32_t buffer_handle, uint32_t width, uint32_t height) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
| 	struct drm_device *dev = dev_priv->dev; | 	struct drm_device *dev = drm->dev; | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct nouveau_bo *cursor = NULL; | 	struct nouveau_bo *cursor = NULL; | ||||||
| 	struct drm_gem_object *gem; | 	struct drm_gem_object *gem; | ||||||
|  | @ -974,7 +983,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset >= 0x11) | 	if (nv_device(drm->device)->chipset >= 0x11) | ||||||
| 		nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); | 		nv11_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); | ||||||
| 	else | 	else | ||||||
| 		nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); | 		nv04_cursor_upload(dev, cursor, nv_crtc->cursor.nvbo); | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_mode.h" | #include "drm_mode.h" | ||||||
|  | #include "nouveau_drm.h" | ||||||
| #include "nouveau_reg.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| 
 | 
 | ||||||
|  | @ -38,7 +38,7 @@ static void | ||||||
| nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) | nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | ||||||
| 	struct drm_crtc *crtc = &nv_crtc->base; | 	struct drm_crtc *crtc = &nv_crtc->base; | ||||||
| 
 | 
 | ||||||
|  | @ -55,7 +55,7 @@ nv04_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) | ||||||
| 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | ||||||
| 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | ||||||
| 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); | 	crtc_wr_cio_state(crtc, regp, NV_CIO_CRE_HCUR_ADDR2_INDEX); | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		nv_fix_nv40_hw_cursor(dev, nv_crtc->index); | 		nv_fix_nv40_hw_cursor(dev, nv_crtc->index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -27,7 +27,7 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
|  | @ -35,6 +35,8 @@ | ||||||
| #include "nvreg.h" | #include "nvreg.h" | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/gpio.h> | #include <subdev/bios/gpio.h> | ||||||
|  | #include <subdev/gpio.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
| 
 | 
 | ||||||
| int nv04_dac_output_offset(struct drm_encoder *encoder) | int nv04_dac_output_offset(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
|  | @ -63,6 +65,8 @@ int nv04_dac_output_offset(struct drm_encoder *encoder) | ||||||
| 
 | 
 | ||||||
| static int sample_load_twice(struct drm_device *dev, bool sense[2]) | static int sample_load_twice(struct drm_device *dev, bool sense[2]) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_timer *ptimer = nouveau_timer(device); | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
|  | @ -76,27 +80,30 @@ static int sample_load_twice(struct drm_device *dev, bool sense[2]) | ||||||
| 		 * use a 10ms timeout (guards against crtc being inactive, in | 		 * use a 10ms timeout (guards against crtc being inactive, in | ||||||
| 		 * which case blank state would never change) | 		 * which case blank state would never change) | ||||||
| 		 */ | 		 */ | ||||||
| 		if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, | 		if (!nouveau_timer_wait_eq(ptimer, 10000000, | ||||||
|  | 					   NV_PRMCIO_INP0__COLOR, | ||||||
| 					   0x00000001, 0x00000000)) | 					   0x00000001, 0x00000000)) | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 		if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, | 		if (!nouveau_timer_wait_eq(ptimer, 10000000, | ||||||
|  | 					   NV_PRMCIO_INP0__COLOR, | ||||||
| 					   0x00000001, 0x00000001)) | 					   0x00000001, 0x00000001)) | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 		if (!nouveau_wait_eq(dev, 10000000, NV_PRMCIO_INP0__COLOR, | 		if (!nouveau_timer_wait_eq(ptimer, 10000000, | ||||||
|  | 					   NV_PRMCIO_INP0__COLOR, | ||||||
| 					   0x00000001, 0x00000000)) | 					   0x00000001, 0x00000000)) | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 
 | 
 | ||||||
| 		udelay(100); | 		udelay(100); | ||||||
| 		/* when level triggers, sense is _LO_ */ | 		/* when level triggers, sense is _LO_ */ | ||||||
| 		sense_a = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; | 		sense_a = nv_rd08(device, NV_PRMCIO_INP0) & 0x10; | ||||||
| 
 | 
 | ||||||
| 		/* take another reading until it agrees with sense_a... */ | 		/* take another reading until it agrees with sense_a... */ | ||||||
| 		do { | 		do { | ||||||
| 			udelay(100); | 			udelay(100); | ||||||
| 			sense_b = nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; | 			sense_b = nv_rd08(device, NV_PRMCIO_INP0) & 0x10; | ||||||
| 			if (sense_a != sense_b) { | 			if (sense_a != sense_b) { | ||||||
| 				sense_b_prime = | 				sense_b_prime = | ||||||
| 					nv_rd08(dev, NV_PRMCIO_INP0) & 0x10; | 					nv_rd08(device, NV_PRMCIO_INP0) & 0x10; | ||||||
| 				if (sense_b == sense_b_prime) { | 				if (sense_b == sense_b_prime) { | ||||||
| 					/* ... unless two consecutive subsequent
 | 					/* ... unless two consecutive subsequent
 | ||||||
| 					 * samples agree; sense_a is replaced */ | 					 * samples agree; sense_a is replaced */ | ||||||
|  | @ -121,6 +128,8 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, | ||||||
| 						 struct drm_connector *connector) | 						 struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode; | 	uint8_t saved_seq1, saved_pi, saved_rpc1, saved_cr_mode; | ||||||
| 	uint8_t saved_palette0[3], saved_palette_mask; | 	uint8_t saved_palette0[3], saved_palette_mask; | ||||||
| 	uint32_t saved_rtest_ctrl, saved_rgen_ctrl; | 	uint32_t saved_rtest_ctrl, saved_rgen_ctrl; | ||||||
|  | @ -155,11 +164,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, | ||||||
| 	saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX); | 	saved_rpc1 = NVReadVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX); | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0); | 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1 & ~0xc0); | ||||||
| 
 | 
 | ||||||
| 	nv_wr08(dev, NV_PRMDIO_READ_MODE_ADDRESS, 0x0); | 	nv_wr08(device, NV_PRMDIO_READ_MODE_ADDRESS, 0x0); | ||||||
| 	for (i = 0; i < 3; i++) | 	for (i = 0; i < 3; i++) | ||||||
| 		saved_palette0[i] = nv_rd08(dev, NV_PRMDIO_PALETTE_DATA); | 		saved_palette0[i] = nv_rd08(device, NV_PRMDIO_PALETTE_DATA); | ||||||
| 	saved_palette_mask = nv_rd08(dev, NV_PRMDIO_PIXEL_MASK); | 	saved_palette_mask = nv_rd08(device, NV_PRMDIO_PIXEL_MASK); | ||||||
| 	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, 0); | 	nv_wr08(device, NV_PRMDIO_PIXEL_MASK, 0); | ||||||
| 
 | 
 | ||||||
| 	saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL); | 	saved_rgen_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL); | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, | ||||||
|  | @ -172,11 +181,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, | ||||||
| 	do { | 	do { | ||||||
| 		bool sense_pair[2]; | 		bool sense_pair[2]; | ||||||
| 
 | 
 | ||||||
| 		nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); | 		nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); | ||||||
| 		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0); | 		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0); | ||||||
| 		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, 0); | 		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, 0); | ||||||
| 		/* testing blue won't find monochrome monitors.  I don't care */ | 		/* testing blue won't find monochrome monitors.  I don't care */ | ||||||
| 		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, blue); | 		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, blue); | ||||||
| 
 | 
 | ||||||
| 		i = 0; | 		i = 0; | ||||||
| 		/* take sample pairs until both samples in the pair agree */ | 		/* take sample pairs until both samples in the pair agree */ | ||||||
|  | @ -199,11 +208,11 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, | ||||||
| 	} while (++blue < 0x18 && sense); | 	} while (++blue < 0x18 && sense); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	nv_wr08(dev, NV_PRMDIO_PIXEL_MASK, saved_palette_mask); | 	nv_wr08(device, NV_PRMDIO_PIXEL_MASK, saved_palette_mask); | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_GENERAL_CONTROL, saved_rgen_ctrl); | ||||||
| 	nv_wr08(dev, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); | 	nv_wr08(device, NV_PRMDIO_WRITE_MODE_ADDRESS, 0); | ||||||
| 	for (i = 0; i < 3; i++) | 	for (i = 0; i < 3; i++) | ||||||
| 		nv_wr08(dev, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]); | 		nv_wr08(device, NV_PRMDIO_PALETTE_DATA, saved_palette0[i]); | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL, saved_rtest_ctrl); | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi); | 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_PIXEL_INDEX, saved_pi); | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1); | 	NVWriteVgaCrtc(dev, 0, NV_CIO_CRE_RPC1_INDEX, saved_rpc1); | ||||||
|  | @ -211,7 +220,7 @@ out: | ||||||
| 	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); | 	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); | ||||||
| 
 | 
 | ||||||
| 	if (blue == 0x18) { | 	if (blue == 0x18) { | ||||||
| 		NV_INFO(dev, "Load detected on head A\n"); | 		NV_INFO(drm, "Load detected on head A\n"); | ||||||
| 		return connector_status_connected; | 		return connector_status_connected; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -221,43 +230,46 @@ out: | ||||||
| uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(device); | ||||||
| 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | ||||||
| 	uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); | 	uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); | ||||||
| 	uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, | 	uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, | ||||||
| 		saved_rtest_ctrl, saved_gpio0, saved_gpio1, temp, routput; | 		saved_rtest_ctrl, saved_gpio0 = 0, saved_gpio1 = 0, temp, routput; | ||||||
| 	int head; | 	int head; | ||||||
| 
 | 
 | ||||||
| #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) | #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) | ||||||
| 	if (dcb->type == DCB_OUTPUT_TV) { | 	if (dcb->type == DCB_OUTPUT_TV) { | ||||||
| 		testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0); | 		testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0); | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->vbios.tvdactestval) | 		if (drm->vbios.tvdactestval) | ||||||
| 			testval = dev_priv->vbios.tvdactestval; | 			testval = drm->vbios.tvdactestval; | ||||||
| 	} else { | 	} else { | ||||||
| 		testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */ | 		testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */ | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->vbios.dactestval) | 		if (drm->vbios.dactestval) | ||||||
| 			testval = dev_priv->vbios.dactestval; | 			testval = drm->vbios.dactestval; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); | 	saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset); | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, | ||||||
| 		      saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); | 		      saved_rtest_ctrl & ~NV_PRAMDAC_TEST_CONTROL_PWRDWN_DAC_OFF); | ||||||
| 
 | 
 | ||||||
| 	saved_powerctrl_2 = nv_rd32(dev, NV_PBUS_POWERCTRL_2); | 	saved_powerctrl_2 = nv_rd32(device, NV_PBUS_POWERCTRL_2); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff); | 	nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2 & 0xd7ffffff); | ||||||
| 	if (regoffset == 0x68) { | 	if (regoffset == 0x68) { | ||||||
| 		saved_powerctrl_4 = nv_rd32(dev, NV_PBUS_POWERCTRL_4); | 		saved_powerctrl_4 = nv_rd32(device, NV_PBUS_POWERCTRL_4); | ||||||
| 		nv_wr32(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); | 		nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	saved_gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); | 	if (gpio) { | ||||||
| 	saved_gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); | 		saved_gpio1 = gpio->get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); | ||||||
| 
 | 		saved_gpio0 = gpio->get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, dcb->type == DCB_OUTPUT_TV); | 		gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, dcb->type == DCB_OUTPUT_TV); | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, dcb->type == DCB_OUTPUT_TV); | 		gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, dcb->type == DCB_OUTPUT_TV); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	msleep(4); | 	msleep(4); | ||||||
| 
 | 
 | ||||||
|  | @ -271,7 +283,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | ||||||
| 	/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ | 	/* nv driver and nv31 use 0xfffffeee, nv34 and 6600 use 0xfffffece */ | ||||||
| 	routput = (saved_routput & 0xfffffece) | head << 8; | 	routput = (saved_routput & 0xfffffece) | head << 8; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type >= NV_40) { | 	if (nv_device(drm->device)->card_type >= NV_40) { | ||||||
| 		if (dcb->type == DCB_OUTPUT_TV) | 		if (dcb->type == DCB_OUTPUT_TV) | ||||||
| 			routput |= 0x1a << 16; | 			routput |= 0x1a << 16; | ||||||
| 		else | 		else | ||||||
|  | @ -304,11 +316,13 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset, saved_routput); | ||||||
| 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl); | 	NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset, saved_rtest_ctrl); | ||||||
| 	if (regoffset == 0x68) | 	if (regoffset == 0x68) | ||||||
| 		nv_wr32(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); | 		nv_wr32(device, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); | ||||||
| 	nv_wr32(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); | 	nv_wr32(device, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); | ||||||
| 
 | 
 | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); | 	if (gpio) { | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); | 		gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, saved_gpio1); | ||||||
|  | 		gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, saved_gpio0); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	return sample; | 	return sample; | ||||||
| } | } | ||||||
|  | @ -316,7 +330,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) | ||||||
| static enum drm_connector_status | static enum drm_connector_status | ||||||
| nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | ||||||
| 
 | 
 | ||||||
| 	if (nv04_dac_in_use(encoder)) | 	if (nv04_dac_in_use(encoder)) | ||||||
|  | @ -324,7 +338,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| 
 | 
 | ||||||
| 	if (nv17_dac_sample_load(encoder) & | 	if (nv17_dac_sample_load(encoder) & | ||||||
| 	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { | 	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { | ||||||
| 		NV_INFO(dev, "Load detected on output %c\n", | 		NV_INFO(drm, "Load detected on output %c\n", | ||||||
| 			'@' + ffs(dcb->or)); | 			'@' + ffs(dcb->or)); | ||||||
| 		return connector_status_connected; | 		return connector_status_connected; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -358,7 +372,7 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, | ||||||
| 			      struct drm_display_mode *adjusted_mode) | 			      struct drm_display_mode *adjusted_mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int head = nouveau_crtc(encoder->crtc)->index; | 	int head = nouveau_crtc(encoder->crtc)->index; | ||||||
| 
 | 
 | ||||||
| 	if (nv_gf4_disp_arch(dev)) { | 	if (nv_gf4_disp_arch(dev)) { | ||||||
|  | @ -384,7 +398,7 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* This could use refinement for flatpanels, but it should work this way */ | 	/* This could use refinement for flatpanels, but it should work this way */ | ||||||
| 	if (dev_priv->chipset < 0x44) | 	if (nv_device(drm->device)->chipset < 0x44) | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); | ||||||
| 	else | 	else | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | ||||||
|  | @ -393,13 +407,13 @@ static void nv04_dac_mode_set(struct drm_encoder *encoder, | ||||||
| static void nv04_dac_commit(struct drm_encoder *encoder) | static void nv04_dac_commit(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | ||||||
| 
 | 
 | ||||||
| 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", | ||||||
| 		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), | 		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), | ||||||
| 		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | 		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | ||||||
| } | } | ||||||
|  | @ -440,14 +454,14 @@ bool nv04_dac_in_use(struct drm_encoder *encoder) | ||||||
| 
 | 
 | ||||||
| static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) | static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; |  | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 
 | 
 | ||||||
| 	if (nv_encoder->last_dpms == mode) | 	if (nv_encoder->last_dpms == mode) | ||||||
| 		return; | 		return; | ||||||
| 	nv_encoder->last_dpms = mode; | 	nv_encoder->last_dpms = mode; | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n", | 	NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", | ||||||
| 		     mode, nv_encoder->dcb->index); | 		     mode, nv_encoder->dcb->index); | ||||||
| 
 | 
 | ||||||
| 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); | 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); | ||||||
|  | @ -479,8 +493,6 @@ static void nv04_dac_destroy(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "\n"); |  | ||||||
| 
 |  | ||||||
| 	drm_encoder_cleanup(encoder); | 	drm_encoder_cleanup(encoder); | ||||||
| 	kfree(nv_encoder); | 	kfree(nv_encoder); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,7 +27,8 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
|  | @ -36,6 +37,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "i2c/sil164.h" | #include "i2c/sil164.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/i2c.h> | ||||||
|  | 
 | ||||||
| #define FP_TG_CONTROL_ON  (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |	\ | #define FP_TG_CONTROL_ON  (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS |	\ | ||||||
| 			   NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |		\ | 			   NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS |		\ | ||||||
| 			   NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) | 			   NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) | ||||||
|  | @ -278,7 +281,8 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| 			      struct drm_display_mode *adjusted_mode) | 			      struct drm_display_mode *adjusted_mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *regp = &nv04_display(dev)->mode_reg.crtc_reg[nv_crtc->index]; | ||||||
| 	struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index]; | 	struct nv04_crtc_reg *savep = &nv04_display(dev)->saved_reg.crtc_reg[nv_crtc->index]; | ||||||
|  | @ -288,7 +292,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| 	struct drm_connector *connector = &nv_connector->base; | 	struct drm_connector *connector = &nv_connector->base; | ||||||
| 	uint32_t mode_ratio, panel_ratio; | 	uint32_t mode_ratio, panel_ratio; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index); | 	NV_DEBUG(drm, "Output mode on CRTC %d:\n", nv_crtc->index); | ||||||
| 	drm_mode_debug_printmodeline(output_mode); | 	drm_mode_debug_printmodeline(output_mode); | ||||||
| 
 | 
 | ||||||
| 	/* Initialize the FP registers in this CRTC. */ | 	/* Initialize the FP registers in this CRTC. */ | ||||||
|  | @ -296,10 +300,10 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| 	regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1; | 	regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1; | ||||||
| 	if (!nv_gf4_disp_arch(dev) || | 	if (!nv_gf4_disp_arch(dev) || | ||||||
| 	    (output_mode->hsync_start - output_mode->hdisplay) >= | 	    (output_mode->hsync_start - output_mode->hdisplay) >= | ||||||
| 					dev_priv->vbios.digital_min_front_porch) | 					drm->vbios.digital_min_front_porch) | ||||||
| 		regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay; | 		regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay; | ||||||
| 	else | 	else | ||||||
| 		regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - dev_priv->vbios.digital_min_front_porch - 1; | 		regp->fp_horiz_regs[FP_CRTC] = output_mode->hsync_start - drm->vbios.digital_min_front_porch - 1; | ||||||
| 	regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1; | 	regp->fp_horiz_regs[FP_SYNC_START] = output_mode->hsync_start - 1; | ||||||
| 	regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1; | 	regp->fp_horiz_regs[FP_SYNC_END] = output_mode->hsync_end - 1; | ||||||
| 	regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew; | 	regp->fp_horiz_regs[FP_VALID_START] = output_mode->hskew; | ||||||
|  | @ -331,7 +335,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE; | 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_NATIVE; | ||||||
| 	else /* gpu needs to scale */ | 	else /* gpu needs to scale */ | ||||||
| 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE; | 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_MODE_SCALE; | ||||||
| 	if (nv_rd32(dev, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT) | 	if (nv_rd32(device, NV_PEXTDEV_BOOT_0) & NV_PEXTDEV_BOOT_0_STRAP_FP_IFACE_12BIT) | ||||||
| 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12; | 		regp->fp_control |= NV_PRAMDAC_FP_TG_CONTROL_WIDTH_12; | ||||||
| 	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && | 	if (nv_encoder->dcb->location != DCB_LOC_ON_CHIP && | ||||||
| 	    output_mode->clock > 165000) | 	    output_mode->clock > 165000) | ||||||
|  | @ -412,7 +416,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| 	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || | 	if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || | ||||||
| 	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO && | 	    (nv_connector->dithering_mode == DITHERING_MODE_AUTO && | ||||||
| 	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { | 	     encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { | ||||||
| 		if (dev_priv->chipset == 0x11) | 		if (nv_device(drm->device)->chipset == 0x11) | ||||||
| 			regp->dither = savep->dither | 0x00010000; | 			regp->dither = savep->dither | 0x00010000; | ||||||
| 		else { | 		else { | ||||||
| 			int i; | 			int i; | ||||||
|  | @ -423,7 +427,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		if (dev_priv->chipset != 0x11) { | 		if (nv_device(drm->device)->chipset != 0x11) { | ||||||
| 			/* reset them */ | 			/* reset them */ | ||||||
| 			int i; | 			int i; | ||||||
| 			for (i = 0; i < 3; i++) { | 			for (i = 0; i < 3; i++) { | ||||||
|  | @ -440,7 +444,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, | ||||||
| static void nv04_dfp_commit(struct drm_encoder *encoder) | static void nv04_dfp_commit(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | @ -459,7 +463,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) | ||||||
| 		NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); | 		NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_TG_CONTROL); | ||||||
| 
 | 
 | ||||||
| 	/* This could use refinement for flatpanels, but it should work this way */ | 	/* This could use refinement for flatpanels, but it should work this way */ | ||||||
| 	if (dev_priv->chipset < 0x44) | 	if (nv_device(drm->device)->chipset < 0x44) | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0xf0000000); | ||||||
| 	else | 	else | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | ||||||
|  | @ -472,7 +476,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) | ||||||
| 
 | 
 | ||||||
| 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", | ||||||
| 		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), | 		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), | ||||||
| 		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | 		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | ||||||
| } | } | ||||||
|  | @ -481,6 +485,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| #ifdef __powerpc__ | #ifdef __powerpc__ | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	/* BIOS scripts usually take care of the backlight, thanks
 | 	/* BIOS scripts usually take care of the backlight, thanks
 | ||||||
| 	 * Apple for your consistency. | 	 * Apple for your consistency. | ||||||
|  | @ -488,11 +493,11 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) | ||||||
| 	if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || | 	if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || | ||||||
| 	    dev->pci_device == 0x0329) { | 	    dev->pci_device == 0x0329) { | ||||||
| 		if (mode == DRM_MODE_DPMS_ON) { | 		if (mode == DRM_MODE_DPMS_ON) { | ||||||
| 			nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); | 			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); | ||||||
| 			nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 1); | 			nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1); | ||||||
| 		} else { | 		} else { | ||||||
| 			nv_mask(dev, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); | 			nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 1 << 31, 0); | ||||||
| 			nv_mask(dev, NV_PCRTC_GPIO_EXT, 3, 0); | 			nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 0); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| #endif | #endif | ||||||
|  | @ -507,6 +512,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_crtc *crtc = encoder->crtc; | 	struct drm_crtc *crtc = encoder->crtc; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms); | 	bool was_powersaving = is_powersaving_dpms(nv_encoder->last_dpms); | ||||||
| 
 | 
 | ||||||
|  | @ -514,7 +520,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 		return; | 		return; | ||||||
| 	nv_encoder->last_dpms = mode; | 	nv_encoder->last_dpms = mode; | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", | 	NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", | ||||||
| 		     mode, nv_encoder->dcb->index); | 		     mode, nv_encoder->dcb->index); | ||||||
| 
 | 
 | ||||||
| 	if (was_powersaving && is_powersaving_dpms(mode)) | 	if (was_powersaving && is_powersaving_dpms(mode)) | ||||||
|  | @ -552,14 +558,14 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 
 | 
 | ||||||
| static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) | static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 
 | 
 | ||||||
| 	if (nv_encoder->last_dpms == mode) | 	if (nv_encoder->last_dpms == mode) | ||||||
| 		return; | 		return; | ||||||
| 	nv_encoder->last_dpms = mode; | 	nv_encoder->last_dpms = mode; | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", | 	NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", | ||||||
| 		     mode, nv_encoder->dcb->index); | 		     mode, nv_encoder->dcb->index); | ||||||
| 
 | 
 | ||||||
| 	nv04_dfp_update_backlight(encoder, mode); | 	nv04_dfp_update_backlight(encoder, mode); | ||||||
|  | @ -605,8 +611,6 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "\n"); |  | ||||||
| 
 |  | ||||||
| 	if (get_slave_funcs(encoder)) | 	if (get_slave_funcs(encoder)) | ||||||
| 		get_slave_funcs(encoder)->destroy(encoder); | 		get_slave_funcs(encoder)->destroy(encoder); | ||||||
| 
 | 
 | ||||||
|  | @ -618,7 +622,9 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | ||||||
| 	struct nouveau_i2c_port *i2c = nouveau_i2c_find(dev, 2); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
|  | 	struct nouveau_i2c_port *port = i2c->find(i2c, 2); | ||||||
| 	struct i2c_board_info info[] = { | 	struct i2c_board_info info[] = { | ||||||
| 		{ | 		{ | ||||||
| 			.type = "sil164", | 			.type = "sil164", | ||||||
|  | @ -631,16 +637,16 @@ static void nv04_tmds_slave_init(struct drm_encoder *encoder) | ||||||
| 	}; | 	}; | ||||||
| 	int type; | 	int type; | ||||||
| 
 | 
 | ||||||
| 	if (!nv_gf4_disp_arch(dev) || !i2c || | 	if (!nv_gf4_disp_arch(dev) || !port || | ||||||
| 	    get_tmds_slave(encoder)) | 	    get_tmds_slave(encoder)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	type = nouveau_i2c_identify(dev, "TMDS transmitter", info, NULL, 2); | 	type = i2c->identify(i2c, 2, "TMDS transmitter", info, NULL); | ||||||
| 	if (type < 0) | 	if (type < 0) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | 	drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | ||||||
| 			     nouveau_i2c_adapter(i2c), &info[type]); | 			     &port->adapter, &info[type]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { | ||||||
|  |  | ||||||
|  | @ -26,8 +26,8 @@ | ||||||
| #include "drm.h" | #include "drm.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_fb.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
|  | @ -53,21 +53,25 @@ nv04_display_late_takedown(struct drm_device *dev) | ||||||
| int | int | ||||||
| nv04_display_create(struct drm_device *dev) | nv04_display_create(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_table *dcb = &dev_priv->vbios.dcb; | 	struct dcb_table *dcb = &drm->vbios.dcb; | ||||||
| 	struct drm_connector *connector, *ct; | 	struct drm_connector *connector, *ct; | ||||||
| 	struct drm_encoder *encoder; | 	struct drm_encoder *encoder; | ||||||
| 	struct drm_crtc *crtc; | 	struct drm_crtc *crtc; | ||||||
| 	struct nv04_display *disp; | 	struct nv04_display *disp; | ||||||
| 	int i, ret; | 	int i, ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	disp = kzalloc(sizeof(*disp), GFP_KERNEL); | 	disp = kzalloc(sizeof(*disp), GFP_KERNEL); | ||||||
| 	dev_priv->engine.display.priv = disp; |  | ||||||
| 	if (!disp) | 	if (!disp) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 
 | 
 | ||||||
|  | 	nouveau_display(dev)->priv = disp; | ||||||
|  | 	nouveau_display(dev)->dtor = nv04_display_destroy; | ||||||
|  | 	nouveau_display(dev)->init = nv04_display_init; | ||||||
|  | 	nouveau_display(dev)->fini = nv04_display_fini; | ||||||
|  | 
 | ||||||
| 	nouveau_hw_save_vga_fonts(dev, 1); | 	nouveau_hw_save_vga_fonts(dev, 1); | ||||||
| 
 | 
 | ||||||
| 	nv04_crtc_create(dev, 0); | 	nv04_crtc_create(dev, 0); | ||||||
|  | @ -96,7 +100,7 @@ nv04_display_create(struct drm_device *dev) | ||||||
| 				ret = nv04_tv_create(connector, dcbent); | 				ret = nv04_tv_create(connector, dcbent); | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_WARN(dev, "DCB type %d not known\n", dcbent->type); | 			NV_WARN(drm, "DCB type %d not known\n", dcbent->type); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -107,7 +111,7 @@ nv04_display_create(struct drm_device *dev) | ||||||
| 	list_for_each_entry_safe(connector, ct, | 	list_for_each_entry_safe(connector, ct, | ||||||
| 				 &dev->mode_config.connector_list, head) { | 				 &dev->mode_config.connector_list, head) { | ||||||
| 		if (!connector->encoder_ids[0]) { | 		if (!connector->encoder_ids[0]) { | ||||||
| 			NV_WARN(dev, "%s has no encoders, removing\n", | 			NV_WARN(drm, "%s has no encoders, removing\n", | ||||||
| 				drm_get_connector_name(connector)); | 				drm_get_connector_name(connector)); | ||||||
| 			connector->funcs->destroy(connector); | 			connector->funcs->destroy(connector); | ||||||
| 		} | 		} | ||||||
|  | @ -129,12 +133,12 @@ nv04_display_create(struct drm_device *dev) | ||||||
| void | void | ||||||
| nv04_display_destroy(struct drm_device *dev) | nv04_display_destroy(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv04_display *disp = nv04_display(dev); | 	struct nv04_display *disp = nv04_display(dev); | ||||||
| 	struct drm_encoder *encoder; | 	struct drm_encoder *encoder; | ||||||
| 	struct drm_crtc *crtc; | 	struct drm_crtc *crtc; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	/* Turn every CRTC off. */ | 	/* Turn every CRTC off. */ | ||||||
| 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||||||
|  | @ -157,7 +161,7 @@ nv04_display_destroy(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	nouveau_hw_save_vga_fonts(dev, 0); | 	nouveau_hw_save_vga_fonts(dev, 0); | ||||||
| 
 | 
 | ||||||
| 	dev_priv->engine.display.priv = NULL; | 	nouveau_display(dev)->priv = NULL; | ||||||
| 	kfree(disp); | 	kfree(disp); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,6 +3,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <subdev/bios/pll.h> | #include <subdev/bios/pll.h> | ||||||
| 
 | 
 | ||||||
|  | #include "nouveau_display.h" | ||||||
|  | 
 | ||||||
| enum nv04_fp_display_regs { | enum nv04_fp_display_regs { | ||||||
| 	FP_DISPLAY_END, | 	FP_DISPLAY_END, | ||||||
| 	FP_TOTAL, | 	FP_TOTAL, | ||||||
|  | @ -80,6 +82,12 @@ struct nv04_display { | ||||||
| 	uint32_t dac_users[4]; | 	uint32_t dac_users[4]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | static inline struct nv04_display * | ||||||
|  | nv04_display(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	return nouveau_display(dev)->priv; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* nv04_display.c */ | /* nv04_display.c */ | ||||||
| int nv04_display_early_init(struct drm_device *); | int nv04_display_early_init(struct drm_device *); | ||||||
| void nv04_display_late_takedown(struct drm_device *); | void nv04_display_late_takedown(struct drm_device *); | ||||||
|  | @ -113,4 +121,64 @@ int nv04_tv_create(struct drm_connector *, struct dcb_output *); | ||||||
| /* nv17_tv.c */ | /* nv17_tv.c */ | ||||||
| int nv17_tv_create(struct drm_connector *, struct dcb_output *); | int nv17_tv_create(struct drm_connector *, struct dcb_output *); | ||||||
| 
 | 
 | ||||||
|  | static inline bool | ||||||
|  | nv_two_heads(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	const int impl = dev->pci_device & 0x0ff0; | ||||||
|  | 
 | ||||||
|  | 	if (nv_device(drm->device)->card_type >= NV_10 && impl != 0x0100 && | ||||||
|  | 	    impl != 0x0150 && impl != 0x01a0 && impl != 0x0200) | ||||||
|  | 		return true; | ||||||
|  | 
 | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline bool | ||||||
|  | nv_gf4_disp_arch(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	return nv_two_heads(dev) && (dev->pci_device & 0x0ff0) != 0x0110; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline bool | ||||||
|  | nv_two_reg_pll(struct drm_device *dev) | ||||||
|  | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	const int impl = dev->pci_device & 0x0ff0; | ||||||
|  | 
 | ||||||
|  | 	if (impl == 0x0310 || impl == 0x0340 || nv_device(drm->device)->card_type >= NV_40) | ||||||
|  | 		return true; | ||||||
|  | 	return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static inline bool | ||||||
|  | nv_match_device(struct drm_device *dev, unsigned device, | ||||||
|  | 		unsigned sub_vendor, unsigned sub_device) | ||||||
|  | { | ||||||
|  | 	return dev->pdev->device == device && | ||||||
|  | 		dev->pdev->subsystem_vendor == sub_vendor && | ||||||
|  | 		dev->pdev->subsystem_device == sub_device; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #include <subdev/bios.h> | ||||||
|  | #include <subdev/bios/init.h> | ||||||
|  | 
 | ||||||
|  | static inline void | ||||||
|  | nouveau_bios_run_init_table(struct drm_device *dev, u16 table, | ||||||
|  | 			    struct dcb_output *outp, int crtc) | ||||||
|  | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
|  | 	struct nvbios_init init = { | ||||||
|  | 		.subdev = nv_subdev(bios), | ||||||
|  | 		.bios = bios, | ||||||
|  | 		.offset = table, | ||||||
|  | 		.outp = outp, | ||||||
|  | 		.crtc = crtc, | ||||||
|  | 		.execute = 1, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	nvbios_exec(&init); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -32,7 +32,7 @@ int | ||||||
| nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -52,7 +52,7 @@ int | ||||||
| nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -79,7 +79,7 @@ int | ||||||
| nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	uint32_t fg; | 	uint32_t fg; | ||||||
| 	uint32_t bg; | 	uint32_t bg; | ||||||
|  | @ -139,7 +139,7 @@ nv04_fbcon_accel_init(struct fb_info *info) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct drm_device *dev = nfbdev->dev; | 	struct drm_device *dev = nfbdev->dev; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	struct nouveau_device *device = nv_device(drm->device); | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	struct nouveau_object *object; | 	struct nouveau_object *object; | ||||||
|  |  | ||||||
|  | @ -23,10 +23,15 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | 
 | ||||||
| int | int | ||||||
| nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
|  | @ -58,13 +63,16 @@ struct nv04_pm_state { | ||||||
| static int | static int | ||||||
| calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) | calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
|  | 	struct nouveau_clock *pclk = nouveau_clock(device); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	ret = get_pll_limits(dev, id, &clk->pll); | 	ret = nvbios_pll_parse(bios, id, &clk->pll); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_calc_pll_mnp(dev, &clk->pll, khz, &clk->calc); | 	ret = pclk->pll_calc(pclk, &clk->pll, khz, &clk->calc); | ||||||
| 	if (!ret) | 	if (!ret) | ||||||
| 		return -EINVAL; | 		return -EINVAL; | ||||||
| 
 | 
 | ||||||
|  | @ -100,38 +108,38 @@ error: | ||||||
| static void | static void | ||||||
| prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) | prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_clock *pclk = nouveau_clock(device); | ||||||
| 	u32 reg = clk->pll.reg; | 	u32 reg = clk->pll.reg; | ||||||
| 
 | 
 | ||||||
| 	/* thank the insane nouveau_hw_setpll() interface for this */ | 	/* thank the insane nouveau_hw_setpll() interface for this */ | ||||||
| 	if (dev_priv->card_type >= NV_40) | 	if (device->card_type >= NV_40) | ||||||
| 		reg += 4; | 		reg += 4; | ||||||
| 
 | 
 | ||||||
| 	nouveau_hw_setpll(dev, reg, &clk->calc); | 	pclk->pll_prog(pclk, reg, &clk->calc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) | nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_timer *ptimer = nouveau_timer(device); | ||||||
| 	struct nv04_pm_state *state = pre_state; | 	struct nv04_pm_state *state = pre_state; | ||||||
| 
 | 
 | ||||||
| 	prog_pll(dev, &state->core); | 	prog_pll(dev, &state->core); | ||||||
| 
 | 
 | ||||||
| 	if (state->memory.pll.reg) { | 	if (state->memory.pll.reg) { | ||||||
| 		prog_pll(dev, &state->memory); | 		prog_pll(dev, &state->memory); | ||||||
| 		if (dev_priv->card_type < NV_30) { | 		if (device->card_type < NV_30) { | ||||||
| 			if (dev_priv->card_type == NV_20) | 			if (device->card_type == NV_20) | ||||||
| 				nv_mask(dev, 0x1002c4, 0, 1 << 20); | 				nv_mask(device, 0x1002c4, 0, 1 << 20); | ||||||
| 
 | 
 | ||||||
| 			/* Reset the DLLs */ | 			/* Reset the DLLs */ | ||||||
| 			nv_mask(dev, 0x1002c0, 0, 1 << 8); | 			nv_mask(device, 0x1002c0, 0, 1 << 8); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| #if 0 /*XXX*/
 | 	nv_ofuncs(ptimer)->init(nv_object(ptimer)); | ||||||
| 	ptimer->init(dev); |  | ||||||
| #endif |  | ||||||
| 
 | 
 | ||||||
| 	kfree(state); | 	kfree(state); | ||||||
| 	return 0; | 	return 0; | ||||||
|  |  | ||||||
|  | @ -25,7 +25,8 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
|  | @ -34,6 +35,8 @@ | ||||||
| 
 | 
 | ||||||
| #include "i2c/ch7006.h" | #include "i2c/ch7006.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/i2c.h> | ||||||
|  | 
 | ||||||
| static struct i2c_board_info nv04_tv_encoder_info[] = { | static struct i2c_board_info nv04_tv_encoder_info[] = { | ||||||
| 	{ | 	{ | ||||||
| 		I2C_BOARD_INFO("ch7006", 0x75), | 		I2C_BOARD_INFO("ch7006", 0x75), | ||||||
|  | @ -49,8 +52,11 @@ static struct i2c_board_info nv04_tv_encoder_info[] = { | ||||||
| 
 | 
 | ||||||
| int nv04_tv_identify(struct drm_device *dev, int i2c_index) | int nv04_tv_identify(struct drm_device *dev, int i2c_index) | ||||||
| { | { | ||||||
| 	return nouveau_i2c_identify(dev, "TV encoder", nv04_tv_encoder_info, | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 				    NULL, i2c_index); | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
|  | 
 | ||||||
|  | 	return i2c->identify(i2c, i2c_index, "TV encoder", | ||||||
|  | 			     nv04_tv_encoder_info, NULL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -64,11 +70,12 @@ int nv04_tv_identify(struct drm_device *dev, int i2c_index) | ||||||
| static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) | static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; | 	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg; | ||||||
| 	uint8_t crtc1A; | 	uint8_t crtc1A; | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", | 	NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", | ||||||
| 		mode, nv_encoder->dcb->index); | 		mode, nv_encoder->dcb->index); | ||||||
| 
 | 
 | ||||||
| 	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); | 	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); | ||||||
|  | @ -154,12 +161,13 @@ static void nv04_tv_commit(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | ||||||
| 
 | 
 | ||||||
| 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", | ||||||
| 		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, | 		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, | ||||||
| 		      '@' + ffs(nv_encoder->dcb->or)); | 		      '@' + ffs(nv_encoder->dcb->or)); | ||||||
| } | } | ||||||
|  | @ -185,8 +193,9 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
| 	struct drm_encoder_helper_funcs *hfuncs; | 	struct drm_encoder_helper_funcs *hfuncs; | ||||||
| 	struct drm_encoder_slave_funcs *sfuncs; | 	struct drm_encoder_slave_funcs *sfuncs; | ||||||
| 	struct nouveau_i2c_port *i2c = | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 		nouveau_i2c_find(dev, entry->i2c_index); | 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | ||||||
|  | 	struct nouveau_i2c_port *port = i2c->find(i2c, entry->i2c_index); | ||||||
| 	int type, ret; | 	int type, ret; | ||||||
| 
 | 
 | ||||||
| 	/* Ensure that we can talk to this encoder */ | 	/* Ensure that we can talk to this encoder */ | ||||||
|  | @ -218,7 +227,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_output *entry) | ||||||
| 
 | 
 | ||||||
| 	/* Run the slave-specific initialization */ | 	/* Run the slave-specific initialization */ | ||||||
| 	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | 	ret = drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | ||||||
| 				   nouveau_i2c_adapter(i2c), &nv04_tv_encoder_info[type]); | 				   &port->adapter, &nv04_tv_encoder_info[type]); | ||||||
| 	if (ret < 0) | 	if (ret < 0) | ||||||
| 		goto fail_cleanup; | 		goto fail_cleanup; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -26,19 +26,32 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nv17_tv.h" | #include "nv17_tv.h" | ||||||
| 
 | 
 | ||||||
|  | #include <core/device.h> | ||||||
|  | 
 | ||||||
| #include <subdev/bios/gpio.h> | #include <subdev/bios/gpio.h> | ||||||
|  | #include <subdev/gpio.h> | ||||||
|  | 
 | ||||||
|  | MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" | ||||||
|  | 		 "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" | ||||||
|  | 		 "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" | ||||||
|  | 		 "\t\tDefault: PAL\n" | ||||||
|  | 		 "\t\t*NOTE* Ignored for cards with external TV encoders."); | ||||||
|  | static char *nouveau_tv_norm; | ||||||
|  | module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); | ||||||
| 
 | 
 | ||||||
| static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
| 	uint32_t testval, regoffset = nv04_dac_output_offset(encoder); | 	uint32_t testval, regoffset = nv04_dac_output_offset(encoder); | ||||||
| 	uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, | 	uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, | ||||||
| 		fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; | 		fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; | ||||||
|  | @ -47,15 +60,15 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | ||||||
| 
 | 
 | ||||||
| #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) | #define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20) | ||||||
| 	testval = RGB_TEST_DATA(0x82, 0xeb, 0x82); | 	testval = RGB_TEST_DATA(0x82, 0xeb, 0x82); | ||||||
| 	if (dev_priv->vbios.tvdactestval) | 	if (drm->vbios.tvdactestval) | ||||||
| 		testval = dev_priv->vbios.tvdactestval; | 		testval = drm->vbios.tvdactestval; | ||||||
| 
 | 
 | ||||||
| 	dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); | 	dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset); | ||||||
| 	head = (dacclk & 0x100) >> 8; | 	head = (dacclk & 0x100) >> 8; | ||||||
| 
 | 
 | ||||||
| 	/* Save the previous state. */ | 	/* Save the previous state. */ | ||||||
| 	gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); | 	gpio1 = gpio->get(gpio, 0, DCB_GPIO_TVDAC1, 0xff); | ||||||
| 	gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); | 	gpio0 = gpio->get(gpio, 0, DCB_GPIO_TVDAC0, 0xff); | ||||||
| 	fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); | 	fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); | ||||||
| 	fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); | 	fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); | ||||||
| 	fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); | 	fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); | ||||||
|  | @ -66,8 +79,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | ||||||
| 	ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); | 	ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); | ||||||
| 
 | 
 | ||||||
| 	/* Prepare the DAC for load detection.  */ | 	/* Prepare the DAC for load detection.  */ | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, true); | 	gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, true); | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, true); | 	gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, true); | ||||||
| 
 | 
 | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); | ||||||
|  | @ -112,8 +125,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); | ||||||
| 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); | 	NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, gpio1); | 	gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, gpio1); | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, gpio0); | 	gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, gpio0); | ||||||
| 
 | 
 | ||||||
| 	return sample; | 	return sample; | ||||||
| } | } | ||||||
|  | @ -121,15 +134,18 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) | ||||||
| static bool | static bool | ||||||
| get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) | get_tv_detect_quirks(struct drm_device *dev, uint32_t *pin_mask) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_object *device = drm->device; | ||||||
|  | 
 | ||||||
| 	/* Zotac FX5200 */ | 	/* Zotac FX5200 */ | ||||||
| 	if (nv_match_device(dev, 0x0322, 0x19da, 0x1035) || | 	if (nv_device_match(device, 0x0322, 0x19da, 0x1035) || | ||||||
| 	    nv_match_device(dev, 0x0322, 0x19da, 0x2035)) { | 	    nv_device_match(device, 0x0322, 0x19da, 0x2035)) { | ||||||
| 		*pin_mask = 0xc; | 		*pin_mask = 0xc; | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* MSI nForce2 IGP */ | 	/* MSI nForce2 IGP */ | ||||||
| 	if (nv_match_device(dev, 0x01f0, 0x1462, 0x5710)) { | 	if (nv_device_match(device, 0x01f0, 0x1462, 0x5710)) { | ||||||
| 		*pin_mask = 0xc; | 		*pin_mask = 0xc; | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
|  | @ -141,7 +157,7 @@ static enum drm_connector_status | ||||||
| nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_mode_config *conf = &dev->mode_config; | 	struct drm_mode_config *conf = &dev->mode_config; | ||||||
| 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | ||||||
| 	struct dcb_output *dcb = tv_enc->base.dcb; | 	struct dcb_output *dcb = tv_enc->base.dcb; | ||||||
|  | @ -151,8 +167,8 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| 		return connector_status_disconnected; | 		return connector_status_disconnected; | ||||||
| 
 | 
 | ||||||
| 	if (reliable) { | 	if (reliable) { | ||||||
| 		if (dev_priv->chipset == 0x42 || | 		if (nv_device(drm->device)->chipset == 0x42 || | ||||||
| 		    dev_priv->chipset == 0x43) | 		    nv_device(drm->device)->chipset == 0x43) | ||||||
| 			tv_enc->pin_mask = | 			tv_enc->pin_mask = | ||||||
| 				nv42_tv_sample_load(encoder) >> 28 & 0xe; | 				nv42_tv_sample_load(encoder) >> 28 & 0xe; | ||||||
| 		else | 		else | ||||||
|  | @ -186,7 +202,7 @@ nv17_tv_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| 	if (!reliable) { | 	if (!reliable) { | ||||||
| 		return connector_status_unknown; | 		return connector_status_unknown; | ||||||
| 	} else if (tv_enc->subconnector) { | 	} else if (tv_enc->subconnector) { | ||||||
| 		NV_INFO(dev, "Load detected on output %c\n", | 		NV_INFO(drm, "Load detected on output %c\n", | ||||||
| 			'@' + ffs(dcb->or)); | 			'@' + ffs(dcb->or)); | ||||||
| 		return connector_status_connected; | 		return connector_status_connected; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -358,6 +374,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, | ||||||
| static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode) | static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||||||
| 	struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; | 	struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; | ||||||
| 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | ||||||
| 
 | 
 | ||||||
|  | @ -365,7 +383,7 @@ static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 		return; | 		return; | ||||||
| 	nouveau_encoder(encoder)->last_dpms = mode; | 	nouveau_encoder(encoder)->last_dpms = mode; | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", | 	NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", | ||||||
| 		 mode, nouveau_encoder(encoder)->dcb->index); | 		 mode, nouveau_encoder(encoder)->dcb->index); | ||||||
| 
 | 
 | ||||||
| 	regs->ptv_200 &= ~1; | 	regs->ptv_200 &= ~1; | ||||||
|  | @ -382,8 +400,8 @@ static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 
 | 
 | ||||||
| 	nv_load_ptv(dev, regs, 200); | 	nv_load_ptv(dev, regs, 200); | ||||||
| 
 | 
 | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); | 	gpio->set(gpio, 0, DCB_GPIO_TVDAC1, 0xff, mode == DRM_MODE_DPMS_ON); | ||||||
| 	nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); | 	gpio->set(gpio, 0, DCB_GPIO_TVDAC0, 0xff, mode == DRM_MODE_DPMS_ON); | ||||||
| 
 | 
 | ||||||
| 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); | 	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); | ||||||
| } | } | ||||||
|  | @ -391,7 +409,7 @@ static void  nv17_tv_dpms(struct drm_encoder *encoder, int mode) | ||||||
| static void nv17_tv_prepare(struct drm_encoder *encoder) | static void nv17_tv_prepare(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | ||||||
| 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); | ||||||
| 	int head = nouveau_crtc(encoder->crtc)->index; | 	int head = nouveau_crtc(encoder->crtc)->index; | ||||||
|  | @ -418,7 +436,7 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) | ||||||
| 			     !enc->crtc && | 			     !enc->crtc && | ||||||
| 			     nv04_dfp_get_bound_head(dev, dcb) == head) { | 			     nv04_dfp_get_bound_head(dev, dcb) == head) { | ||||||
| 				nv04_dfp_bind_head(dev, dcb, head ^ 1, | 				nv04_dfp_bind_head(dev, dcb, head ^ 1, | ||||||
| 						dev_priv->vbios.fp.dual_link); | 						drm->vbios.fp.dual_link); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -430,7 +448,7 @@ static void nv17_tv_prepare(struct drm_encoder *encoder) | ||||||
| 	/* Set the DACCLK register */ | 	/* Set the DACCLK register */ | ||||||
| 	dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; | 	dacclk = (NVReadRAMDAC(dev, 0, dacclk_off) & ~0x30) | 0x1; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type == NV_40) | 	if (nv_device(drm->device)->card_type == NV_40) | ||||||
| 		dacclk |= 0x1a << 16; | 		dacclk |= 0x1a << 16; | ||||||
| 
 | 
 | ||||||
| 	if (tv_norm->kind == CTV_ENC_MODE) { | 	if (tv_norm->kind == CTV_ENC_MODE) { | ||||||
|  | @ -454,7 +472,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, | ||||||
| 			     struct drm_display_mode *adjusted_mode) | 			     struct drm_display_mode *adjusted_mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int head = nouveau_crtc(encoder->crtc)->index; | 	int head = nouveau_crtc(encoder->crtc)->index; | ||||||
| 	struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head]; | 	struct nv04_crtc_reg *regs = &nv04_display(dev)->mode_reg.crtc_reg[head]; | ||||||
| 	struct nv17_tv_state *tv_regs = &to_tv_enc(encoder)->state; | 	struct nv17_tv_state *tv_regs = &to_tv_enc(encoder)->state; | ||||||
|  | @ -487,7 +505,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, | ||||||
| 			tv_regs->ptv_614 = 0x13; | 			tv_regs->ptv_614 = 0x13; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->card_type >= NV_30) { | 		if (nv_device(drm->device)->card_type >= NV_30) { | ||||||
| 			tv_regs->ptv_500 = 0xe8e0; | 			tv_regs->ptv_500 = 0xe8e0; | ||||||
| 			tv_regs->ptv_504 = 0x1710; | 			tv_regs->ptv_504 = 0x1710; | ||||||
| 			tv_regs->ptv_604 = 0x0; | 			tv_regs->ptv_604 = 0x0; | ||||||
|  | @ -567,7 +585,7 @@ static void nv17_tv_mode_set(struct drm_encoder *encoder, | ||||||
| static void nv17_tv_commit(struct drm_encoder *encoder) | static void nv17_tv_commit(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | 	struct drm_encoder_helper_funcs *helper = encoder->helper_private; | ||||||
|  | @ -582,7 +600,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder) | ||||||
| 	nv17_tv_state_load(dev, &to_tv_enc(encoder)->state); | 	nv17_tv_state_load(dev, &to_tv_enc(encoder)->state); | ||||||
| 
 | 
 | ||||||
| 	/* This could use refinement for flatpanels, but it should work */ | 	/* This could use refinement for flatpanels, but it should work */ | ||||||
| 	if (dev_priv->chipset < 0x44) | 	if (nv_device(drm->device)->chipset < 0x44) | ||||||
| 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + | 		NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + | ||||||
| 					nv04_dac_output_offset(encoder), | 					nv04_dac_output_offset(encoder), | ||||||
| 					0xf0000000); | 					0xf0000000); | ||||||
|  | @ -593,7 +611,7 @@ static void nv17_tv_commit(struct drm_encoder *encoder) | ||||||
| 
 | 
 | ||||||
| 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | 	helper->dpms(encoder, DRM_MODE_DPMS_ON); | ||||||
| 
 | 
 | ||||||
| 	NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", | ||||||
| 		drm_get_connector_name( | 		drm_get_connector_name( | ||||||
| 			&nouveau_encoder_connector_get(nv_encoder)->base), | 			&nouveau_encoder_connector_get(nv_encoder)->base), | ||||||
| 		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | 		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); | ||||||
|  | @ -631,6 +649,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, | ||||||
| 				    struct drm_connector *connector) | 				    struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_mode_config *conf = &dev->mode_config; | 	struct drm_mode_config *conf = &dev->mode_config; | ||||||
| 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | ||||||
| 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | 	struct dcb_output *dcb = nouveau_encoder(encoder)->dcb; | ||||||
|  | @ -647,7 +666,7 @@ static int nv17_tv_create_resources(struct drm_encoder *encoder, | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (i == num_tv_norms) | 		if (i == num_tv_norms) | ||||||
| 			NV_WARN(dev, "Invalid TV norm setting \"%s\"\n", | 			NV_WARN(drm, "Invalid TV norm setting \"%s\"\n", | ||||||
| 				nouveau_tv_norm); | 				nouveau_tv_norm); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -760,8 +779,6 @@ static void nv17_tv_destroy(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | 	struct nv17_tv_encoder *tv_enc = to_tv_enc(encoder); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "\n"); |  | ||||||
| 
 |  | ||||||
| 	drm_encoder_cleanup(encoder); | 	drm_encoder_cleanup(encoder); | ||||||
| 	kfree(tv_enc); | 	kfree(tv_enc); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -130,12 +130,14 @@ void nv17_ctv_update_rescaler(struct drm_encoder *encoder); | ||||||
| static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, | static inline void nv_write_ptv(struct drm_device *dev, uint32_t reg, | ||||||
| 				uint32_t val) | 				uint32_t val) | ||||||
| { | { | ||||||
| 	nv_wr32(dev, reg, val); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	nv_wr32(device, reg, val); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg) | static inline uint32_t nv_read_ptv(struct drm_device *dev, uint32_t reg) | ||||||
| { | { | ||||||
| 	return nv_rd32(dev, reg); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	return nv_rd32(device, reg); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, | static inline void nv_write_tv_enc(struct drm_device *dev, uint8_t reg, | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
|  |  | ||||||
|  | @ -23,17 +23,24 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include <nouveau_bios.h> | #include "nouveau_bios.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | 
 | ||||||
|  | #include <engine/fifo.h> | ||||||
|  | 
 | ||||||
| #define min2(a,b) ((a) < (b) ? (a) : (b)) | #define min2(a,b) ((a) < (b) ? (a) : (b)) | ||||||
| 
 | 
 | ||||||
| static u32 | static u32 | ||||||
| read_pll_1(struct drm_device *dev, u32 reg) | read_pll_1(struct drm_device *dev, u32 reg) | ||||||
| { | { | ||||||
| 	u32 ctrl = nv_rd32(dev, reg + 0x00); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	u32 ctrl = nv_rd32(device, reg + 0x00); | ||||||
| 	int P = (ctrl & 0x00070000) >> 16; | 	int P = (ctrl & 0x00070000) >> 16; | ||||||
| 	int N = (ctrl & 0x0000ff00) >> 8; | 	int N = (ctrl & 0x0000ff00) >> 8; | ||||||
| 	int M = (ctrl & 0x000000ff) >> 0; | 	int M = (ctrl & 0x000000ff) >> 0; | ||||||
|  | @ -48,8 +55,9 @@ read_pll_1(struct drm_device *dev, u32 reg) | ||||||
| static u32 | static u32 | ||||||
| read_pll_2(struct drm_device *dev, u32 reg) | read_pll_2(struct drm_device *dev, u32 reg) | ||||||
| { | { | ||||||
| 	u32 ctrl = nv_rd32(dev, reg + 0x00); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 coef = nv_rd32(dev, reg + 0x04); | 	u32 ctrl = nv_rd32(device, reg + 0x00); | ||||||
|  | 	u32 coef = nv_rd32(device, reg + 0x04); | ||||||
| 	int N2 = (coef & 0xff000000) >> 24; | 	int N2 = (coef & 0xff000000) >> 24; | ||||||
| 	int M2 = (coef & 0x00ff0000) >> 16; | 	int M2 = (coef & 0x00ff0000) >> 16; | ||||||
| 	int N1 = (coef & 0x0000ff00) >> 8; | 	int N1 = (coef & 0x0000ff00) >> 8; | ||||||
|  | @ -88,7 +96,8 @@ read_clk(struct drm_device *dev, u32 src) | ||||||
| int | int | ||||||
| nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nv40_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	u32 ctrl = nv_rd32(dev, 0x00c040); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	u32 ctrl = nv_rd32(device, 0x00c040); | ||||||
| 
 | 
 | ||||||
| 	perflvl->core   = read_clk(dev, (ctrl & 0x00000003) >> 0); | 	perflvl->core   = read_clk(dev, (ctrl & 0x00000003) >> 0); | ||||||
| 	perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); | 	perflvl->shader = read_clk(dev, (ctrl & 0x00000030) >> 4); | ||||||
|  | @ -109,17 +118,20 @@ static int | ||||||
| nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | nv40_calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | ||||||
| 	      u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) | 	      u32 clk, int *N1, int *M1, int *N2, int *M2, int *log2P) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
|  | 	struct nouveau_clock *pclk = nouveau_clock(device); | ||||||
| 	struct nouveau_pll_vals coef; | 	struct nouveau_pll_vals coef; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	ret = get_pll_limits(dev, reg, pll); | 	ret = nvbios_pll_parse(bios, reg, pll); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	if (clk < pll->vco1.max_freq) | 	if (clk < pll->vco1.max_freq) | ||||||
| 		pll->vco2.max_freq = 0; | 		pll->vco2.max_freq = 0; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); | 	pclk->pll_calc(pclk, pll, clk, &coef); | ||||||
| 	if (ret == 0) | 	if (ret == 0) | ||||||
| 		return -ERANGE; | 		return -ERANGE; | ||||||
| 
 | 
 | ||||||
|  | @ -211,12 +223,13 @@ static bool | ||||||
| nv40_pm_gr_idle(void *data) | nv40_pm_gr_idle(void *data) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = data; | 	struct drm_device *dev = data; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	if ((nv_rd32(dev, 0x400760) & 0x000000f0) >> 4 != | 	if ((nv_rd32(device, 0x400760) & 0x000000f0) >> 4 != | ||||||
| 	    (nv_rd32(dev, 0x400760) & 0x0000000f)) | 	    (nv_rd32(device, 0x400760) & 0x0000000f)) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	if (nv_rd32(dev, 0x400700)) | 	if (nv_rd32(device, 0x400700)) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	return true; | 	return true; | ||||||
|  | @ -225,7 +238,9 @@ nv40_pm_gr_idle(void *data) | ||||||
| int | int | ||||||
| nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) | nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_fifo *pfifo = nouveau_fifo(device); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv40_pm_state *info = pre_state; | 	struct nv40_pm_state *info = pre_state; | ||||||
| 	unsigned long flags; | 	unsigned long flags; | ||||||
| 	struct bit_entry M; | 	struct bit_entry M; | ||||||
|  | @ -235,12 +250,12 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| 
 | 
 | ||||||
| 	/* determine which CRTCs are active, fetch VGA_SR1 for each */ | 	/* determine which CRTCs are active, fetch VGA_SR1 for each */ | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
| 		u32 vbl = nv_rd32(dev, 0x600808 + (i * 0x2000)); | 		u32 vbl = nv_rd32(device, 0x600808 + (i * 0x2000)); | ||||||
| 		u32 cnt = 0; | 		u32 cnt = 0; | ||||||
| 		do { | 		do { | ||||||
| 			if (vbl != nv_rd32(dev, 0x600808 + (i * 0x2000))) { | 			if (vbl != nv_rd32(device, 0x600808 + (i * 0x2000))) { | ||||||
| 				nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); | 				nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); | ||||||
| 				sr1[i] = nv_rd08(dev, 0x0c03c5 + (i * 0x2000)); | 				sr1[i] = nv_rd08(device, 0x0c03c5 + (i * 0x2000)); | ||||||
| 				if (!(sr1[i] & 0x20)) | 				if (!(sr1[i] & 0x20)) | ||||||
| 					crtc_mask |= (1 << i); | 					crtc_mask |= (1 << i); | ||||||
| 				break; | 				break; | ||||||
|  | @ -250,28 +265,20 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* halt and idle engines */ | 	/* halt and idle engines */ | ||||||
| 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 	pfifo->pause(pfifo, &flags); | ||||||
| 	nv_mask(dev, 0x002500, 0x00000001, 0x00000000); |  | ||||||
| 	if (!nv_wait(dev, 0x002500, 0x00000010, 0x00000000)) |  | ||||||
| 		goto resume; |  | ||||||
| 	nv_mask(dev, 0x003220, 0x00000001, 0x00000000); |  | ||||||
| 	if (!nv_wait(dev, 0x003220, 0x00000010, 0x00000000)) |  | ||||||
| 		goto resume; |  | ||||||
| 	nv_mask(dev, 0x003200, 0x00000001, 0x00000000); |  | ||||||
| 	//XXX: nv04_fifo_cache_pull(dev, false);
 |  | ||||||
| 
 | 
 | ||||||
| 	if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) | 	if (!nv_wait_cb(device, nv40_pm_gr_idle, dev)) | ||||||
| 		goto resume; | 		goto resume; | ||||||
| 
 | 
 | ||||||
| 	ret = 0; | 	ret = 0; | ||||||
| 
 | 
 | ||||||
| 	/* set engine clocks */ | 	/* set engine clocks */ | ||||||
| 	nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); | 	nv_mask(device, 0x00c040, 0x00000333, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x004004, info->npll_coef); | 	nv_wr32(device, 0x004004, info->npll_coef); | ||||||
| 	nv_mask(dev, 0x004000, 0xc0070100, info->npll_ctrl); | 	nv_mask(device, 0x004000, 0xc0070100, info->npll_ctrl); | ||||||
| 	nv_mask(dev, 0x004008, 0xc007ffff, info->spll); | 	nv_mask(device, 0x004008, 0xc007ffff, info->spll); | ||||||
| 	mdelay(5); | 	mdelay(5); | ||||||
| 	nv_mask(dev, 0x00c040, 0x00000333, info->ctrl); | 	nv_mask(device, 0x00c040, 0x00000333, info->ctrl); | ||||||
| 
 | 
 | ||||||
| 	if (!info->mpll_ctrl) | 	if (!info->mpll_ctrl) | ||||||
| 		goto resume; | 		goto resume; | ||||||
|  | @ -280,52 +287,52 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
| 		if (!(crtc_mask & (1 << i))) | 		if (!(crtc_mask & (1 << i))) | ||||||
| 			continue; | 			continue; | ||||||
| 		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); | 		nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00000000); | ||||||
| 		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); | 		nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); | ||||||
| 		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); | 		nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); | ||||||
| 		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); | 		nv_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i] | 0x20); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* prepare ram for reclocking */ | 	/* prepare ram for reclocking */ | ||||||
| 	nv_wr32(dev, 0x1002d4, 0x00000001); /* precharge */ | 	nv_wr32(device, 0x1002d4, 0x00000001); /* precharge */ | ||||||
| 	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ | 	nv_wr32(device, 0x1002d0, 0x00000001); /* refresh */ | ||||||
| 	nv_wr32(dev, 0x1002d0, 0x00000001); /* refresh */ | 	nv_wr32(device, 0x1002d0, 0x00000001); /* refresh */ | ||||||
| 	nv_mask(dev, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ | 	nv_mask(device, 0x100210, 0x80000000, 0x00000000); /* no auto refresh */ | ||||||
| 	nv_wr32(dev, 0x1002dc, 0x00000001); /* enable self-refresh */ | 	nv_wr32(device, 0x1002dc, 0x00000001); /* enable self-refresh */ | ||||||
| 
 | 
 | ||||||
| 	/* change the PLL of each memory partition */ | 	/* change the PLL of each memory partition */ | ||||||
| 	nv_mask(dev, 0x00c040, 0x0000c000, 0x00000000); | 	nv_mask(device, 0x00c040, 0x0000c000, 0x00000000); | ||||||
| 	switch (dev_priv->chipset) { | 	switch (nv_device(drm->device)->chipset) { | ||||||
| 	case 0x40: | 	case 0x40: | ||||||
| 	case 0x45: | 	case 0x45: | ||||||
| 	case 0x41: | 	case 0x41: | ||||||
| 	case 0x42: | 	case 0x42: | ||||||
| 	case 0x47: | 	case 0x47: | ||||||
| 		nv_mask(dev, 0x004044, 0xc0771100, info->mpll_ctrl); | 		nv_mask(device, 0x004044, 0xc0771100, info->mpll_ctrl); | ||||||
| 		nv_mask(dev, 0x00402c, 0xc0771100, info->mpll_ctrl); | 		nv_mask(device, 0x00402c, 0xc0771100, info->mpll_ctrl); | ||||||
| 		nv_wr32(dev, 0x004048, info->mpll_coef); | 		nv_wr32(device, 0x004048, info->mpll_coef); | ||||||
| 		nv_wr32(dev, 0x004030, info->mpll_coef); | 		nv_wr32(device, 0x004030, info->mpll_coef); | ||||||
| 	case 0x43: | 	case 0x43: | ||||||
| 	case 0x49: | 	case 0x49: | ||||||
| 	case 0x4b: | 	case 0x4b: | ||||||
| 		nv_mask(dev, 0x004038, 0xc0771100, info->mpll_ctrl); | 		nv_mask(device, 0x004038, 0xc0771100, info->mpll_ctrl); | ||||||
| 		nv_wr32(dev, 0x00403c, info->mpll_coef); | 		nv_wr32(device, 0x00403c, info->mpll_coef); | ||||||
| 	default: | 	default: | ||||||
| 		nv_mask(dev, 0x004020, 0xc0771100, info->mpll_ctrl); | 		nv_mask(device, 0x004020, 0xc0771100, info->mpll_ctrl); | ||||||
| 		nv_wr32(dev, 0x004024, info->mpll_coef); | 		nv_wr32(device, 0x004024, info->mpll_coef); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	udelay(100); | 	udelay(100); | ||||||
| 	nv_mask(dev, 0x00c040, 0x0000c000, 0x0000c000); | 	nv_mask(device, 0x00c040, 0x0000c000, 0x0000c000); | ||||||
| 
 | 
 | ||||||
| 	/* re-enable normal operation of memory controller */ | 	/* re-enable normal operation of memory controller */ | ||||||
| 	nv_wr32(dev, 0x1002dc, 0x00000000); | 	nv_wr32(device, 0x1002dc, 0x00000000); | ||||||
| 	nv_mask(dev, 0x100210, 0x80000000, 0x80000000); | 	nv_mask(device, 0x100210, 0x80000000, 0x80000000); | ||||||
| 	udelay(100); | 	udelay(100); | ||||||
| 
 | 
 | ||||||
| 	/* execute memory reset script from vbios */ | 	/* execute memory reset script from vbios */ | ||||||
| 	if (!bit_table(dev, 'M', &M)) | 	if (!bit_table(dev, 'M', &M)) | ||||||
| 		nouveau_bios_init_exec(dev, ROM16(M.data[0])); | 		nouveau_bios_run_init_table(dev, ROM16(M.data[0]), NULL, 0); | ||||||
| 
 | 
 | ||||||
| 	/* make sure we're in vblank (hopefully the same one as before), and
 | 	/* make sure we're in vblank (hopefully the same one as before), and
 | ||||||
| 	 * then re-enable crtc memory access | 	 * then re-enable crtc memory access | ||||||
|  | @ -333,19 +340,14 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
| 		if (!(crtc_mask & (1 << i))) | 		if (!(crtc_mask & (1 << i))) | ||||||
| 			continue; | 			continue; | ||||||
| 		nv_wait(dev, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); | 		nv_wait(device, 0x600808 + (i * 0x2000), 0x00010000, 0x00010000); | ||||||
| 		nv_wr08(dev, 0x0c03c4 + (i * 0x2000), 0x01); | 		nv_wr08(device, 0x0c03c4 + (i * 0x2000), 0x01); | ||||||
| 		nv_wr08(dev, 0x0c03c5 + (i * 0x2000), sr1[i]); | 		nv_wr08(device, 0x0c03c5 + (i * 0x2000), sr1[i]); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* resume engines */ | 	/* resume engines */ | ||||||
| resume: | resume: | ||||||
| 	nv_wr32(dev, 0x003250, 0x00000001); | 	pfifo->start(pfifo, &flags); | ||||||
| 	nv_mask(dev, 0x003220, 0x00000001, 0x00000001); |  | ||||||
| 	nv_wr32(dev, 0x003200, 0x00000001); |  | ||||||
| 	nv_wr32(dev, 0x002500, 0x00000001); |  | ||||||
| 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |  | ||||||
| 
 |  | ||||||
| 	kfree(info); | 	kfree(info); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | @ -353,8 +355,11 @@ resume: | ||||||
| int | int | ||||||
| nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 
 | ||||||
| 	if (line == 2) { | 	if (line == 2) { | ||||||
| 		u32 reg = nv_rd32(dev, 0x0010f0); | 		u32 reg = nv_rd32(device, 0x0010f0); | ||||||
| 		if (reg & 0x80000000) { | 		if (reg & 0x80000000) { | ||||||
| 			*duty = (reg & 0x7fff0000) >> 16; | 			*duty = (reg & 0x7fff0000) >> 16; | ||||||
| 			*divs = (reg & 0x00007fff); | 			*divs = (reg & 0x00007fff); | ||||||
|  | @ -362,14 +367,14 @@ nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||||||
| 		} | 		} | ||||||
| 	} else | 	} else | ||||||
| 	if (line == 9) { | 	if (line == 9) { | ||||||
| 		u32 reg = nv_rd32(dev, 0x0015f4); | 		u32 reg = nv_rd32(device, 0x0015f4); | ||||||
| 		if (reg & 0x80000000) { | 		if (reg & 0x80000000) { | ||||||
| 			*divs = nv_rd32(dev, 0x0015f8); | 			*divs = nv_rd32(device, 0x0015f8); | ||||||
| 			*duty = (reg & 0x7fffffff); | 			*duty = (reg & 0x7fffffff); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); | 		NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", line); | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -379,14 +384,17 @@ nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||||||
| int | int | ||||||
| nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) | nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (line == 2) { | 	if (line == 2) { | ||||||
| 		nv_wr32(dev, 0x0010f0, 0x80000000 | (duty << 16) | divs); | 		nv_wr32(device, 0x0010f0, 0x80000000 | (duty << 16) | divs); | ||||||
| 	} else | 	} else | ||||||
| 	if (line == 9) { | 	if (line == 9) { | ||||||
| 		nv_wr32(dev, 0x0015f8, divs); | 		nv_wr32(device, 0x0015f8, divs); | ||||||
| 		nv_wr32(dev, 0x0015f4, duty | 0x80000000); | 		nv_wr32(device, 0x0015f4, duty | 0x80000000); | ||||||
| 	} else { | 	} else { | ||||||
| 		NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); | 		NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", line); | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -28,24 +28,27 @@ | ||||||
| #include "drm_mode.h" | #include "drm_mode.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) |  | ||||||
| #include "nouveau_reg.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_dma.h" | ||||||
|  | #include "nouveau_gem.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| nv50_crtc_lut_load(struct drm_crtc *crtc) | nv50_crtc_lut_load(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); | 	void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(crtc->dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 256; i++) { | 	for (i = 0; i < 256; i++) { | ||||||
| 		writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0); | 		writew(nv_crtc->lut.r[i] >> 2, lut + 8*i + 0); | ||||||
|  | @ -64,25 +67,25 @@ int | ||||||
| nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	int index = nv_crtc->index, ret; | 	int index = nv_crtc->index, ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 	NV_DEBUG(drm, "index %d\n", nv_crtc->index); | ||||||
| 	NV_DEBUG_KMS(dev, "%s\n", blanked ? "blanked" : "unblanked"); | 	NV_DEBUG(drm, "%s\n", blanked ? "blanked" : "unblanked"); | ||||||
| 
 | 
 | ||||||
| 	if (blanked) { | 	if (blanked) { | ||||||
| 		nv_crtc->cursor.hide(nv_crtc, false); | 		nv_crtc->cursor.hide(nv_crtc, false); | ||||||
| 
 | 
 | ||||||
| 		ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 7 : 5); | 		ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 7 : 5); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			NV_ERROR(dev, "no space while blanking crtc\n"); | 			NV_ERROR(drm, "no space while blanking crtc\n"); | ||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 		BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); | 		BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); | ||||||
| 		OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK); | 		OUT_RING(evo, NV50_EVO_CRTC_CLUT_MODE_BLANK); | ||||||
| 		OUT_RING(evo, 0); | 		OUT_RING(evo, 0); | ||||||
| 		if (dev_priv->chipset != 0x50) { | 		if (nv_device(drm->device)->chipset != 0x50) { | ||||||
| 			BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); | 			BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); | ||||||
| 			OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE); | 			OUT_RING(evo, NV84_EVO_CRTC_CLUT_DMA_HANDLE_NONE); | ||||||
| 		} | 		} | ||||||
|  | @ -95,9 +98,9 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | ||||||
| 		else | 		else | ||||||
| 			nv_crtc->cursor.hide(nv_crtc, false); | 			nv_crtc->cursor.hide(nv_crtc, false); | ||||||
| 
 | 
 | ||||||
| 		ret = RING_SPACE(evo, dev_priv->chipset != 0x50 ? 10 : 8); | 		ret = RING_SPACE(evo, nv_device(drm->device)->chipset != 0x50 ? 10 : 8); | ||||||
| 		if (ret) { | 		if (ret) { | ||||||
| 			NV_ERROR(dev, "no space while unblanking crtc\n"); | 			NV_ERROR(drm, "no space while unblanking crtc\n"); | ||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 		BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); | 		BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, CLUT_MODE), 2); | ||||||
|  | @ -105,7 +108,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | ||||||
| 				NV50_EVO_CRTC_CLUT_MODE_OFF : | 				NV50_EVO_CRTC_CLUT_MODE_OFF : | ||||||
| 				NV50_EVO_CRTC_CLUT_MODE_ON); | 				NV50_EVO_CRTC_CLUT_MODE_ON); | ||||||
| 		OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8); | 		OUT_RING(evo, nv_crtc->lut.nvbo->bo.offset >> 8); | ||||||
| 		if (dev_priv->chipset != 0x50) { | 		if (nv_device(drm->device)->chipset != 0x50) { | ||||||
| 			BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); | 			BEGIN_NV04(evo, 0, NV84_EVO_CRTC(index, CLUT_DMA), 1); | ||||||
| 			OUT_RING(evo, NvEvoVRAM); | 			OUT_RING(evo, NvEvoVRAM); | ||||||
| 		} | 		} | ||||||
|  | @ -114,7 +117,7 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) | ||||||
| 		OUT_RING(evo, nv_crtc->fb.offset >> 8); | 		OUT_RING(evo, nv_crtc->fb.offset >> 8); | ||||||
| 		OUT_RING(evo, 0); | 		OUT_RING(evo, 0); | ||||||
| 		BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); | 		BEGIN_NV04(evo, 0, NV50_EVO_CRTC(index, FB_DMA), 1); | ||||||
| 		if (dev_priv->chipset != 0x50) | 		if (nv_device(drm->device)->chipset != 0x50) | ||||||
| 			if (nv_crtc->fb.tile_flags == 0x7a00 || | 			if (nv_crtc->fb.tile_flags == 0x7a00 || | ||||||
| 			    nv_crtc->fb.tile_flags == 0xfe00) | 			    nv_crtc->fb.tile_flags == 0xfe00) | ||||||
| 				OUT_RING(evo, NvEvoFB32); | 				OUT_RING(evo, NvEvoFB32); | ||||||
|  | @ -174,17 +177,18 @@ static int | ||||||
| nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update) | nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	int ret; | 	int ret; | ||||||
| 	int adj; | 	int adj; | ||||||
| 	u32 hue, vib; | 	u32 hue, vib; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "vibrance = %i, hue = %i\n", | 	NV_DEBUG(drm, "vibrance = %i, hue = %i\n", | ||||||
| 		     nv_crtc->color_vibrance, nv_crtc->vibrant_hue); | 		     nv_crtc->color_vibrance, nv_crtc->vibrant_hue); | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); | 	ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while setting color vibrance\n"); | 		NV_ERROR(drm, "no space while setting color vibrance\n"); | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -229,17 +233,18 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct drm_crtc *crtc = &nv_crtc->base; | 	struct drm_crtc *crtc = &nv_crtc->base; | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	struct drm_display_mode *umode = &crtc->mode; | 	struct drm_display_mode *umode = &crtc->mode; | ||||||
| 	struct drm_display_mode *omode; | 	struct drm_display_mode *omode; | ||||||
| 	int scaling_mode, ret; | 	int scaling_mode, ret; | ||||||
| 	u32 ctrl = 0, oX, oY; | 	u32 ctrl = 0, oX, oY; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	nv_connector = nouveau_crtc_connector_get(nv_crtc); | 	nv_connector = nouveau_crtc_connector_get(nv_crtc); | ||||||
| 	if (!nv_connector || !nv_connector->native_mode) { | 	if (!nv_connector || !nv_connector->native_mode) { | ||||||
| 		NV_ERROR(dev, "no native mode, forcing panel scaling\n"); | 		NV_ERROR(drm, "no native mode, forcing panel scaling\n"); | ||||||
| 		scaling_mode = DRM_MODE_SCALE_NONE; | 		scaling_mode = DRM_MODE_SCALE_NONE; | ||||||
| 	} else { | 	} else { | ||||||
| 		scaling_mode = nv_connector->scaling_mode; | 		scaling_mode = nv_connector->scaling_mode; | ||||||
|  | @ -329,15 +334,19 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| int | int | ||||||
| nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | ||||||
| { | { | ||||||
| 	return setPLL(dev, PLL_VPLL0 + head, pclk); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_clock *clk = nouveau_clock(device); | ||||||
|  | 
 | ||||||
|  | 	return clk->pll_set(clk, PLL_VPLL0 + head, pclk); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_crtc_destroy(struct drm_crtc *crtc) | nv50_crtc_destroy(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(crtc->dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	nouveau_bo_unmap(nv_crtc->lut.nvbo); | 	nouveau_bo_unmap(nv_crtc->lut.nvbo); | ||||||
| 	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); | 	nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); | ||||||
|  | @ -426,13 +435,15 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, | ||||||
| static void | static void | ||||||
| nv50_crtc_save(struct drm_crtc *crtc) | nv50_crtc_save(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	NV_ERROR(crtc->dev, "!!\n"); | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
|  | 	NV_ERROR(drm, "!!\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_crtc_restore(struct drm_crtc *crtc) | nv50_crtc_restore(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	NV_ERROR(crtc->dev, "!!\n"); | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
|  | 	NV_ERROR(drm, "!!\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static const struct drm_crtc_funcs nv50_crtc_funcs = { | static const struct drm_crtc_funcs nv50_crtc_funcs = { | ||||||
|  | @ -456,8 +467,9 @@ nv50_crtc_prepare(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 	NV_DEBUG(drm, "index %d\n", nv_crtc->index); | ||||||
| 
 | 
 | ||||||
| 	nv50_display_flip_stop(crtc); | 	nv50_display_flip_stop(crtc); | ||||||
| 	drm_vblank_pre_modeset(dev, nv_crtc->index); | 	drm_vblank_pre_modeset(dev, nv_crtc->index); | ||||||
|  | @ -468,9 +480,10 @@ static void | ||||||
| nv50_crtc_commit(struct drm_crtc *crtc) | nv50_crtc_commit(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = crtc->dev; | 	struct drm_device *dev = crtc->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 	NV_DEBUG(drm, "index %d\n", nv_crtc->index); | ||||||
| 
 | 
 | ||||||
| 	nv50_crtc_blank(nv_crtc, false); | 	nv50_crtc_blank(nv_crtc, false); | ||||||
| 	drm_vblank_post_modeset(dev, nv_crtc->index); | 	drm_vblank_post_modeset(dev, nv_crtc->index); | ||||||
|  | @ -492,17 +505,17 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | ||||||
| { | { | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	struct drm_framebuffer *drm_fb; | 	struct drm_framebuffer *drm_fb; | ||||||
| 	struct nouveau_framebuffer *fb; | 	struct nouveau_framebuffer *fb; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 	NV_DEBUG(drm, "index %d\n", nv_crtc->index); | ||||||
| 
 | 
 | ||||||
| 	/* no fb bound */ | 	/* no fb bound */ | ||||||
| 	if (!atomic && !crtc->fb) { | 	if (!atomic && !crtc->fb) { | ||||||
| 		NV_DEBUG_KMS(dev, "No FB bound\n"); | 		NV_DEBUG(drm, "No FB bound\n"); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -532,7 +545,7 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, | ||||||
| 	nv_crtc->fb.offset = fb->nvbo->bo.offset; | 	nv_crtc->fb.offset = fb->nvbo->bo.offset; | ||||||
| 	nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); | 	nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo); | ||||||
| 	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; | 	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8; | ||||||
| 	if (!nv_crtc->fb.blanked && dev_priv->chipset != 0x50) { | 	if (!nv_crtc->fb.blanked && nv_device(drm->device)->chipset != 0x50) { | ||||||
| 		ret = RING_SPACE(evo, 2); | 		ret = RING_SPACE(evo, 2); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			return ret; | 			return ret; | ||||||
|  | @ -690,10 +703,11 @@ static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { | ||||||
| int | int | ||||||
| nv50_crtc_create(struct drm_device *dev, int index) | nv50_crtc_create(struct drm_device *dev, int index) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = NULL; | 	struct nouveau_crtc *nv_crtc = NULL; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); | 	nv_crtc = kzalloc(sizeof(*nv_crtc), GFP_KERNEL); | ||||||
| 	if (!nv_crtc) | 	if (!nv_crtc) | ||||||
|  |  | ||||||
|  | @ -27,9 +27,8 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_mode.h" | #include "drm_mode.h" | ||||||
| 
 | 
 | ||||||
| #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | #include "nouveau_drm.h" | ||||||
| #include "nouveau_reg.h" | #include "nouveau_dma.h" | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
|  | @ -37,22 +36,22 @@ static void | ||||||
| nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) | nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (update && nv_crtc->cursor.visible) | 	if (update && nv_crtc->cursor.visible) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2); | 	ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while unhiding cursor\n"); | 		NV_ERROR(drm, "no space while unhiding cursor\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset != 0x50) { | 	if (nv_device(drm->device)->chipset != 0x50) { | ||||||
| 		BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); | 		BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); | ||||||
| 		OUT_RING(evo, NvEvoVRAM); | 		OUT_RING(evo, NvEvoVRAM); | ||||||
| 	} | 	} | ||||||
|  | @ -72,24 +71,24 @@ static void | ||||||
| nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) | nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	if (update && !nv_crtc->cursor.visible) | 	if (update && !nv_crtc->cursor.visible) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, (dev_priv->chipset != 0x50 ? 5 : 3) + update * 2); | 	ret = RING_SPACE(evo, (nv_device(drm->device)->chipset != 0x50 ? 5 : 3) + update * 2); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while hiding cursor\n"); | 		NV_ERROR(drm, "no space while hiding cursor\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); | 	BEGIN_NV04(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CURSOR_CTRL), 2); | ||||||
| 	OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE); | 	OUT_RING(evo, NV50_EVO_CRTC_CURSOR_CTRL_HIDE); | ||||||
| 	OUT_RING(evo, 0); | 	OUT_RING(evo, 0); | ||||||
| 	if (dev_priv->chipset != 0x50) { | 	if (nv_device(drm->device)->chipset != 0x50) { | ||||||
| 		BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); | 		BEGIN_NV04(evo, 0, NV84_EVO_CRTC(nv_crtc->index, CURSOR_DMA), 1); | ||||||
| 		OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE); | 		OUT_RING(evo, NV84_EVO_CRTC_CURSOR_DMA_HANDLE_NONE); | ||||||
| 	} | 	} | ||||||
|  | @ -105,19 +104,18 @@ nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| static void | static void | ||||||
| nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) | nv50_cursor_set_pos(struct nouveau_crtc *nv_crtc, int x, int y) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct nouveau_device *device = nouveau_dev(nv_crtc->base.dev); | ||||||
| 
 | 
 | ||||||
| 	nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y; | 	nv_crtc->cursor_saved_x = x; nv_crtc->cursor_saved_y = y; | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), | 	nv_wr32(device, NV50_PDISPLAY_CURSOR_USER_POS(nv_crtc->index), | ||||||
| 		((y & 0xFFFF) << 16) | (x & 0xFFFF)); | 		((y & 0xFFFF) << 16) | (x & 0xFFFF)); | ||||||
| 	/* Needed to make the cursor move. */ | 	/* Needed to make the cursor move. */ | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0); | 	nv_wr32(device, NV50_PDISPLAY_CURSOR_USER_POS_CTRL(nv_crtc->index), 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) | nv50_cursor_set_offset(struct nouveau_crtc *nv_crtc, uint32_t offset) | ||||||
| { | { | ||||||
| 	NV_DEBUG_KMS(nv_crtc->base.dev, "\n"); |  | ||||||
| 	if (offset == nv_crtc->cursor.offset) | 	if (offset == nv_crtc->cursor.offset) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -29,18 +29,21 @@ | ||||||
| 
 | 
 | ||||||
| #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | ||||||
| #include "nouveau_reg.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| nv50_dac_disconnect(struct drm_encoder *encoder) | nv50_dac_disconnect(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -48,11 +51,11 @@ nv50_dac_disconnect(struct drm_encoder *encoder) | ||||||
| 		return; | 		return; | ||||||
| 	nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); | 	nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "Disconnecting DAC %d\n", nv_encoder->or); | 	NV_DEBUG(drm, "Disconnecting DAC %d\n", nv_encoder->or); | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 4); | 	ret = RING_SPACE(evo, 4); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while disconnecting DAC\n"); | 		NV_ERROR(drm, "no space while disconnecting DAC\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); | 	BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 1); | ||||||
|  | @ -67,43 +70,43 @@ static enum drm_connector_status | ||||||
| nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	enum drm_connector_status status = connector_status_disconnected; | 	enum drm_connector_status status = connector_status_disconnected; | ||||||
| 	uint32_t dpms_state, load_pattern, load_state; | 	uint32_t dpms_state, load_pattern, load_state; | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001); | 	nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(or), 0x00000001); | ||||||
| 	dpms_state = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)); | 	dpms_state = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | 	nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | ||||||
| 		0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | 		0x00150000 | NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | ||||||
| 	if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | 	if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | ||||||
| 		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { | 		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { | ||||||
| 		NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); | 		NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); | ||||||
| 		NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, | 		NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, | ||||||
| 			  nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); | 			  nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); | ||||||
| 		return status; | 		return status; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Use bios provided value if possible. */ | 	/* Use bios provided value if possible. */ | ||||||
| 	if (dev_priv->vbios.dactestval) { | 	if (drm->vbios.dactestval) { | ||||||
| 		load_pattern = dev_priv->vbios.dactestval; | 		load_pattern = drm->vbios.dactestval; | ||||||
| 		NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n", | 		NV_DEBUG(drm, "Using bios provided load_pattern of %d\n", | ||||||
| 			  load_pattern); | 			  load_pattern); | ||||||
| 	} else { | 	} else { | ||||||
| 		load_pattern = 340; | 		load_pattern = 340; | ||||||
| 		NV_DEBUG_KMS(dev, "Using default load_pattern of %d\n", | 		NV_DEBUG(drm, "Using default load_pattern of %d\n", | ||||||
| 			 load_pattern); | 			 load_pattern); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), | 	nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or), | ||||||
| 		NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern); | 		NV50_PDISPLAY_DAC_LOAD_CTRL_ACTIVE | load_pattern); | ||||||
| 	mdelay(45); /* give it some time to process */ | 	mdelay(45); /* give it some time to process */ | ||||||
| 	load_state = nv_rd32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or)); | 	load_state = nv_rd32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or)); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0); | 	nv_wr32(device, NV50_PDISPLAY_DAC_LOAD_CTRL(or), 0); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state | | 	nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), dpms_state | | ||||||
| 		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | 		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | ||||||
| 
 | 
 | ||||||
| 	if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) == | 	if ((load_state & NV50_PDISPLAY_DAC_LOAD_CTRL_PRESENT) == | ||||||
|  | @ -111,9 +114,9 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| 		status = connector_status_connected; | 		status = connector_status_connected; | ||||||
| 
 | 
 | ||||||
| 	if (status == connector_status_connected) | 	if (status == connector_status_connected) | ||||||
| 		NV_DEBUG_KMS(dev, "Load was detected on output with or %d\n", or); | 		NV_DEBUG(drm, "Load was detected on output with or %d\n", or); | ||||||
| 	else | 	else | ||||||
| 		NV_DEBUG_KMS(dev, "Load was not detected on output with or %d\n", or); | 		NV_DEBUG(drm, "Load was not detected on output with or %d\n", or); | ||||||
| 
 | 
 | ||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
|  | @ -121,23 +124,24 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| static void | static void | ||||||
| nv50_dac_dpms(struct drm_encoder *encoder, int mode) | nv50_dac_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	uint32_t val; | 	uint32_t val; | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); | 	NV_DEBUG(drm, "or %d mode %d\n", or, mode); | ||||||
| 
 | 
 | ||||||
| 	/* wait for it to be done */ | 	/* wait for it to be done */ | ||||||
| 	if (!nv_wait(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | 	if (!nv_wait(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), | ||||||
| 		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { | 		     NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING, 0)) { | ||||||
| 		NV_ERROR(dev, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); | 		NV_ERROR(drm, "timeout: DAC_DPMS_CTRL_PENDING(%d) == 0\n", or); | ||||||
| 		NV_ERROR(dev, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, | 		NV_ERROR(drm, "DAC_DPMS_CTRL(%d) = 0x%08x\n", or, | ||||||
| 			 nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); | 			 nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or))); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	val = nv_rd32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F; | 	val = nv_rd32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or)) & ~0x7F; | ||||||
| 
 | 
 | ||||||
| 	if (mode != DRM_MODE_DPMS_ON) | 	if (mode != DRM_MODE_DPMS_ON) | ||||||
| 		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED; | 		val |= NV50_PDISPLAY_DAC_DPMS_CTRL_BLANKED; | ||||||
|  | @ -158,20 +162,22 @@ nv50_dac_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val | | 	nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(or), val | | ||||||
| 		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | 		NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_dac_save(struct drm_encoder *encoder) | nv50_dac_save(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	NV_ERROR(encoder->dev, "!!\n"); | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
|  | 	NV_ERROR(drm, "!!\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_dac_restore(struct drm_encoder *encoder) | nv50_dac_restore(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	NV_ERROR(encoder->dev, "!!\n"); | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
|  | 	NV_ERROR(drm, "!!\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
|  | @ -179,14 +185,15 @@ nv50_dac_mode_fixup(struct drm_encoder *encoder, | ||||||
| 		    const struct drm_display_mode *mode, | 		    const struct drm_display_mode *mode, | ||||||
| 		    struct drm_display_mode *adjusted_mode) | 		    struct drm_display_mode *adjusted_mode) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nouveau_connector *connector; | 	struct nouveau_connector *connector; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); | 	NV_DEBUG(drm, "or %d\n", nv_encoder->or); | ||||||
| 
 | 
 | ||||||
| 	connector = nouveau_encoder_connector_get(nv_encoder); | 	connector = nouveau_encoder_connector_get(nv_encoder); | ||||||
| 	if (!connector) { | 	if (!connector) { | ||||||
| 		NV_ERROR(encoder->dev, "Encoder has no connector\n"); | 		NV_ERROR(drm, "Encoder has no connector\n"); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -207,13 +214,14 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||||||
| 		  struct drm_display_mode *adjusted_mode) | 		  struct drm_display_mode *adjusted_mode) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	uint32_t mode_ctl = 0, mode_ctl2 = 0; | 	uint32_t mode_ctl = 0, mode_ctl2 = 0; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "or %d type %d crtc %d\n", | 	NV_DEBUG(drm, "or %d type %d crtc %d\n", | ||||||
| 		     nv_encoder->or, nv_encoder->dcb->type, crtc->index); | 		     nv_encoder->or, nv_encoder->dcb->type, crtc->index); | ||||||
| 
 | 
 | ||||||
| 	nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); | 	nv50_dac_dpms(encoder, DRM_MODE_DPMS_ON); | ||||||
|  | @ -238,7 +246,7 @@ nv50_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 3); | 	ret = RING_SPACE(evo, 3); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while connecting DAC\n"); | 		NV_ERROR(drm, "no space while connecting DAC\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); | 	BEGIN_NV04(evo, 0, NV50_EVO_DAC(nv_encoder->or, MODE_CTRL), 2); | ||||||
|  | @ -271,11 +279,12 @@ static void | ||||||
| nv50_dac_destroy(struct drm_encoder *encoder) | nv50_dac_destroy(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 
 | 
 | ||||||
| 	if (!encoder) | 	if (!encoder) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	drm_encoder_cleanup(encoder); | 	drm_encoder_cleanup(encoder); | ||||||
| 	kfree(nv_encoder); | 	kfree(nv_encoder); | ||||||
|  |  | ||||||
|  | @ -24,27 +24,30 @@ | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_dma.h" | ||||||
|  | 
 | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_fbcon.h" | #include "nouveau_fbcon.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| 
 | 
 | ||||||
| static void nv50_display_isr(struct drm_device *); | #include <core/gpuobj.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | 
 | ||||||
| static void nv50_display_bh(unsigned long); | static void nv50_display_bh(unsigned long); | ||||||
| 
 | 
 | ||||||
| static inline int | static inline int | ||||||
| nv50_sor_nr(struct drm_device *dev) | nv50_sor_nr(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset  < 0x90 || | 	if (device->chipset  < 0x90 || | ||||||
| 	    dev_priv->chipset == 0x92 || | 	    device->chipset == 0x92 || | ||||||
| 	    dev_priv->chipset == 0xa0) | 	    device->chipset == 0xa0) | ||||||
| 		return 2; | 		return 2; | ||||||
| 
 | 
 | ||||||
| 	return 4; | 	return 4; | ||||||
|  | @ -53,22 +56,22 @@ nv50_sor_nr(struct drm_device *dev) | ||||||
| u32 | u32 | ||||||
| nv50_display_active_crtcs(struct drm_device *dev) | nv50_display_active_crtcs(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 mask = 0; | 	u32 mask = 0; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset  < 0x90 || | 	if (device->chipset  < 0x90 || | ||||||
| 	    dev_priv->chipset == 0x92 || | 	    device->chipset == 0x92 || | ||||||
| 	    dev_priv->chipset == 0xa0) { | 	    device->chipset == 0xa0) { | ||||||
| 		for (i = 0; i < 2; i++) | 		for (i = 0; i < 2; i++) | ||||||
| 			mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); | 			mask |= nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); | ||||||
| 	} else { | 	} else { | ||||||
| 		for (i = 0; i < 4; i++) | 		for (i = 0; i < 4; i++) | ||||||
| 			mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); | 			mask |= nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 3; i++) | 	for (i = 0; i < 3; i++) | ||||||
| 		mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); | 		mask |= nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); | ||||||
| 
 | 
 | ||||||
| 	return mask & 3; | 	return mask & 3; | ||||||
| } | } | ||||||
|  | @ -89,7 +92,6 @@ nv50_display_sync(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	struct nouveau_channel *evo = disp->master; | 	struct nouveau_channel *evo = disp->master; | ||||||
| 	u64 start; |  | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 6); | 	ret = RING_SPACE(evo, 6); | ||||||
|  | @ -104,11 +106,8 @@ nv50_display_sync(struct drm_device *dev) | ||||||
| 		nv_wo32(disp->ramin, 0x2000, 0x00000000); | 		nv_wo32(disp->ramin, 0x2000, 0x00000000); | ||||||
| 		FIRE_RING (evo); | 		FIRE_RING (evo); | ||||||
| 
 | 
 | ||||||
| 		start = nv_timer_read(dev); | 		if (nv_wait_ne(disp->ramin, 0x2000, 0xffffffff, 0x00000000)) | ||||||
| 		do { |  | ||||||
| 			if (nv_ro32(disp->ramin, 0x2000)) |  | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} while (nv_timer_read(dev) - start < 2000000000ULL); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -117,13 +116,15 @@ nv50_display_sync(struct drm_device *dev) | ||||||
| int | int | ||||||
| nv50_display_init(struct drm_device *dev) | nv50_display_init(struct drm_device *dev) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_channel *evo; | 	struct nouveau_channel *evo; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 	u32 val; | 	u32 val; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x00610184, nv_rd32(dev, 0x00614004)); | 	nv_wr32(device, 0x00610184, nv_rd32(device, 0x00614004)); | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * I think the 0x006101XX range is some kind of main control area | 	 * I think the 0x006101XX range is some kind of main control area | ||||||
|  | @ -131,82 +132,82 @@ nv50_display_init(struct drm_device *dev) | ||||||
| 	 */ | 	 */ | ||||||
| 	/* CRTC? */ | 	/* CRTC? */ | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
| 		val = nv_rd32(dev, 0x00616100 + (i * 0x800)); | 		val = nv_rd32(device, 0x00616100 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x00610190 + (i * 0x10), val); | 		nv_wr32(device, 0x00610190 + (i * 0x10), val); | ||||||
| 		val = nv_rd32(dev, 0x00616104 + (i * 0x800)); | 		val = nv_rd32(device, 0x00616104 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x00610194 + (i * 0x10), val); | 		nv_wr32(device, 0x00610194 + (i * 0x10), val); | ||||||
| 		val = nv_rd32(dev, 0x00616108 + (i * 0x800)); | 		val = nv_rd32(device, 0x00616108 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x00610198 + (i * 0x10), val); | 		nv_wr32(device, 0x00610198 + (i * 0x10), val); | ||||||
| 		val = nv_rd32(dev, 0x0061610c + (i * 0x800)); | 		val = nv_rd32(device, 0x0061610c + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x0061019c + (i * 0x10), val); | 		nv_wr32(device, 0x0061019c + (i * 0x10), val); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* DAC */ | 	/* DAC */ | ||||||
| 	for (i = 0; i < 3; i++) { | 	for (i = 0; i < 3; i++) { | ||||||
| 		val = nv_rd32(dev, 0x0061a000 + (i * 0x800)); | 		val = nv_rd32(device, 0x0061a000 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x006101d0 + (i * 0x04), val); | 		nv_wr32(device, 0x006101d0 + (i * 0x04), val); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* SOR */ | 	/* SOR */ | ||||||
| 	for (i = 0; i < nv50_sor_nr(dev); i++) { | 	for (i = 0; i < nv50_sor_nr(dev); i++) { | ||||||
| 		val = nv_rd32(dev, 0x0061c000 + (i * 0x800)); | 		val = nv_rd32(device, 0x0061c000 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x006101e0 + (i * 0x04), val); | 		nv_wr32(device, 0x006101e0 + (i * 0x04), val); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* EXT */ | 	/* EXT */ | ||||||
| 	for (i = 0; i < 3; i++) { | 	for (i = 0; i < 3; i++) { | ||||||
| 		val = nv_rd32(dev, 0x0061e000 + (i * 0x800)); | 		val = nv_rd32(device, 0x0061e000 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x006101f0 + (i * 0x04), val); | 		nv_wr32(device, 0x006101f0 + (i * 0x04), val); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 3; i++) { | 	for (i = 0; i < 3; i++) { | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 | | 		nv_wr32(device, NV50_PDISPLAY_DAC_DPMS_CTRL(i), 0x00550000 | | ||||||
| 			NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | 			NV50_PDISPLAY_DAC_DPMS_CTRL_PENDING); | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); | 		nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL1(i), 0x00000001); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* The precise purpose is unknown, i suspect it has something to do
 | 	/* The precise purpose is unknown, i suspect it has something to do
 | ||||||
| 	 * with text mode. | 	 * with text mode. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (nv_rd32(dev, NV50_PDISPLAY_INTR_1) & 0x100) { | 	if (nv_rd32(device, NV50_PDISPLAY_INTR_1) & 0x100) { | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_INTR_1, 0x100); | 		nv_wr32(device, NV50_PDISPLAY_INTR_1, 0x100); | ||||||
| 		nv_wr32(dev, 0x006194e8, nv_rd32(dev, 0x006194e8) & ~1); | 		nv_wr32(device, 0x006194e8, nv_rd32(device, 0x006194e8) & ~1); | ||||||
| 		if (!nv_wait(dev, 0x006194e8, 2, 0)) { | 		if (!nv_wait(device, 0x006194e8, 2, 0)) { | ||||||
| 			NV_ERROR(dev, "timeout: (0x6194e8 & 2) != 0\n"); | 			NV_ERROR(drm, "timeout: (0x6194e8 & 2) != 0\n"); | ||||||
| 			NV_ERROR(dev, "0x6194e8 = 0x%08x\n", | 			NV_ERROR(drm, "0x6194e8 = 0x%08x\n", | ||||||
| 						nv_rd32(dev, 0x6194e8)); | 						nv_rd32(device, 0x6194e8)); | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); | 		nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0x2000); | ||||||
| 		if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 		if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | ||||||
| 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { | 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { | ||||||
| 			NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); | 			NV_ERROR(drm, "timeout: CURSOR_CTRL2_STATUS == 0\n"); | ||||||
| 			NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", | 			NV_ERROR(drm, "CURSOR_CTRL2 = 0x%08x\n", | ||||||
| 				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); | 				 nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 		nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | ||||||
| 			NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); | 			NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_ON); | ||||||
| 		if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 		if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | ||||||
| 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, | 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, | ||||||
| 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { | 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS_ACTIVE)) { | ||||||
| 			NV_ERROR(dev, "timeout: " | 			NV_ERROR(drm, "timeout: " | ||||||
| 				      "CURSOR_CTRL2_STATUS_ACTIVE(%d)\n", i); | 				      "CURSOR_CTRL2_STATUS_ACTIVE(%d)\n", i); | ||||||
| 			NV_ERROR(dev, "CURSOR_CTRL2(%d) = 0x%08x\n", i, | 			NV_ERROR(drm, "CURSOR_CTRL2(%d) = 0x%08x\n", i, | ||||||
| 				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); | 				 nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_PIO_CTRL, 0x00000000); | 	nv_wr32(device, NV50_PDISPLAY_PIO_CTRL, 0x00000000); | ||||||
| 	nv_mask(dev, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); | 	nv_mask(device, NV50_PDISPLAY_INTR_0, 0x00000000, 0x00000000); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_0, 0x00000000); | 	nv_wr32(device, NV50_PDISPLAY_INTR_EN_0, 0x00000000); | ||||||
| 	nv_mask(dev, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); | 	nv_mask(device, NV50_PDISPLAY_INTR_1, 0x00000000, 0x00000000); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, | 	nv_wr32(device, NV50_PDISPLAY_INTR_EN_1, | ||||||
| 		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | | 		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK10 | | ||||||
| 		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | | 		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | | ||||||
| 		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); | 		     NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); | ||||||
|  | @ -216,7 +217,7 @@ nv50_display_init(struct drm_device *dev) | ||||||
| 		return ret; | 		return ret; | ||||||
| 	evo = nv50_display(dev)->master; | 	evo = nv50_display(dev)->master; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (nv50_display(dev)->ramin->addr >> 8) | 9); | 	nv_wr32(device, NV50_PDISPLAY_OBJECTS, (nv50_display(dev)->ramin->addr >> 8) | 9); | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 3); | 	ret = RING_SPACE(evo, 3); | ||||||
| 	if (ret) | 	if (ret) | ||||||
|  | @ -231,12 +232,14 @@ nv50_display_init(struct drm_device *dev) | ||||||
| void | void | ||||||
| nv50_display_fini(struct drm_device *dev) | nv50_display_fini(struct drm_device *dev) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	struct nouveau_channel *evo = disp->master; | 	struct nouveau_channel *evo = disp->master; | ||||||
| 	struct drm_crtc *drm_crtc; | 	struct drm_crtc *drm_crtc; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { | 	list_for_each_entry(drm_crtc, &dev->mode_config.crtc_list, head) { | ||||||
| 		struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); | 		struct nouveau_crtc *crtc = nouveau_crtc(drm_crtc); | ||||||
|  | @ -261,55 +264,59 @@ nv50_display_fini(struct drm_device *dev) | ||||||
| 		if (!crtc->base.enabled) | 		if (!crtc->base.enabled) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_INTR_1, mask); | 		nv_wr32(device, NV50_PDISPLAY_INTR_1, mask); | ||||||
| 		if (!nv_wait(dev, NV50_PDISPLAY_INTR_1, mask, mask)) { | 		if (!nv_wait(device, NV50_PDISPLAY_INTR_1, mask, mask)) { | ||||||
| 			NV_ERROR(dev, "timeout: (0x610024 & 0x%08x) == " | 			NV_ERROR(drm, "timeout: (0x610024 & 0x%08x) == " | ||||||
| 				      "0x%08x\n", mask, mask); | 				      "0x%08x\n", mask, mask); | ||||||
| 			NV_ERROR(dev, "0x610024 = 0x%08x\n", | 			NV_ERROR(drm, "0x610024 = 0x%08x\n", | ||||||
| 				 nv_rd32(dev, NV50_PDISPLAY_INTR_1)); | 				 nv_rd32(device, NV50_PDISPLAY_INTR_1)); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); | 		nv_wr32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), 0); | ||||||
| 		if (!nv_wait(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | 		if (!nv_wait(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i), | ||||||
| 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { | 			     NV50_PDISPLAY_CURSOR_CURSOR_CTRL2_STATUS, 0)) { | ||||||
| 			NV_ERROR(dev, "timeout: CURSOR_CTRL2_STATUS == 0\n"); | 			NV_ERROR(drm, "timeout: CURSOR_CTRL2_STATUS == 0\n"); | ||||||
| 			NV_ERROR(dev, "CURSOR_CTRL2 = 0x%08x\n", | 			NV_ERROR(drm, "CURSOR_CTRL2 = 0x%08x\n", | ||||||
| 				 nv_rd32(dev, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); | 				 nv_rd32(device, NV50_PDISPLAY_CURSOR_CURSOR_CTRL2(i))); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv50_evo_fini(dev); | 	nv50_evo_fini(dev); | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 3; i++) { | 	for (i = 0; i < 3; i++) { | ||||||
| 		if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i), | 		if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_STATE(i), | ||||||
| 			     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { | 			     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { | ||||||
| 			NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); | 			NV_ERROR(drm, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", i); | ||||||
| 			NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, | 			NV_ERROR(drm, "SOR_DPMS_STATE(%d) = 0x%08x\n", i, | ||||||
| 				  nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(i))); | 				  nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_STATE(i))); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* disable interrupts. */ | 	/* disable interrupts. */ | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); | 	nv_wr32(device, NV50_PDISPLAY_INTR_EN_1, 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nv50_display_create(struct drm_device *dev) | nv50_display_create(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_table *dcb = &dev_priv->vbios.dcb; | 	struct dcb_table *dcb = &drm->vbios.dcb; | ||||||
| 	struct drm_connector *connector, *ct; | 	struct drm_connector *connector, *ct; | ||||||
| 	struct nv50_display *priv; | 	struct nv50_display *priv; | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 	priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||||||
| 	if (!priv) | 	if (!priv) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	dev_priv->engine.display.priv = priv; | 
 | ||||||
|  | 	nouveau_display(dev)->priv = priv; | ||||||
|  | 	nouveau_display(dev)->dtor = nv50_display_destroy; | ||||||
|  | 	nouveau_display(dev)->init = nv50_display_init; | ||||||
|  | 	nouveau_display(dev)->fini = nv50_display_fini; | ||||||
| 
 | 
 | ||||||
| 	/* Create CRTC objects */ | 	/* Create CRTC objects */ | ||||||
| 	for (i = 0; i < 2; i++) { | 	for (i = 0; i < 2; i++) { | ||||||
|  | @ -323,7 +330,7 @@ nv50_display_create(struct drm_device *dev) | ||||||
| 		struct dcb_output *entry = &dcb->entry[i]; | 		struct dcb_output *entry = &dcb->entry[i]; | ||||||
| 
 | 
 | ||||||
| 		if (entry->location != DCB_LOC_ON_CHIP) { | 		if (entry->location != DCB_LOC_ON_CHIP) { | ||||||
| 			NV_WARN(dev, "Off-chip encoder %d/%d unsupported\n", | 			NV_WARN(drm, "Off-chip encoder %d/%d unsupported\n", | ||||||
| 				entry->type, ffs(entry->or) - 1); | 				entry->type, ffs(entry->or) - 1); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | @ -342,7 +349,7 @@ nv50_display_create(struct drm_device *dev) | ||||||
| 			nv50_dac_create(connector, entry); | 			nv50_dac_create(connector, entry); | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_WARN(dev, "DCB encoder %d unknown\n", entry->type); | 			NV_WARN(drm, "DCB encoder %d unknown\n", entry->type); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -350,14 +357,13 @@ nv50_display_create(struct drm_device *dev) | ||||||
| 	list_for_each_entry_safe(connector, ct, | 	list_for_each_entry_safe(connector, ct, | ||||||
| 				 &dev->mode_config.connector_list, head) { | 				 &dev->mode_config.connector_list, head) { | ||||||
| 		if (!connector->encoder_ids[0]) { | 		if (!connector->encoder_ids[0]) { | ||||||
| 			NV_WARN(dev, "%s has no encoders, removing\n", | 			NV_WARN(drm, "%s has no encoders, removing\n", | ||||||
| 				drm_get_connector_name(connector)); | 				drm_get_connector_name(connector)); | ||||||
| 			connector->funcs->destroy(connector); | 			connector->funcs->destroy(connector); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); | 	tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); | ||||||
| 	nouveau_irq_register(dev, 26, nv50_display_isr); |  | ||||||
| 
 | 
 | ||||||
| 	ret = nv50_evo_create(dev); | 	ret = nv50_evo_create(dev); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
|  | @ -373,13 +379,16 @@ nv50_display_destroy(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); |  | ||||||
| 
 |  | ||||||
| 	nv50_evo_destroy(dev); | 	nv50_evo_destroy(dev); | ||||||
| 	nouveau_irq_unregister(dev, 26); |  | ||||||
| 	kfree(disp); | 	kfree(disp); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | struct nouveau_bo * | ||||||
|  | nv50_display_crtc_sema(struct drm_device *dev, int crtc) | ||||||
|  | { | ||||||
|  | 	return nv50_display(dev)->crtc[crtc].sem.bo; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void | void | ||||||
| nv50_display_flip_stop(struct drm_crtc *crtc) | nv50_display_flip_stop(struct drm_crtc *crtc) | ||||||
| { | { | ||||||
|  | @ -410,7 +419,7 @@ int | ||||||
| nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| 		       struct nouveau_channel *chan) | 		       struct nouveau_channel *chan) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
| 	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); | 	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); | ||||||
| 	struct nv50_display *disp = nv50_display(crtc->dev); | 	struct nv50_display *disp = nv50_display(crtc->dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
|  | @ -430,7 +439,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| 			return ret; | 			return ret; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (dev_priv->chipset < 0xc0) { | 		if (nv_device(drm->device)->chipset < 0xc0) { | ||||||
| 			BEGIN_NV04(chan, 0, 0x0060, 2); | 			BEGIN_NV04(chan, 0, 0x0060, 2); | ||||||
| 			OUT_RING  (chan, NvEvoSema0 + nv_crtc->index); | 			OUT_RING  (chan, NvEvoSema0 + nv_crtc->index); | ||||||
| 			OUT_RING  (chan, dispc->sem.offset); | 			OUT_RING  (chan, dispc->sem.offset); | ||||||
|  | @ -440,7 +449,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| 			OUT_RING  (chan, dispc->sem.offset ^ 0x10); | 			OUT_RING  (chan, dispc->sem.offset ^ 0x10); | ||||||
| 			OUT_RING  (chan, 0x74b1e000); | 			OUT_RING  (chan, 0x74b1e000); | ||||||
| 			BEGIN_NV04(chan, 0, 0x0060, 1); | 			BEGIN_NV04(chan, 0, 0x0060, 1); | ||||||
| 			if (dev_priv->chipset < 0x84) | 			if (nv_device(drm->device)->chipset < 0x84) | ||||||
| 				OUT_RING  (chan, NvSema); | 				OUT_RING  (chan, NvSema); | ||||||
| 			else | 			else | ||||||
| 				OUT_RING  (chan, chan->vram); | 				OUT_RING  (chan, chan->vram); | ||||||
|  | @ -511,10 +520,10 @@ static u16 | ||||||
| nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, | nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 			   u32 mc, int pxclk) | 			   u32 mc, int pxclk) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_connector *nv_connector = NULL; | 	struct nouveau_connector *nv_connector = NULL; | ||||||
| 	struct drm_encoder *encoder; | 	struct drm_encoder *encoder; | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	u32 script = 0, or; | 	u32 script = 0, or; | ||||||
| 
 | 
 | ||||||
| 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||||||
|  | @ -562,25 +571,11 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 			    (nv_connector->edid->input & 0x70) >= 0x20) | 			    (nv_connector->edid->input & 0x70) >= 0x20) | ||||||
| 				script |= 0x0200; | 				script |= 0x0200; | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 		if (nouveau_uscript_lvds >= 0) { |  | ||||||
| 			NV_INFO(dev, "override script 0x%04x with 0x%04x " |  | ||||||
| 				     "for output LVDS-%d\n", script, |  | ||||||
| 				     nouveau_uscript_lvds, or); |  | ||||||
| 			script = nouveau_uscript_lvds; |  | ||||||
| 		} |  | ||||||
| 		break; | 		break; | ||||||
| 	case DCB_OUTPUT_TMDS: | 	case DCB_OUTPUT_TMDS: | ||||||
| 		script = (mc >> 8) & 0xf; | 		script = (mc >> 8) & 0xf; | ||||||
| 		if (pxclk >= 165000) | 		if (pxclk >= 165000) | ||||||
| 			script |= 0x0100; | 			script |= 0x0100; | ||||||
| 
 |  | ||||||
| 		if (nouveau_uscript_tmds >= 0) { |  | ||||||
| 			NV_INFO(dev, "override script 0x%04x with 0x%04x " |  | ||||||
| 				     "for output TMDS-%d\n", script, |  | ||||||
| 				     nouveau_uscript_tmds, or); |  | ||||||
| 			script = nouveau_uscript_tmds; |  | ||||||
| 		} |  | ||||||
| 		break; | 		break; | ||||||
| 	case DCB_OUTPUT_DP: | 	case DCB_OUTPUT_DP: | ||||||
| 		script = (mc >> 8) & 0xf; | 		script = (mc >> 8) & 0xf; | ||||||
|  | @ -589,7 +584,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 		script = 0xff; | 		script = 0xff; | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, "modeset on unsupported output type!\n"); | 		NV_ERROR(drm, "modeset on unsupported output type!\n"); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -599,15 +594,16 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| static void | static void | ||||||
| nv50_display_unk10_handler(struct drm_device *dev) | nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	u32 unk30 = nv_rd32(dev, 0x610030), mc; | 	u32 unk30 = nv_rd32(device, 0x610030), mc; | ||||||
| 	int i, crtc, or = 0, type = DCB_OUTPUT_ANY; | 	int i, crtc, or = 0, type = DCB_OUTPUT_ANY; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | 	NV_DEBUG(drm, "0x610030: 0x%08x\n", unk30); | ||||||
| 	disp->irq.dcb = NULL; | 	disp->irq.dcb = NULL; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8); | 	nv_wr32(device, 0x619494, nv_rd32(device, 0x619494) & ~8); | ||||||
| 
 | 
 | ||||||
| 	/* Determine which CRTC we're dealing with, only 1 ever will be
 | 	/* Determine which CRTC we're dealing with, only 1 ever will be
 | ||||||
| 	 * signalled at the same time with the current nouveau code. | 	 * signalled at the same time with the current nouveau code. | ||||||
|  | @ -623,8 +619,8 @@ nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	/* Find which encoder was connected to the CRTC */ | 	/* Find which encoder was connected to the CRTC */ | ||||||
| 	for (i = 0; type == DCB_OUTPUT_ANY && i < 3; i++) { | 	for (i = 0; type == DCB_OUTPUT_ANY && i < 3; i++) { | ||||||
| 		mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); | 		mc = nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_C(i)); | ||||||
| 		NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); | 		NV_DEBUG(drm, "DAC-%d mc: 0x%08x\n", i, mc); | ||||||
| 		if (!(mc & (1 << crtc))) | 		if (!(mc & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -632,7 +628,7 @@ nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| 		case 0: type = DCB_OUTPUT_ANALOG; break; | 		case 0: type = DCB_OUTPUT_ANALOG; break; | ||||||
| 		case 1: type = DCB_OUTPUT_TV; break; | 		case 1: type = DCB_OUTPUT_TV; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); | 			NV_ERROR(drm, "invalid mc, DAC-%d: 0x%08x\n", i, mc); | ||||||
| 			goto ack; | 			goto ack; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -640,14 +636,14 @@ nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; type == DCB_OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { | 	for (i = 0; type == DCB_OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { | ||||||
| 		if (dev_priv->chipset  < 0x90 || | 		if (nv_device(drm->device)->chipset  < 0x90 || | ||||||
| 		    dev_priv->chipset == 0x92 || | 		    nv_device(drm->device)->chipset == 0x92 || | ||||||
| 		    dev_priv->chipset == 0xa0) | 		    nv_device(drm->device)->chipset == 0xa0) | ||||||
| 			mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); | 			mc = nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_C(i)); | ||||||
| 		else | 		else | ||||||
| 			mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); | 			mc = nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_C(i)); | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); | 		NV_DEBUG(drm, "SOR-%d mc: 0x%08x\n", i, mc); | ||||||
| 		if (!(mc & (1 << crtc))) | 		if (!(mc & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -659,7 +655,7 @@ nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| 		case 8: type = DCB_OUTPUT_DP; break; | 		case 8: type = DCB_OUTPUT_DP; break; | ||||||
| 		case 9: type = DCB_OUTPUT_DP; break; | 		case 9: type = DCB_OUTPUT_DP; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); | 			NV_ERROR(drm, "invalid mc, SOR-%d: 0x%08x\n", i, mc); | ||||||
| 			goto ack; | 			goto ack; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -671,8 +667,8 @@ nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| 		goto ack; | 		goto ack; | ||||||
| 
 | 
 | ||||||
| 	/* Disable the encoder */ | 	/* Disable the encoder */ | ||||||
| 	for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { | 	for (i = 0; i < drm->vbios.dcb.entries; i++) { | ||||||
| 		struct dcb_output *dcb = &dev_priv->vbios.dcb.entry[i]; | 		struct dcb_output *dcb = &drm->vbios.dcb.entry[i]; | ||||||
| 
 | 
 | ||||||
| 		if (dcb->type == type && (dcb->or & (1 << or))) { | 		if (dcb->type == type && (dcb->or & (1 << or))) { | ||||||
| 			nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); | 			nouveau_bios_run_display_table(dev, 0, -1, dcb, -1); | ||||||
|  | @ -681,22 +677,23 @@ nv50_display_unk10_handler(struct drm_device *dev) | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); | 	NV_ERROR(drm, "no dcb for %d %d 0x%08x\n", or, type, mc); | ||||||
| ack: | ack: | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); | 	nv_wr32(device, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK10); | ||||||
| 	nv_wr32(dev, 0x610030, 0x80000000); | 	nv_wr32(device, 0x610030, 0x80000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_display_unk20_handler(struct drm_device *dev) | nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0; | 	u32 unk30 = nv_rd32(device, 0x610030), tmp, pclk, script, mc = 0; | ||||||
| 	struct dcb_output *dcb; | 	struct dcb_output *dcb; | ||||||
| 	int i, crtc, or = 0, type = DCB_OUTPUT_ANY; | 	int i, crtc, or = 0, type = DCB_OUTPUT_ANY; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | 	NV_DEBUG(drm, "0x610030: 0x%08x\n", unk30); | ||||||
| 	dcb = disp->irq.dcb; | 	dcb = disp->irq.dcb; | ||||||
| 	if (dcb) { | 	if (dcb) { | ||||||
| 		nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); | 		nouveau_bios_run_display_table(dev, 0, -2, dcb, -1); | ||||||
|  | @ -706,26 +703,26 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 	/* CRTC clock change requested? */ | 	/* CRTC clock change requested? */ | ||||||
| 	crtc = ffs((unk30 & 0x00000600) >> 9) - 1; | 	crtc = ffs((unk30 & 0x00000600) >> 9) - 1; | ||||||
| 	if (crtc >= 0) { | 	if (crtc >= 0) { | ||||||
| 		pclk  = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); | 		pclk  = nv_rd32(device, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); | ||||||
| 		pclk &= 0x003fffff; | 		pclk &= 0x003fffff; | ||||||
| 		if (pclk) | 		if (pclk) | ||||||
| 			nv50_crtc_set_clock(dev, crtc, pclk); | 			nv50_crtc_set_clock(dev, crtc, pclk); | ||||||
| 
 | 
 | ||||||
| 		tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); | 		tmp = nv_rd32(device, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); | ||||||
| 		tmp &= ~0x000000f; | 		tmp &= ~0x000000f; | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp); | 		nv_wr32(device, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc), tmp); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* Nothing needs to be done for the encoder */ | 	/* Nothing needs to be done for the encoder */ | ||||||
| 	crtc = ffs((unk30 & 0x00000180) >> 7) - 1; | 	crtc = ffs((unk30 & 0x00000180) >> 7) - 1; | ||||||
| 	if (crtc < 0) | 	if (crtc < 0) | ||||||
| 		goto ack; | 		goto ack; | ||||||
| 	pclk  = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; | 	pclk  = nv_rd32(device, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)) & 0x003fffff; | ||||||
| 
 | 
 | ||||||
| 	/* Find which encoder is connected to the CRTC */ | 	/* Find which encoder is connected to the CRTC */ | ||||||
| 	for (i = 0; type == DCB_OUTPUT_ANY && i < 3; i++) { | 	for (i = 0; type == DCB_OUTPUT_ANY && i < 3; i++) { | ||||||
| 		mc = nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_P(i)); | 		mc = nv_rd32(device, NV50_PDISPLAY_DAC_MODE_CTRL_P(i)); | ||||||
| 		NV_DEBUG_KMS(dev, "DAC-%d mc: 0x%08x\n", i, mc); | 		NV_DEBUG(drm, "DAC-%d mc: 0x%08x\n", i, mc); | ||||||
| 		if (!(mc & (1 << crtc))) | 		if (!(mc & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -733,7 +730,7 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 		case 0: type = DCB_OUTPUT_ANALOG; break; | 		case 0: type = DCB_OUTPUT_ANALOG; break; | ||||||
| 		case 1: type = DCB_OUTPUT_TV; break; | 		case 1: type = DCB_OUTPUT_TV; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "invalid mc, DAC-%d: 0x%08x\n", i, mc); | 			NV_ERROR(drm, "invalid mc, DAC-%d: 0x%08x\n", i, mc); | ||||||
| 			goto ack; | 			goto ack; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -741,14 +738,14 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; type == DCB_OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { | 	for (i = 0; type == DCB_OUTPUT_ANY && i < nv50_sor_nr(dev); i++) { | ||||||
| 		if (dev_priv->chipset  < 0x90 || | 		if (nv_device(drm->device)->chipset  < 0x90 || | ||||||
| 		    dev_priv->chipset == 0x92 || | 		    nv_device(drm->device)->chipset == 0x92 || | ||||||
| 		    dev_priv->chipset == 0xa0) | 		    nv_device(drm->device)->chipset == 0xa0) | ||||||
| 			mc = nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_P(i)); | 			mc = nv_rd32(device, NV50_PDISPLAY_SOR_MODE_CTRL_P(i)); | ||||||
| 		else | 		else | ||||||
| 			mc = nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_P(i)); | 			mc = nv_rd32(device, NV90_PDISPLAY_SOR_MODE_CTRL_P(i)); | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "SOR-%d mc: 0x%08x\n", i, mc); | 		NV_DEBUG(drm, "SOR-%d mc: 0x%08x\n", i, mc); | ||||||
| 		if (!(mc & (1 << crtc))) | 		if (!(mc & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -760,7 +757,7 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 		case 8: type = DCB_OUTPUT_DP; break; | 		case 8: type = DCB_OUTPUT_DP; break; | ||||||
| 		case 9: type = DCB_OUTPUT_DP; break; | 		case 9: type = DCB_OUTPUT_DP; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "invalid mc, SOR-%d: 0x%08x\n", i, mc); | 			NV_ERROR(drm, "invalid mc, SOR-%d: 0x%08x\n", i, mc); | ||||||
| 			goto ack; | 			goto ack; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -771,14 +768,14 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 		goto ack; | 		goto ack; | ||||||
| 
 | 
 | ||||||
| 	/* Enable the encoder */ | 	/* Enable the encoder */ | ||||||
| 	for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { | 	for (i = 0; i < drm->vbios.dcb.entries; i++) { | ||||||
| 		dcb = &dev_priv->vbios.dcb.entry[i]; | 		dcb = &drm->vbios.dcb.entry[i]; | ||||||
| 		if (dcb->type == type && (dcb->or & (1 << or))) | 		if (dcb->type == type && (dcb->or & (1 << or))) | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (i == dev_priv->vbios.dcb.entries) { | 	if (i == drm->vbios.dcb.entries) { | ||||||
| 		NV_ERROR(dev, "no dcb for %d %d 0x%08x\n", or, type, mc); | 		NV_ERROR(drm, "no dcb for %d %d 0x%08x\n", or, type, mc); | ||||||
| 		goto ack; | 		goto ack; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -794,13 +791,13 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dcb->type != DCB_OUTPUT_ANALOG) { | 	if (dcb->type != DCB_OUTPUT_ANALOG) { | ||||||
| 		tmp = nv_rd32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); | 		tmp = nv_rd32(device, NV50_PDISPLAY_SOR_CLK_CTRL2(or)); | ||||||
| 		tmp &= ~0x00000f0f; | 		tmp &= ~0x00000f0f; | ||||||
| 		if (script & 0x0100) | 		if (script & 0x0100) | ||||||
| 			tmp |= 0x00000101; | 			tmp |= 0x00000101; | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp); | 		nv_wr32(device, NV50_PDISPLAY_SOR_CLK_CTRL2(or), tmp); | ||||||
| 	} else { | 	} else { | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); | 		nv_wr32(device, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	disp->irq.dcb = dcb; | 	disp->irq.dcb = dcb; | ||||||
|  | @ -808,8 +805,8 @@ nv50_display_unk20_handler(struct drm_device *dev) | ||||||
| 	disp->irq.script = script; | 	disp->irq.script = script; | ||||||
| 
 | 
 | ||||||
| ack: | ack: | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); | 	nv_wr32(device, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20); | ||||||
| 	nv_wr32(dev, 0x610030, 0x80000000); | 	nv_wr32(device, 0x610030, 0x80000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* If programming a TMDS output on a SOR that can also be configured for
 | /* If programming a TMDS output on a SOR that can also be configured for
 | ||||||
|  | @ -823,6 +820,7 @@ ack: | ||||||
| static void | static void | ||||||
| nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) | nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); | 	int or = ffs(dcb->or) - 1, link = !(dcb->dpconf.sor.link & 1); | ||||||
| 	struct drm_encoder *encoder; | 	struct drm_encoder *encoder; | ||||||
| 	u32 tmp; | 	u32 tmp; | ||||||
|  | @ -835,9 +833,9 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) | ||||||
| 
 | 
 | ||||||
| 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP && | 		if (nv_encoder->dcb->type == DCB_OUTPUT_DP && | ||||||
| 		    nv_encoder->dcb->or & (1 << or)) { | 		    nv_encoder->dcb->or & (1 << or)) { | ||||||
| 			tmp  = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)); | 			tmp  = nv_rd32(device, NV50_SOR_DP_CTRL(or, link)); | ||||||
| 			tmp &= ~NV50_SOR_DP_CTRL_ENABLED; | 			tmp &= ~NV50_SOR_DP_CTRL_ENABLED; | ||||||
| 			nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), tmp); | 			nv_wr32(device, NV50_SOR_DP_CTRL(or, link), tmp); | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -846,12 +844,14 @@ nv50_display_unk40_dp_set_tmds(struct drm_device *dev, struct dcb_output *dcb) | ||||||
| static void | static void | ||||||
| nv50_display_unk40_handler(struct drm_device *dev) | nv50_display_unk40_handler(struct drm_device *dev) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	struct dcb_output *dcb = disp->irq.dcb; | 	struct dcb_output *dcb = disp->irq.dcb; | ||||||
| 	u16 script = disp->irq.script; | 	u16 script = disp->irq.script; | ||||||
| 	u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk; | 	u32 unk30 = nv_rd32(device, 0x610030), pclk = disp->irq.pclk; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30); | 	NV_DEBUG(drm, "0x610030: 0x%08x\n", unk30); | ||||||
| 	disp->irq.dcb = NULL; | 	disp->irq.dcb = NULL; | ||||||
| 	if (!dcb) | 	if (!dcb) | ||||||
| 		goto ack; | 		goto ack; | ||||||
|  | @ -860,21 +860,23 @@ nv50_display_unk40_handler(struct drm_device *dev) | ||||||
| 	nv50_display_unk40_dp_set_tmds(dev, dcb); | 	nv50_display_unk40_dp_set_tmds(dev, dcb); | ||||||
| 
 | 
 | ||||||
| ack: | ack: | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); | 	nv_wr32(device, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK40); | ||||||
| 	nv_wr32(dev, 0x610030, 0x80000000); | 	nv_wr32(device, 0x610030, 0x80000000); | ||||||
| 	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8); | 	nv_wr32(device, 0x619494, nv_rd32(device, 0x619494) | 8); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_display_bh(unsigned long data) | nv50_display_bh(unsigned long data) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = (struct drm_device *)data; | 	struct drm_device *dev = (struct drm_device *)data; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	for (;;) { | 	for (;;) { | ||||||
| 		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); | 		uint32_t intr0 = nv_rd32(device, NV50_PDISPLAY_INTR_0); | ||||||
| 		uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); | 		uint32_t intr1 = nv_rd32(device, NV50_PDISPLAY_INTR_1); | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); | 		NV_DEBUG(drm, "PDISPLAY_INTR_BH 0x%08x 0x%08x\n", intr0, intr1); | ||||||
| 
 | 
 | ||||||
| 		if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10) | 		if (intr1 & NV50_PDISPLAY_INTR_1_CLK_UNK10) | ||||||
| 			nv50_display_unk10_handler(dev); | 			nv50_display_unk10_handler(dev); | ||||||
|  | @ -888,13 +890,15 @@ nv50_display_bh(unsigned long data) | ||||||
| 			break; | 			break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV03_PMC_INTR_EN_0, 1); | 	nv_wr32(device, NV03_PMC_INTR_EN_0, 1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_display_error_handler(struct drm_device *dev) | nv50_display_error_handler(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	u32 channels = (nv_rd32(dev, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	u32 channels = (nv_rd32(device, NV50_PDISPLAY_INTR_0) & 0x001f0000) >> 16; | ||||||
| 	u32 addr, data; | 	u32 addr, data; | ||||||
| 	int chid; | 	int chid; | ||||||
| 
 | 
 | ||||||
|  | @ -902,29 +906,31 @@ nv50_display_error_handler(struct drm_device *dev) | ||||||
| 		if (!(channels & (1 << chid))) | 		if (!(channels & (1 << chid))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); | 		nv_wr32(device, NV50_PDISPLAY_INTR_0, 0x00010000 << chid); | ||||||
| 		addr = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid)); | 		addr = nv_rd32(device, NV50_PDISPLAY_TRAPPED_ADDR(chid)); | ||||||
| 		data = nv_rd32(dev, NV50_PDISPLAY_TRAPPED_DATA(chid)); | 		data = nv_rd32(device, NV50_PDISPLAY_TRAPPED_DATA(chid)); | ||||||
| 		NV_ERROR(dev, "EvoCh %d Mthd 0x%04x Data 0x%08x " | 		NV_ERROR(drm, "EvoCh %d Mthd 0x%04x Data 0x%08x " | ||||||
| 			      "(0x%04x 0x%02x)\n", chid, | 			      "(0x%04x 0x%02x)\n", chid, | ||||||
| 			 addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); | 			 addr & 0xffc, data, addr >> 16, (addr >> 12) & 0xf); | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); | 		nv_wr32(device, NV50_PDISPLAY_TRAPPED_ADDR(chid), 0x90000000); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | void | ||||||
| nv50_display_isr(struct drm_device *dev) | nv50_display_intr(struct drm_device *dev) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	uint32_t delayed = 0; | 	uint32_t delayed = 0; | ||||||
| 
 | 
 | ||||||
| 	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { | 	while (nv_rd32(device, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) { | ||||||
| 		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0); | 		uint32_t intr0 = nv_rd32(device, NV50_PDISPLAY_INTR_0); | ||||||
| 		uint32_t intr1 = nv_rd32(dev, NV50_PDISPLAY_INTR_1); | 		uint32_t intr1 = nv_rd32(device, NV50_PDISPLAY_INTR_1); | ||||||
| 		uint32_t clock; | 		uint32_t clock; | ||||||
| 
 | 
 | ||||||
| 		NV_DEBUG_KMS(dev, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); | 		NV_DEBUG(drm, "PDISPLAY_INTR 0x%08x 0x%08x\n", intr0, intr1); | ||||||
| 
 | 
 | ||||||
| 		if (!intr0 && !(intr1 & ~delayed)) | 		if (!intr0 && !(intr1 & ~delayed)) | ||||||
| 			break; | 			break; | ||||||
|  | @ -943,21 +949,21 @@ nv50_display_isr(struct drm_device *dev) | ||||||
| 				  NV50_PDISPLAY_INTR_1_CLK_UNK20 | | 				  NV50_PDISPLAY_INTR_1_CLK_UNK20 | | ||||||
| 				  NV50_PDISPLAY_INTR_1_CLK_UNK40)); | 				  NV50_PDISPLAY_INTR_1_CLK_UNK40)); | ||||||
| 		if (clock) { | 		if (clock) { | ||||||
| 			nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); | 			nv_wr32(device, NV03_PMC_INTR_EN_0, 0); | ||||||
| 			tasklet_schedule(&disp->tasklet); | 			tasklet_schedule(&disp->tasklet); | ||||||
| 			delayed |= clock; | 			delayed |= clock; | ||||||
| 			intr1 &= ~clock; | 			intr1 &= ~clock; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (intr0) { | 		if (intr0) { | ||||||
| 			NV_ERROR(dev, "unknown PDISPLAY_INTR_0: 0x%08x\n", intr0); | 			NV_ERROR(drm, "unknown PDISPLAY_INTR_0: 0x%08x\n", intr0); | ||||||
| 			nv_wr32(dev, NV50_PDISPLAY_INTR_0, intr0); | 			nv_wr32(device, NV50_PDISPLAY_INTR_0, intr0); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (intr1) { | 		if (intr1) { | ||||||
| 			NV_ERROR(dev, | 			NV_ERROR(drm, | ||||||
| 				 "unknown PDISPLAY_INTR_1: 0x%08x\n", intr1); | 				 "unknown PDISPLAY_INTR_1: 0x%08x\n", intr1); | ||||||
| 			nv_wr32(dev, NV50_PDISPLAY_INTR_1, intr1); | 			nv_wr32(device, NV50_PDISPLAY_INTR_1, intr1); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -27,12 +27,9 @@ | ||||||
| #ifndef __NV50_DISPLAY_H__ | #ifndef __NV50_DISPLAY_H__ | ||||||
| #define __NV50_DISPLAY_H__ | #define __NV50_DISPLAY_H__ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "nouveau_display.h" | ||||||
| #include "drm.h" |  | ||||||
| #include "nouveau_drv.h" |  | ||||||
| #include "nouveau_dma.h" |  | ||||||
| #include "nouveau_reg.h" |  | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
|  | #include "nouveau_reg.h" | ||||||
| #include "nv50_evo.h" | #include "nv50_evo.h" | ||||||
| 
 | 
 | ||||||
| struct nv50_display_crtc { | struct nv50_display_crtc { | ||||||
|  | @ -64,8 +61,7 @@ struct nv50_display { | ||||||
| static inline struct nv50_display * | static inline struct nv50_display * | ||||||
| nv50_display(struct drm_device *dev) | nv50_display(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	return nouveau_display(dev)->priv; | ||||||
| 	return dev_priv->engine.display.priv; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int nv50_display_early_init(struct drm_device *dev); | int nv50_display_early_init(struct drm_device *dev); | ||||||
|  | @ -74,6 +70,7 @@ int nv50_display_create(struct drm_device *dev); | ||||||
| int nv50_display_init(struct drm_device *dev); | int nv50_display_init(struct drm_device *dev); | ||||||
| void nv50_display_fini(struct drm_device *dev); | void nv50_display_fini(struct drm_device *dev); | ||||||
| void nv50_display_destroy(struct drm_device *dev); | void nv50_display_destroy(struct drm_device *dev); | ||||||
|  | void nv50_display_intr(struct drm_device *); | ||||||
| int nv50_crtc_blank(struct nouveau_crtc *, bool blank); | int nv50_crtc_blank(struct nouveau_crtc *, bool blank); | ||||||
| int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); | int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); | ||||||
| 
 | 
 | ||||||
|  | @ -93,4 +90,17 @@ void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, | ||||||
| int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, | int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype, | ||||||
| 			 u64 base, u64 size, struct nouveau_gpuobj **); | 			 u64 base, u64 size, struct nouveau_gpuobj **); | ||||||
| 
 | 
 | ||||||
|  | int  nvd0_display_create(struct drm_device *); | ||||||
|  | void nvd0_display_destroy(struct drm_device *); | ||||||
|  | int  nvd0_display_init(struct drm_device *); | ||||||
|  | void nvd0_display_fini(struct drm_device *); | ||||||
|  | void nvd0_display_intr(struct drm_device *); | ||||||
|  | 
 | ||||||
|  | void nvd0_display_flip_stop(struct drm_crtc *); | ||||||
|  | int  nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, | ||||||
|  | 			    struct nouveau_channel *, u32 swap_interval); | ||||||
|  | 
 | ||||||
|  | struct nouveau_bo *nv50_display_crtc_sema(struct drm_device *, int head); | ||||||
|  | struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int head); | ||||||
|  | 
 | ||||||
| #endif /* __NV50_DISPLAY_H__ */ | #endif /* __NV50_DISPLAY_H__ */ | ||||||
|  |  | ||||||
|  | @ -24,10 +24,15 @@ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
|  | #include <core/gpuobj.h> | ||||||
|  | 
 | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | #include <subdev/fb.h> | ||||||
|  | 
 | ||||||
| static u32 | static u32 | ||||||
| nv50_evo_rd32(struct nouveau_object *object, u32 addr) | nv50_evo_rd32(struct nouveau_object *object, u32 addr) | ||||||
| { | { | ||||||
|  | @ -65,15 +70,15 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype, | ||||||
| 		    u64 base, u64 size, struct nouveau_gpuobj **pobj) | 		    u64 base, u64 size, struct nouveau_gpuobj **pobj) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = evo->fence; | 	struct drm_device *dev = evo->fence; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	u32 dmao = disp->dmao; | 	u32 dmao = disp->dmao; | ||||||
| 	u32 hash = disp->hash; | 	u32 hash = disp->hash; | ||||||
| 	u32 flags5; | 	u32 flags5; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset < 0xc0) { | 	if (nv_device(drm->device)->chipset < 0xc0) { | ||||||
| 		/* not supported on 0x50, specified in format mthd */ | 		/* not supported on 0x50, specified in format mthd */ | ||||||
| 		if (dev_priv->chipset == 0x50) | 		if (nv_device(drm->device)->chipset == 0x50) | ||||||
| 			memtype = 0; | 			memtype = 0; | ||||||
| 		flags5 = 0x00010000; | 		flags5 = 0x00010000; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -104,6 +109,7 @@ static int | ||||||
| nv50_evo_channel_new(struct drm_device *dev, int chid, | nv50_evo_channel_new(struct drm_device *dev, int chid, | ||||||
| 		     struct nouveau_channel **pevo) | 		     struct nouveau_channel **pevo) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	struct nouveau_channel *evo; | 	struct nouveau_channel *evo; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -113,6 +119,7 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	*pevo = evo; | 	*pevo = evo; | ||||||
| 
 | 
 | ||||||
|  | 	evo->drm = drm; | ||||||
| 	evo->handle = chid; | 	evo->handle = chid; | ||||||
| 	evo->fence = dev; | 	evo->fence = dev; | ||||||
| 	evo->user_get = 4; | 	evo->user_get = 4; | ||||||
|  | @ -123,14 +130,14 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, | ||||||
| 	if (ret == 0) | 	if (ret == 0) | ||||||
| 		ret = nouveau_bo_pin(evo->push.buffer, TTM_PL_FLAG_VRAM); | 		ret = nouveau_bo_pin(evo->push.buffer, TTM_PL_FLAG_VRAM); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "Error creating EVO DMA push buffer: %d\n", ret); | 		NV_ERROR(drm, "Error creating EVO DMA push buffer: %d\n", ret); | ||||||
| 		nv50_evo_channel_del(pevo); | 		nv50_evo_channel_del(pevo); | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_bo_map(evo->push.buffer); | 	ret = nouveau_bo_map(evo->push.buffer); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "Error mapping EVO DMA push buffer: %d\n", ret); | 		NV_ERROR(drm, "Error mapping EVO DMA push buffer: %d\n", ret); | ||||||
| 		nv50_evo_channel_del(pevo); | 		nv50_evo_channel_del(pevo); | ||||||
| 		return ret; | 		return ret; | ||||||
| 	} | 	} | ||||||
|  | @ -156,39 +163,40 @@ nv50_evo_channel_new(struct drm_device *dev, int chid, | ||||||
| static int | static int | ||||||
| nv50_evo_channel_init(struct nouveau_channel *evo) | nv50_evo_channel_init(struct nouveau_channel *evo) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = evo->fence; | 	struct nouveau_drm *drm = evo->drm; | ||||||
|  | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int id = evo->handle, ret, i; | 	int id = evo->handle, ret, i; | ||||||
| 	u64 pushbuf = evo->push.buffer->bo.offset; | 	u64 pushbuf = evo->push.buffer->bo.offset; | ||||||
| 	u32 tmp; | 	u32 tmp; | ||||||
| 
 | 
 | ||||||
| 	tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); | 	tmp = nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id)); | ||||||
| 	if ((tmp & 0x009f0000) == 0x00020000) | 	if ((tmp & 0x009f0000) == 0x00020000) | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); | 		nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00800000); | ||||||
| 
 | 
 | ||||||
| 	tmp = nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id)); | 	tmp = nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id)); | ||||||
| 	if ((tmp & 0x003f0000) == 0x00030000) | 	if ((tmp & 0x003f0000) == 0x00030000) | ||||||
| 		nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); | 		nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), tmp | 0x00600000); | ||||||
| 
 | 
 | ||||||
| 	/* initialise fifo */ | 	/* initialise fifo */ | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | | 	nv_wr32(device, NV50_PDISPLAY_EVO_DMA_CB(id), pushbuf >> 8 | | ||||||
| 		     NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | | 		     NV50_PDISPLAY_EVO_DMA_CB_LOCATION_VRAM | | ||||||
| 		     NV50_PDISPLAY_EVO_DMA_CB_VALID); | 		     NV50_PDISPLAY_EVO_DMA_CB_VALID); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); | 	nv_wr32(device, NV50_PDISPLAY_EVO_UNK2(id), 0x00010000); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_EVO_HASH_TAG(id), id); | 	nv_wr32(device, NV50_PDISPLAY_EVO_HASH_TAG(id), id); | ||||||
| 	nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, | 	nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), NV50_PDISPLAY_EVO_CTRL_DMA, | ||||||
| 		     NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); | 		     NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_USER_PUT(id), 0x00000000); | 	nv_wr32(device, NV50_PDISPLAY_USER_PUT(id), 0x00000000); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | | 	nv_wr32(device, NV50_PDISPLAY_EVO_CTRL(id), 0x01000003 | | ||||||
| 		     NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); | 		     NV50_PDISPLAY_EVO_CTRL_DMA_ENABLED); | ||||||
| 	if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { | 	if (!nv_wait(device, NV50_PDISPLAY_EVO_CTRL(id), 0x80000000, 0x00000000)) { | ||||||
| 		NV_ERROR(dev, "EvoCh %d init timeout: 0x%08x\n", id, | 		NV_ERROR(drm, "EvoCh %d init timeout: 0x%08x\n", id, | ||||||
| 			 nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); | 			 nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id))); | ||||||
| 		return -EBUSY; | 		return -EBUSY; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* enable error reporting on the channel */ | 	/* enable error reporting on the channel */ | ||||||
| 	nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id); | 	nv_mask(device, 0x610028, 0x00000000, 0x00010001 << id); | ||||||
| 
 | 
 | ||||||
| 	evo->dma.max = (4096/4) - 2; | 	evo->dma.max = (4096/4) - 2; | ||||||
| 	evo->dma.max &= ~7; | 	evo->dma.max &= ~7; | ||||||
|  | @ -209,16 +217,17 @@ nv50_evo_channel_init(struct nouveau_channel *evo) | ||||||
| static void | static void | ||||||
| nv50_evo_channel_fini(struct nouveau_channel *evo) | nv50_evo_channel_fini(struct nouveau_channel *evo) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = evo->fence; | 	struct nouveau_drm *drm = evo->drm; | ||||||
|  | 	struct nouveau_device *device = nv_device(drm->device); | ||||||
| 	int id = evo->handle; | 	int id = evo->handle; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x610028, 0x00010001 << id, 0x00000000); | 	nv_mask(device, 0x610028, 0x00010001 << id, 0x00000000); | ||||||
| 	nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); | 	nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), 0x00001010, 0x00001000); | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_INTR_0, (1 << id)); | 	nv_wr32(device, NV50_PDISPLAY_INTR_0, (1 << id)); | ||||||
| 	nv_mask(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); | 	nv_mask(device, NV50_PDISPLAY_EVO_CTRL(id), 0x00000003, 0x00000000); | ||||||
| 	if (!nv_wait(dev, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { | 	if (!nv_wait(device, NV50_PDISPLAY_EVO_CTRL(id), 0x001e0000, 0x00000000)) { | ||||||
| 		NV_ERROR(dev, "EvoCh %d takedown timeout: 0x%08x\n", id, | 		NV_ERROR(drm, "EvoCh %d takedown timeout: 0x%08x\n", id, | ||||||
| 			 nv_rd32(dev, NV50_PDISPLAY_EVO_CTRL(id))); | 			 nv_rd32(device, NV50_PDISPLAY_EVO_CTRL(id))); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -242,7 +251,8 @@ nv50_evo_destroy(struct drm_device *dev) | ||||||
| int | int | ||||||
| nv50_evo_create(struct drm_device *dev) | nv50_evo_create(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(drm->device); | ||||||
| 	struct nv50_display *disp = nv50_display(dev); | 	struct nv50_display *disp = nv50_display(dev); | ||||||
| 	struct nouveau_channel *evo; | 	struct nouveau_channel *evo; | ||||||
| 	int ret, i, j; | 	int ret, i, j; | ||||||
|  | @ -251,10 +261,10 @@ nv50_evo_create(struct drm_device *dev) | ||||||
| 	 * use this also as there's no per-channel support on the | 	 * use this also as there's no per-channel support on the | ||||||
| 	 * hardware | 	 * hardware | ||||||
| 	 */ | 	 */ | ||||||
| 	ret = nouveau_gpuobj_new(dev, NULL, 32768, 65536, | 	ret = nouveau_gpuobj_new(drm->device, NULL, 32768, 65536, | ||||||
| 				 NVOBJ_FLAG_ZERO_ALLOC, &disp->ramin); | 				 NVOBJ_FLAG_ZERO_ALLOC, &disp->ramin); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret); | 		NV_ERROR(drm, "Error allocating EVO channel memory: %d\n", ret); | ||||||
| 		goto err; | 		goto err; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -276,24 +286,24 @@ nv50_evo_create(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	/* create some default objects for the scanout memtypes we support */ | 	/* create some default objects for the scanout memtypes we support */ | ||||||
| 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, | 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000, | ||||||
| 				  0, nvfb_vram_size(dev), NULL); | 				  0, pfb->ram.size, NULL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, | 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000, | ||||||
| 				  0, nvfb_vram_size(dev), NULL); | 				  0, pfb->ram.size, NULL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | | 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 | | ||||||
| 				  (dev_priv->chipset < 0xc0 ? 0x7a : 0xfe), | 				  (nv_device(drm->device)->chipset < 0xc0 ? 0x7a : 0xfe), | ||||||
| 				  0, nvfb_vram_size(dev), NULL); | 				  0, pfb->ram.size, NULL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
| 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | | 	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 | | ||||||
| 				  (dev_priv->chipset < 0xc0 ? 0x70 : 0xfe), | 				  (nv_device(drm->device)->chipset < 0xc0 ? 0x70 : 0xfe), | ||||||
| 				  0, nvfb_vram_size(dev), NULL); | 				  0, pfb->ram.size, NULL); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto err; | 		goto err; | ||||||
| 
 | 
 | ||||||
|  | @ -328,21 +338,21 @@ nv50_evo_create(struct drm_device *dev) | ||||||
| 			goto err; | 			goto err; | ||||||
| 
 | 
 | ||||||
| 		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, | 		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000, | ||||||
| 					  0, nvfb_vram_size(dev), NULL); | 					  0, pfb->ram.size, NULL); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto err; | 			goto err; | ||||||
| 
 | 
 | ||||||
| 		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | | 		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 | | ||||||
| 					  (dev_priv->chipset < 0xc0 ? | 					  (nv_device(drm->device)->chipset < 0xc0 ? | ||||||
| 					  0x7a : 0xfe), | 					  0x7a : 0xfe), | ||||||
| 					  0, nvfb_vram_size(dev), NULL); | 					  0, pfb->ram.size, NULL); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto err; | 			goto err; | ||||||
| 
 | 
 | ||||||
| 		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | | 		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 | | ||||||
| 					  (dev_priv->chipset < 0xc0 ? | 					  (nv_device(drm->device)->chipset < 0xc0 ? | ||||||
| 					  0x70 : 0xfe), | 					  0x70 : 0xfe), | ||||||
| 					  0, nvfb_vram_size(dev), NULL); | 					  0, pfb->ram.size, NULL); | ||||||
| 		if (ret) | 		if (ret) | ||||||
| 			goto err; | 			goto err; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ int | ||||||
| nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +65,7 @@ int | ||||||
| nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -93,7 +93,7 @@ int | ||||||
| nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	uint32_t width, dwords, *data = (uint32_t *)image->data; | 	uint32_t width, dwords, *data = (uint32_t *)image->data; | ||||||
| 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); | 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); | ||||||
|  | @ -152,7 +152,7 @@ nv50_fbcon_accel_init(struct fb_info *info) | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; | 	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; | ||||||
| 	struct drm_device *dev = nfbdev->dev; | 	struct drm_device *dev = nfbdev->dev; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	struct nouveau_object *object; | 	struct nouveau_object *object; | ||||||
| 	int ret, format; | 	int ret, format; | ||||||
|  |  | ||||||
|  | @ -29,6 +29,8 @@ | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| 
 | 
 | ||||||
|  | #include "nv50_display.h" | ||||||
|  | 
 | ||||||
| struct nv50_fence_chan { | struct nv50_fence_chan { | ||||||
| 	struct nouveau_fence_chan base; | 	struct nouveau_fence_chan base; | ||||||
| }; | }; | ||||||
|  | @ -43,6 +45,7 @@ struct nv50_fence_priv { | ||||||
| static int | static int | ||||||
| nv50_fence_context_new(struct nouveau_channel *chan) | nv50_fence_context_new(struct nouveau_channel *chan) | ||||||
| { | { | ||||||
|  | 	struct drm_device *dev = chan->drm->dev; | ||||||
| 	struct nv50_fence_priv *priv = chan->drm->fence; | 	struct nv50_fence_priv *priv = chan->drm->fence; | ||||||
| 	struct nv50_fence_chan *fctx; | 	struct nv50_fence_chan *fctx; | ||||||
| 	struct ttm_mem_reg *mem = &priv->bo->bo.mem; | 	struct ttm_mem_reg *mem = &priv->bo->bo.mem; | ||||||
|  | @ -66,8 +69,8 @@ nv50_fence_context_new(struct nouveau_channel *chan) | ||||||
| 				 &object); | 				 &object); | ||||||
| 
 | 
 | ||||||
| 	/* dma objects for display sync channel semaphore blocks */ | 	/* dma objects for display sync channel semaphore blocks */ | ||||||
| 	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { | 	for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { | ||||||
| 		struct nouveau_bo *bo = nv50sema(chan->drm->dev, i); | 		struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); | ||||||
| 
 | 
 | ||||||
| 		ret = nouveau_object_new(nv_object(chan->cli), chan->handle, | 		ret = nouveau_object_new(nv_object(chan->cli), chan->handle, | ||||||
| 					 NvEvoSema0 + i, 0x003d, | 					 NvEvoSema0 + i, 0x003d, | ||||||
|  |  | ||||||
|  | @ -23,12 +23,19 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include <nouveau_bios.h> | #include "nouveau_bios.h" | ||||||
| #include "nouveau_hw.h" | #include "nouveau_hw.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| #include "nouveau_hwsq.h" | #include "nouveau_hwsq.h" | ||||||
| 
 | 
 | ||||||
|  | #include "nv50_display.h" | ||||||
|  | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | #include <subdev/fb.h> | ||||||
|  | 
 | ||||||
| enum clk_src { | enum clk_src { | ||||||
| 	clk_src_crystal, | 	clk_src_crystal, | ||||||
| 	clk_src_href, | 	clk_src_href, | ||||||
|  | @ -48,19 +55,20 @@ static u32 read_clk(struct drm_device *, enum clk_src); | ||||||
| static u32 | static u32 | ||||||
| read_div(struct drm_device *dev) | read_div(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 
 | 
 | ||||||
| 	switch (dev_priv->chipset) { | 	switch (nv_device(drm->device)->chipset) { | ||||||
| 	case 0x50: /* it exists, but only has bit 31, not the dividers.. */ | 	case 0x50: /* it exists, but only has bit 31, not the dividers.. */ | ||||||
| 	case 0x84: | 	case 0x84: | ||||||
| 	case 0x86: | 	case 0x86: | ||||||
| 	case 0x98: | 	case 0x98: | ||||||
| 	case 0xa0: | 	case 0xa0: | ||||||
| 		return nv_rd32(dev, 0x004700); | 		return nv_rd32(device, 0x004700); | ||||||
| 	case 0x92: | 	case 0x92: | ||||||
| 	case 0x94: | 	case 0x94: | ||||||
| 	case 0x96: | 	case 0x96: | ||||||
| 		return nv_rd32(dev, 0x004800); | 		return nv_rd32(device, 0x004800); | ||||||
| 	default: | 	default: | ||||||
| 		return 0x00000000; | 		return 0x00000000; | ||||||
| 	} | 	} | ||||||
|  | @ -69,12 +77,13 @@ read_div(struct drm_device *dev) | ||||||
| static u32 | static u32 | ||||||
| read_pll_src(struct drm_device *dev, u32 base) | read_pll_src(struct drm_device *dev, u32 base) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u32 coef, ref = read_clk(dev, clk_src_crystal); | 	u32 coef, ref = read_clk(dev, clk_src_crystal); | ||||||
| 	u32 rsel = nv_rd32(dev, 0x00e18c); | 	u32 rsel = nv_rd32(device, 0x00e18c); | ||||||
| 	int P, N, M, id; | 	int P, N, M, id; | ||||||
| 
 | 
 | ||||||
| 	switch (dev_priv->chipset) { | 	switch (nv_device(drm->device)->chipset) { | ||||||
| 	case 0x50: | 	case 0x50: | ||||||
| 	case 0xa0: | 	case 0xa0: | ||||||
| 		switch (base) { | 		switch (base) { | ||||||
|  | @ -83,11 +92,11 @@ read_pll_src(struct drm_device *dev, u32 base) | ||||||
| 		case 0x4008: id = !!(rsel & 0x00000008); break; | 		case 0x4008: id = !!(rsel & 0x00000008); break; | ||||||
| 		case 0x4030: id = 0; break; | 		case 0x4030: id = 0; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); | 			NV_ERROR(drm, "ref: bad pll 0x%06x\n", base); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		coef = nv_rd32(dev, 0x00e81c + (id * 0x0c)); | 		coef = nv_rd32(device, 0x00e81c + (id * 0x0c)); | ||||||
| 		ref *=  (coef & 0x01000000) ? 2 : 4; | 		ref *=  (coef & 0x01000000) ? 2 : 4; | ||||||
| 		P    =  (coef & 0x00070000) >> 16; | 		P    =  (coef & 0x00070000) >> 16; | ||||||
| 		N    = ((coef & 0x0000ff00) >> 8) + 1; | 		N    = ((coef & 0x0000ff00) >> 8) + 1; | ||||||
|  | @ -96,7 +105,7 @@ read_pll_src(struct drm_device *dev, u32 base) | ||||||
| 	case 0x84: | 	case 0x84: | ||||||
| 	case 0x86: | 	case 0x86: | ||||||
| 	case 0x92: | 	case 0x92: | ||||||
| 		coef = nv_rd32(dev, 0x00e81c); | 		coef = nv_rd32(device, 0x00e81c); | ||||||
| 		P    = (coef & 0x00070000) >> 16; | 		P    = (coef & 0x00070000) >> 16; | ||||||
| 		N    = (coef & 0x0000ff00) >> 8; | 		N    = (coef & 0x0000ff00) >> 8; | ||||||
| 		M    = (coef & 0x000000ff) >> 0; | 		M    = (coef & 0x000000ff) >> 0; | ||||||
|  | @ -104,14 +113,14 @@ read_pll_src(struct drm_device *dev, u32 base) | ||||||
| 	case 0x94: | 	case 0x94: | ||||||
| 	case 0x96: | 	case 0x96: | ||||||
| 	case 0x98: | 	case 0x98: | ||||||
| 		rsel = nv_rd32(dev, 0x00c050); | 		rsel = nv_rd32(device, 0x00c050); | ||||||
| 		switch (base) { | 		switch (base) { | ||||||
| 		case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; | 		case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; | ||||||
| 		case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; | 		case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; | ||||||
| 		case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; | 		case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; | ||||||
| 		case 0x4030: rsel = 3; break; | 		case 0x4030: rsel = 3; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); | 			NV_ERROR(drm, "ref: bad pll 0x%06x\n", base); | ||||||
| 			return 0; | 			return 0; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -122,8 +131,8 @@ read_pll_src(struct drm_device *dev, u32 base) | ||||||
| 		case 3: id = 0; break; | 		case 3: id = 0; break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		coef =  nv_rd32(dev, 0x00e81c + (id * 0x28)); | 		coef =  nv_rd32(device, 0x00e81c + (id * 0x28)); | ||||||
| 		P    = (nv_rd32(dev, 0x00e824 + (id * 0x28)) >> 16) & 7; | 		P    = (nv_rd32(device, 0x00e824 + (id * 0x28)) >> 16) & 7; | ||||||
| 		P   += (coef & 0x00070000) >> 16; | 		P   += (coef & 0x00070000) >> 16; | ||||||
| 		N    = (coef & 0x0000ff00) >> 8; | 		N    = (coef & 0x0000ff00) >> 8; | ||||||
| 		M    = (coef & 0x000000ff) >> 0; | 		M    = (coef & 0x000000ff) >> 0; | ||||||
|  | @ -140,7 +149,9 @@ read_pll_src(struct drm_device *dev, u32 base) | ||||||
| static u32 | static u32 | ||||||
| read_pll_ref(struct drm_device *dev, u32 base) | read_pll_ref(struct drm_device *dev, u32 base) | ||||||
| { | { | ||||||
| 	u32 src, mast = nv_rd32(dev, 0x00c040); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	u32 src, mast = nv_rd32(device, 0x00c040); | ||||||
| 
 | 
 | ||||||
| 	switch (base) { | 	switch (base) { | ||||||
| 	case 0x004028: | 	case 0x004028: | ||||||
|  | @ -158,7 +169,7 @@ read_pll_ref(struct drm_device *dev, u32 base) | ||||||
| 	case 0x00e810: | 	case 0x00e810: | ||||||
| 		return read_clk(dev, clk_src_crystal); | 		return read_clk(dev, clk_src_crystal); | ||||||
| 	default: | 	default: | ||||||
| 		NV_ERROR(dev, "bad pll 0x%06x\n", base); | 		NV_ERROR(drm, "bad pll 0x%06x\n", base); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -170,17 +181,18 @@ read_pll_ref(struct drm_device *dev, u32 base) | ||||||
| static u32 | static u32 | ||||||
| read_pll(struct drm_device *dev, u32 base) | read_pll(struct drm_device *dev, u32 base) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 mast = nv_rd32(dev, 0x00c040); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u32 ctrl = nv_rd32(dev, base + 0); | 	u32 mast = nv_rd32(device, 0x00c040); | ||||||
| 	u32 coef = nv_rd32(dev, base + 4); | 	u32 ctrl = nv_rd32(device, base + 0); | ||||||
|  | 	u32 coef = nv_rd32(device, base + 4); | ||||||
| 	u32 ref = read_pll_ref(dev, base); | 	u32 ref = read_pll_ref(dev, base); | ||||||
| 	u32 clk = 0; | 	u32 clk = 0; | ||||||
| 	int N1, N2, M1, M2; | 	int N1, N2, M1, M2; | ||||||
| 
 | 
 | ||||||
| 	if (base == 0x004028 && (mast & 0x00100000)) { | 	if (base == 0x004028 && (mast & 0x00100000)) { | ||||||
| 		/* wtf, appears to only disable post-divider on nva0 */ | 		/* wtf, appears to only disable post-divider on nva0 */ | ||||||
| 		if (dev_priv->chipset != 0xa0) | 		if (nv_device(drm->device)->chipset != 0xa0) | ||||||
| 			return read_clk(dev, clk_src_dom6); | 			return read_clk(dev, clk_src_dom6); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -204,13 +216,14 @@ read_pll(struct drm_device *dev, u32 base) | ||||||
| static u32 | static u32 | ||||||
| read_clk(struct drm_device *dev, enum clk_src src) | read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 mast = nv_rd32(dev, 0x00c040); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	u32 mast = nv_rd32(device, 0x00c040); | ||||||
| 	u32 P = 0; | 	u32 P = 0; | ||||||
| 
 | 
 | ||||||
| 	switch (src) { | 	switch (src) { | ||||||
| 	case clk_src_crystal: | 	case clk_src_crystal: | ||||||
| 		return dev_priv->crystal; | 		return device->crystal; | ||||||
| 	case clk_src_href: | 	case clk_src_href: | ||||||
| 		return 100000; /* PCIE reference clock */ | 		return 100000; /* PCIE reference clock */ | ||||||
| 	case clk_src_hclk: | 	case clk_src_hclk: | ||||||
|  | @ -229,7 +242,7 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		break; | 		break; | ||||||
| 	case clk_src_nvclk: | 	case clk_src_nvclk: | ||||||
| 		if (!(mast & 0x00100000)) | 		if (!(mast & 0x00100000)) | ||||||
| 			P = (nv_rd32(dev, 0x004028) & 0x00070000) >> 16; | 			P = (nv_rd32(device, 0x004028) & 0x00070000) >> 16; | ||||||
| 		switch (mast & 0x00000003) { | 		switch (mast & 0x00000003) { | ||||||
| 		case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; | 		case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; | ||||||
| 		case 0x00000001: return read_clk(dev, clk_src_dom6); | 		case 0x00000001: return read_clk(dev, clk_src_dom6); | ||||||
|  | @ -238,7 +251,7 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case clk_src_sclk: | 	case clk_src_sclk: | ||||||
| 		P = (nv_rd32(dev, 0x004020) & 0x00070000) >> 16; | 		P = (nv_rd32(device, 0x004020) & 0x00070000) >> 16; | ||||||
| 		switch (mast & 0x00000030) { | 		switch (mast & 0x00000030) { | ||||||
| 		case 0x00000000: | 		case 0x00000000: | ||||||
| 			if (mast & 0x00000080) | 			if (mast & 0x00000080) | ||||||
|  | @ -250,8 +263,8 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case clk_src_mclk: | 	case clk_src_mclk: | ||||||
| 		P = (nv_rd32(dev, 0x004008) & 0x00070000) >> 16; | 		P = (nv_rd32(device, 0x004008) & 0x00070000) >> 16; | ||||||
| 		if (nv_rd32(dev, 0x004008) & 0x00000200) { | 		if (nv_rd32(device, 0x004008) & 0x00000200) { | ||||||
| 			switch (mast & 0x0000c000) { | 			switch (mast & 0x0000c000) { | ||||||
| 			case 0x00000000: | 			case 0x00000000: | ||||||
| 				return read_clk(dev, clk_src_crystal) >> P; | 				return read_clk(dev, clk_src_crystal) >> P; | ||||||
|  | @ -265,7 +278,7 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		break; | 		break; | ||||||
| 	case clk_src_vdec: | 	case clk_src_vdec: | ||||||
| 		P = (read_div(dev) & 0x00000700) >> 8; | 		P = (read_div(dev) & 0x00000700) >> 8; | ||||||
| 		switch (dev_priv->chipset) { | 		switch (nv_device(drm->device)->chipset) { | ||||||
| 		case 0x84: | 		case 0x84: | ||||||
| 		case 0x86: | 		case 0x86: | ||||||
| 		case 0x92: | 		case 0x92: | ||||||
|  | @ -274,7 +287,7 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		case 0xa0: | 		case 0xa0: | ||||||
| 			switch (mast & 0x00000c00) { | 			switch (mast & 0x00000c00) { | ||||||
| 			case 0x00000000: | 			case 0x00000000: | ||||||
| 				if (dev_priv->chipset == 0xa0) /* wtf?? */ | 				if (nv_device(drm->device)->chipset == 0xa0) /* wtf?? */ | ||||||
| 					return read_clk(dev, clk_src_nvclk) >> P; | 					return read_clk(dev, clk_src_nvclk) >> P; | ||||||
| 				return read_clk(dev, clk_src_crystal) >> P; | 				return read_clk(dev, clk_src_crystal) >> P; | ||||||
| 			case 0x00000400: | 			case 0x00000400: | ||||||
|  | @ -302,7 +315,7 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case clk_src_dom6: | 	case clk_src_dom6: | ||||||
| 		switch (dev_priv->chipset) { | 		switch (nv_device(drm->device)->chipset) { | ||||||
| 		case 0x50: | 		case 0x50: | ||||||
| 		case 0xa0: | 		case 0xa0: | ||||||
| 			return read_pll(dev, 0x00e810) >> 2; | 			return read_pll(dev, 0x00e810) >> 2; | ||||||
|  | @ -328,22 +341,22 @@ read_clk(struct drm_device *dev, enum clk_src src) | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG(dev, "unknown clock source %d 0x%08x\n", src, mast); | 	NV_DEBUG(drm, "unknown clock source %d 0x%08x\n", src, mast); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	if (dev_priv->chipset == 0xaa || | 	if (nv_device(drm->device)->chipset == 0xaa || | ||||||
| 	    dev_priv->chipset == 0xac) | 	    nv_device(drm->device)->chipset == 0xac) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	perflvl->core   = read_clk(dev, clk_src_nvclk); | 	perflvl->core   = read_clk(dev, clk_src_nvclk); | ||||||
| 	perflvl->shader = read_clk(dev, clk_src_sclk); | 	perflvl->shader = read_clk(dev, clk_src_sclk); | ||||||
| 	perflvl->memory = read_clk(dev, clk_src_mclk); | 	perflvl->memory = read_clk(dev, clk_src_mclk); | ||||||
| 	if (dev_priv->chipset != 0x50) { | 	if (nv_device(drm->device)->chipset != 0x50) { | ||||||
| 		perflvl->vdec = read_clk(dev, clk_src_vdec); | 		perflvl->vdec = read_clk(dev, clk_src_vdec); | ||||||
| 		perflvl->dom6 = read_clk(dev, clk_src_dom6); | 		perflvl->dom6 = read_clk(dev, clk_src_dom6); | ||||||
| 	} | 	} | ||||||
|  | @ -365,10 +378,13 @@ static u32 | ||||||
| calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | ||||||
| 	 u32 clk, int *N1, int *M1, int *log2P) | 	 u32 clk, int *N1, int *M1, int *log2P) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
|  | 	struct nouveau_clock *pclk = nouveau_clock(device); | ||||||
| 	struct nouveau_pll_vals coef; | 	struct nouveau_pll_vals coef; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	ret = get_pll_limits(dev, reg, pll); | 	ret = nvbios_pll_parse(bios, reg, pll); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
|  | @ -377,7 +393,7 @@ calc_pll(struct drm_device *dev, u32 reg, struct nvbios_pll *pll, | ||||||
| 	if (!pll->refclk) | 	if (!pll->refclk) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); | 	ret = pclk->pll_calc(pclk, pll, clk, &coef); | ||||||
| 	if (ret == 0) | 	if (ret == 0) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
|  | @ -460,26 +476,29 @@ mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) | ||||||
| static u32 | static u32 | ||||||
| mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	if (mr <= 1) | 	if (mr <= 1) | ||||||
| 		return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4)); | 		return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4)); | ||||||
| 	if (mr <= 3) | 	if (mr <= 3) | ||||||
| 		return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4)); | 		return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4)); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
| 	struct nv50_pm_state *info = exec->priv; | 	struct nv50_pm_state *info = exec->priv; | ||||||
| 	struct hwsq_ucode *hwsq = &info->mclk_hwsq; | 	struct hwsq_ucode *hwsq = &info->mclk_hwsq; | ||||||
| 
 | 
 | ||||||
| 	if (mr <= 1) { | 	if (mr <= 1) { | ||||||
| 		if (nvfb_vram_rank_B(exec->dev)) | 		if (pfb->ram.ranks > 1) | ||||||
| 			hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); | 			hwsq_wr32(hwsq, 0x1002c8 + ((mr - 0) * 4), data); | ||||||
| 		hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); | 		hwsq_wr32(hwsq, 0x1002c0 + ((mr - 0) * 4), data); | ||||||
| 	} else | 	} else | ||||||
| 	if (mr <= 3) { | 	if (mr <= 3) { | ||||||
| 		if (nvfb_vram_rank_B(exec->dev)) | 		if (pfb->ram.ranks > 1) | ||||||
| 			hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); | 			hwsq_wr32(hwsq, 0x1002e8 + ((mr - 2) * 4), data); | ||||||
| 		hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); | 		hwsq_wr32(hwsq, 0x1002e0 + ((mr - 2) * 4), data); | ||||||
| 	} | 	} | ||||||
|  | @ -488,11 +507,12 @@ mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | ||||||
| static void | static void | ||||||
| mclk_clock_set(struct nouveau_mem_exec_func *exec) | mclk_clock_set(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	struct nv50_pm_state *info = exec->priv; | 	struct nv50_pm_state *info = exec->priv; | ||||||
| 	struct hwsq_ucode *hwsq = &info->mclk_hwsq; | 	struct hwsq_ucode *hwsq = &info->mclk_hwsq; | ||||||
| 	u32 ctrl = nv_rd32(exec->dev, 0x004008); | 	u32 ctrl = nv_rd32(device, 0x004008); | ||||||
| 
 | 
 | ||||||
| 	info->mmast = nv_rd32(exec->dev, 0x00c040); | 	info->mmast = nv_rd32(device, 0x00c040); | ||||||
| 	info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */ | 	info->mmast &= ~0xc0000000; /* get MCLK_2 from HREF */ | ||||||
| 	info->mmast |=  0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */ | 	info->mmast |=  0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */ | ||||||
| 
 | 
 | ||||||
|  | @ -506,7 +526,7 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec) | ||||||
| static void | static void | ||||||
| mclk_timing_set(struct nouveau_mem_exec_func *exec) | mclk_timing_set(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = exec->dev; | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	struct nv50_pm_state *info = exec->priv; | 	struct nv50_pm_state *info = exec->priv; | ||||||
| 	struct nouveau_pm_level *perflvl = info->perflvl; | 	struct nouveau_pm_level *perflvl = info->perflvl; | ||||||
| 	struct hwsq_ucode *hwsq = &info->mclk_hwsq; | 	struct hwsq_ucode *hwsq = &info->mclk_hwsq; | ||||||
|  | @ -514,7 +534,7 @@ mclk_timing_set(struct nouveau_mem_exec_func *exec) | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 9; i++) { | 	for (i = 0; i < 9; i++) { | ||||||
| 		u32 reg = 0x100220 + (i * 4); | 		u32 reg = 0x100220 + (i * 4); | ||||||
| 		u32 val = nv_rd32(dev, reg); | 		u32 val = nv_rd32(device, reg); | ||||||
| 		if (val != perflvl->timing.reg[i]) | 		if (val != perflvl->timing.reg[i]) | ||||||
| 			hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]); | 			hwsq_wr32(hwsq, reg, perflvl->timing.reg[i]); | ||||||
| 	} | 	} | ||||||
|  | @ -524,7 +544,8 @@ static int | ||||||
| calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 	  struct nv50_pm_state *info) | 	  struct nv50_pm_state *info) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 crtc_mask = nv50_display_active_crtcs(dev); | 	u32 crtc_mask = nv50_display_active_crtcs(dev); | ||||||
| 	struct nouveau_mem_exec_func exec = { | 	struct nouveau_mem_exec_func exec = { | ||||||
| 		.dev = dev, | 		.dev = dev, | ||||||
|  | @ -545,7 +566,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	/* use pcie refclock if possible, otherwise use mpll */ | 	/* use pcie refclock if possible, otherwise use mpll */ | ||||||
| 	info->mctrl  = nv_rd32(dev, 0x004008); | 	info->mctrl  = nv_rd32(device, 0x004008); | ||||||
| 	info->mctrl &= ~0x81ff0200; | 	info->mctrl &= ~0x81ff0200; | ||||||
| 	if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { | 	if (clk_same(perflvl->memory, read_clk(dev, clk_src_href))) { | ||||||
| 		info->mctrl |= 0x00000200 | (pll.bias_p << 19); | 		info->mctrl |= 0x00000200 | (pll.bias_p << 19); | ||||||
|  | @ -565,7 +586,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 		hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */ | 		hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */ | ||||||
| 		hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */ | 		hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */ | ||||||
| 	} | 	} | ||||||
| 	if (dev_priv->chipset >= 0x92) | 	if (nv_device(drm->device)->chipset >= 0x92) | ||||||
| 		hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */ | 		hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */ | ||||||
| 	hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ | 	hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ | ||||||
| 	hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ | 	hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ | ||||||
|  | @ -576,7 +597,7 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| 
 | 
 | ||||||
| 	hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ | 	hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ | ||||||
| 	hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ | 	hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ | ||||||
| 	if (dev_priv->chipset >= 0x92) | 	if (nv_device(drm->device)->chipset >= 0x92) | ||||||
| 		hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */ | 		hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */ | ||||||
| 	hwsq_fini(hwsq); | 	hwsq_fini(hwsq); | ||||||
| 	return 0; | 	return 0; | ||||||
|  | @ -585,7 +606,8 @@ calc_mclk(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||||||
| void * | void * | ||||||
| nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nv50_pm_state *info; | 	struct nv50_pm_state *info; | ||||||
| 	struct hwsq_ucode *hwsq; | 	struct hwsq_ucode *hwsq; | ||||||
| 	struct nvbios_pll pll; | 	struct nvbios_pll pll; | ||||||
|  | @ -593,8 +615,8 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	int clk, ret = -EINVAL; | 	int clk, ret = -EINVAL; | ||||||
| 	int N, M, P1, P2; | 	int N, M, P1, P2; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset == 0xaa || | 	if (nv_device(drm->device)->chipset == 0xaa || | ||||||
| 	    dev_priv->chipset == 0xac) | 	    nv_device(drm->device)->chipset == 0xac) | ||||||
| 		return ERR_PTR(-ENODEV); | 		return ERR_PTR(-ENODEV); | ||||||
| 
 | 
 | ||||||
| 	info = kmalloc(sizeof(*info), GFP_KERNEL); | 	info = kmalloc(sizeof(*info), GFP_KERNEL); | ||||||
|  | @ -643,7 +665,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 		clk = calc_div(perflvl->core, perflvl->vdec, &P1); | 		clk = calc_div(perflvl->core, perflvl->vdec, &P1); | ||||||
| 
 | 
 | ||||||
| 		/* see how close we can get using xpll/hclk as a source */ | 		/* see how close we can get using xpll/hclk as a source */ | ||||||
| 		if (dev_priv->chipset != 0x98) | 		if (nv_device(drm->device)->chipset != 0x98) | ||||||
| 			out = read_pll(dev, 0x004030); | 			out = read_pll(dev, 0x004030); | ||||||
| 		else | 		else | ||||||
| 			out = read_clk(dev, clk_src_hclkm3d2); | 			out = read_clk(dev, clk_src_hclkm3d2); | ||||||
|  | @ -652,7 +674,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 		/* select whichever gets us closest */ | 		/* select whichever gets us closest */ | ||||||
| 		if (abs((int)perflvl->vdec - clk) <= | 		if (abs((int)perflvl->vdec - clk) <= | ||||||
| 		    abs((int)perflvl->vdec - out)) { | 		    abs((int)perflvl->vdec - out)) { | ||||||
| 			if (dev_priv->chipset != 0x98) | 			if (nv_device(drm->device)->chipset != 0x98) | ||||||
| 				mast |= 0x00000c00; | 				mast |= 0x00000c00; | ||||||
| 			divs |= P1 << 8; | 			divs |= P1 << 8; | ||||||
| 		} else { | 		} else { | ||||||
|  | @ -680,7 +702,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* vdec/dom6: complete switch to new clocks */ | 	/* vdec/dom6: complete switch to new clocks */ | ||||||
| 	switch (dev_priv->chipset) { | 	switch (nv_device(drm->device)->chipset) { | ||||||
| 	case 0x92: | 	case 0x92: | ||||||
| 	case 0x94: | 	case 0x94: | ||||||
| 	case 0x96: | 	case 0x96: | ||||||
|  | @ -696,7 +718,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	/* core/shader: make sure sclk/nvclk are disconnected from their
 | 	/* core/shader: make sure sclk/nvclk are disconnected from their
 | ||||||
| 	 * PLLs (nvclk to dom6, sclk to hclk) | 	 * PLLs (nvclk to dom6, sclk to hclk) | ||||||
| 	 */ | 	 */ | ||||||
| 	if (dev_priv->chipset < 0x92) | 	if (nv_device(drm->device)->chipset < 0x92) | ||||||
| 		mast = (mast & ~0x001000b0) | 0x00100080; | 		mast = (mast & ~0x001000b0) | 0x00100080; | ||||||
| 	else | 	else | ||||||
| 		mast = (mast & ~0x000000b3) | 0x00000081; | 		mast = (mast & ~0x000000b3) | 0x00000081; | ||||||
|  | @ -708,7 +730,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	if (clk == 0) | 	if (clk == 0) | ||||||
| 		goto error; | 		goto error; | ||||||
| 
 | 
 | ||||||
| 	ctrl  = nv_rd32(dev, 0x004028) & ~0xc03f0100; | 	ctrl  = nv_rd32(device, 0x004028) & ~0xc03f0100; | ||||||
| 	mast &= ~0x00100000; | 	mast &= ~0x00100000; | ||||||
| 	mast |= 3; | 	mast |= 3; | ||||||
| 
 | 
 | ||||||
|  | @ -721,7 +743,7 @@ nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	 * cases will be handled by tying to nvclk, but it's possible there's | 	 * cases will be handled by tying to nvclk, but it's possible there's | ||||||
| 	 * corners | 	 * corners | ||||||
| 	 */ | 	 */ | ||||||
| 	ctrl = nv_rd32(dev, 0x004020) & ~0xc03f0100; | 	ctrl = nv_rd32(device, 0x004020) & ~0xc03f0100; | ||||||
| 
 | 
 | ||||||
| 	if (P1-- && perflvl->shader == (perflvl->core << 1)) { | 	if (P1-- && perflvl->shader == (perflvl->core << 1)) { | ||||||
| 		hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); | 		hwsq_wr32(hwsq, 0x004020, (P1 << 19) | (P1 << 16) | ctrl); | ||||||
|  | @ -750,11 +772,12 @@ error: | ||||||
| static int | static int | ||||||
| prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) | prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u32 hwsq_data, hwsq_kick; | 	u32 hwsq_data, hwsq_kick; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset < 0x94) { | 	if (nv_device(drm->device)->chipset < 0x94) { | ||||||
| 		hwsq_data = 0x001400; | 		hwsq_data = 0x001400; | ||||||
| 		hwsq_kick = 0x00000003; | 		hwsq_kick = 0x00000003; | ||||||
| 	} else { | 	} else { | ||||||
|  | @ -762,22 +785,22 @@ prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) | ||||||
| 		hwsq_kick = 0x00000001; | 		hwsq_kick = 0x00000001; | ||||||
| 	} | 	} | ||||||
| 	/* upload hwsq ucode */ | 	/* upload hwsq ucode */ | ||||||
| 	nv_mask(dev, 0x001098, 0x00000008, 0x00000000); | 	nv_mask(device, 0x001098, 0x00000008, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x001304, 0x00000000); | 	nv_wr32(device, 0x001304, 0x00000000); | ||||||
| 	if (dev_priv->chipset >= 0x92) | 	if (nv_device(drm->device)->chipset >= 0x92) | ||||||
| 		nv_wr32(dev, 0x001318, 0x00000000); | 		nv_wr32(device, 0x001318, 0x00000000); | ||||||
| 	for (i = 0; i < hwsq->len / 4; i++) | 	for (i = 0; i < hwsq->len / 4; i++) | ||||||
| 		nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]); | 		nv_wr32(device, hwsq_data + (i * 4), hwsq->ptr.u32[i]); | ||||||
| 	nv_mask(dev, 0x001098, 0x00000018, 0x00000018); | 	nv_mask(device, 0x001098, 0x00000018, 0x00000018); | ||||||
| 
 | 
 | ||||||
| 	/* launch, and wait for completion */ | 	/* launch, and wait for completion */ | ||||||
| 	nv_wr32(dev, 0x00130c, hwsq_kick); | 	nv_wr32(device, 0x00130c, hwsq_kick); | ||||||
| 	if (!nv_wait(dev, 0x001308, 0x00000100, 0x00000000)) { | 	if (!nv_wait(device, 0x001308, 0x00000100, 0x00000000)) { | ||||||
| 		NV_ERROR(dev, "hwsq ucode exec timed out\n"); | 		NV_ERROR(drm, "hwsq ucode exec timed out\n"); | ||||||
| 		NV_ERROR(dev, "0x001308: 0x%08x\n", nv_rd32(dev, 0x001308)); | 		NV_ERROR(drm, "0x001308: 0x%08x\n", nv_rd32(device, 0x001308)); | ||||||
| 		for (i = 0; i < hwsq->len / 4; i++) { | 		for (i = 0; i < hwsq->len / 4; i++) { | ||||||
| 			NV_ERROR(dev, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), | 			NV_ERROR(drm, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), | ||||||
| 				 nv_rd32(dev, 0x001400 + (i * 4))); | 				 nv_rd32(device, 0x001400 + (i * 4))); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return -EIO; | 		return -EIO; | ||||||
|  | @ -789,20 +812,22 @@ prog_hwsq(struct drm_device *dev, struct hwsq_ucode *hwsq) | ||||||
| int | int | ||||||
| nv50_pm_clocks_set(struct drm_device *dev, void *data) | nv50_pm_clocks_set(struct drm_device *dev, void *data) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nv50_pm_state *info = data; | 	struct nv50_pm_state *info = data; | ||||||
| 	struct bit_entry M; | 	struct bit_entry M; | ||||||
| 	int ret = -EBUSY; | 	int ret = -EBUSY; | ||||||
| 
 | 
 | ||||||
| 	/* halt and idle execution engines */ | 	/* halt and idle execution engines */ | ||||||
| 	nv_mask(dev, 0x002504, 0x00000001, 0x00000001); | 	nv_mask(device, 0x002504, 0x00000001, 0x00000001); | ||||||
| 	if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) | 	if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010)) | ||||||
| 		goto resume; | 		goto resume; | ||||||
| 	if (!nv_wait(dev, 0x00251c, 0x0000003f, 0x0000003f)) | 	if (!nv_wait(device, 0x00251c, 0x0000003f, 0x0000003f)) | ||||||
| 		goto resume; | 		goto resume; | ||||||
| 
 | 
 | ||||||
| 	/* program memory clock, if necessary - must come before engine clock
 | 	/* program memory clock, if necessary - must come before engine clock
 | ||||||
| 	 * reprogramming due to how we construct the hwsq scripts in pre() | 	 * reprogramming due to how we construct the hwsq scripts in pre() | ||||||
| 	 */ | 	 */ | ||||||
|  | #define nouveau_bios_init_exec(a,b) nouveau_bios_run_init_table((a), (b), NULL, 0) | ||||||
| 	if (info->mclk_hwsq.len) { | 	if (info->mclk_hwsq.len) { | ||||||
| 		/* execute some scripts that do ??? from the vbios.. */ | 		/* execute some scripts that do ??? from the vbios.. */ | ||||||
| 		if (!bit_table(dev, 'M', &M) && M.version == 1) { | 		if (!bit_table(dev, 'M', &M) && M.version == 1) { | ||||||
|  | @ -824,7 +849,7 @@ nv50_pm_clocks_set(struct drm_device *dev, void *data) | ||||||
| 	ret = prog_hwsq(dev, &info->eclk_hwsq); | 	ret = prog_hwsq(dev, &info->eclk_hwsq); | ||||||
| 
 | 
 | ||||||
| resume: | resume: | ||||||
| 	nv_mask(dev, 0x002504, 0x00000001, 0x00000000); | 	nv_mask(device, 0x002504, 0x00000001, 0x00000000); | ||||||
| 	kfree(info); | 	kfree(info); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  | @ -832,6 +857,8 @@ resume: | ||||||
| static int | static int | ||||||
| pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) | pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (*line == 0x04) { | 	if (*line == 0x04) { | ||||||
| 		*ctrl = 0x00e100; | 		*ctrl = 0x00e100; | ||||||
| 		*line = 4; | 		*line = 4; | ||||||
|  | @ -847,7 +874,7 @@ pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) | ||||||
| 		*line = 0; | 		*line = 0; | ||||||
| 		*indx = 0; | 		*indx = 0; | ||||||
| 	} else { | 	} else { | ||||||
| 		NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", *line); | 		NV_ERROR(drm, "unknown pwm ctrl for gpio %d\n", *line); | ||||||
| 		return -ENODEV; | 		return -ENODEV; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -857,13 +884,14 @@ pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) | ||||||
| int | int | ||||||
| nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); | 	int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	if (nv_rd32(dev, ctrl) & (1 << line)) { | 	if (nv_rd32(device, ctrl) & (1 << line)) { | ||||||
| 		*divs = nv_rd32(dev, 0x00e114 + (id * 8)); | 		*divs = nv_rd32(device, 0x00e114 + (id * 8)); | ||||||
| 		*duty = nv_rd32(dev, 0x00e118 + (id * 8)); | 		*duty = nv_rd32(device, 0x00e118 + (id * 8)); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -873,12 +901,13 @@ nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) | ||||||
| int | int | ||||||
| nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) | nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); | 	int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, ctrl, 0x00010001 << line, 0x00000001 << line); | 	nv_mask(device, ctrl, 0x00010001 << line, 0x00000001 << line); | ||||||
| 	nv_wr32(dev, 0x00e114 + (id * 8), divs); | 	nv_wr32(device, 0x00e114 + (id * 8), divs); | ||||||
| 	nv_wr32(dev, 0x00e118 + (id * 8), duty | 0x80000000); | 	nv_wr32(device, 0x00e118 + (id * 8), duty | 0x80000000); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -29,20 +29,22 @@ | ||||||
| 
 | 
 | ||||||
| #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | #define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) | ||||||
| #include "nouveau_reg.h" | #include "nouveau_reg.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | 
 | ||||||
| static u32 | static u32 | ||||||
| nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) | nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ | 	static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ | ||||||
| 	static const u8 nv50[] = { 16, 8, 0, 24 }; | 	static const u8 nv50[] = { 16, 8, 0, 24 }; | ||||||
| 	if (dev_priv->chipset == 0xaf) | 	if (nv_device(drm->device)->chipset == 0xaf) | ||||||
| 		return nvaf[lane]; | 		return nvaf[lane]; | ||||||
| 	return nv50[lane]; | 	return nv50[lane]; | ||||||
| } | } | ||||||
|  | @ -50,14 +52,17 @@ nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) | ||||||
| static void | static void | ||||||
| nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) | nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); | 	nv_mask(device, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 		      u8 lane, u8 swing, u8 preem) | 		      u8 lane, u8 swing, u8 preem) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	u32 shift = nv50_sor_dp_lane_map(dev, dcb, lane); | 	u32 shift = nv50_sor_dp_lane_map(dev, dcb, lane); | ||||||
| 	u32 mask = 0x000000ff << shift; | 	u32 mask = 0x000000ff << shift; | ||||||
|  | @ -65,7 +70,7 @@ nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 
 | 
 | ||||||
| 	table = nouveau_dp_bios_data(dev, dcb, &entry); | 	table = nouveau_dp_bios_data(dev, dcb, &entry); | ||||||
| 	if (!table || (table[0] != 0x20 && table[0] != 0x21)) { | 	if (!table || (table[0] != 0x20 && table[0] != 0x21)) { | ||||||
| 		NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); | 		NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -76,24 +81,26 @@ nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 			return; | 			return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, NV50_SOR_DP_UNK118(or, link), mask, config[2] << shift); | 	nv_mask(device, NV50_SOR_DP_UNK118(or, link), mask, config[2] << shift); | ||||||
| 	nv_mask(dev, NV50_SOR_DP_UNK120(or, link), mask, config[3] << shift); | 	nv_mask(device, NV50_SOR_DP_UNK120(or, link), mask, config[3] << shift); | ||||||
| 	nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8); | 	nv_mask(device, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | ||||||
| 		     int link_nr, u32 link_bw, bool enhframe) | 		     int link_nr, u32 link_bw, bool enhframe) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000; | 	u32 dpctrl = nv_rd32(device, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000; | ||||||
| 	u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)) & ~0x000c0000; | 	u32 clksor = nv_rd32(device, 0x614300 + (or * 0x800)) & ~0x000c0000; | ||||||
| 	u8 *table, *entry, mask; | 	u8 *table, *entry, mask; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	table = nouveau_dp_bios_data(dev, dcb, &entry); | 	table = nouveau_dp_bios_data(dev, dcb, &entry); | ||||||
| 	if (!table || (table[0] != 0x20 && table[0] != 0x21)) { | 	if (!table || (table[0] != 0x20 && table[0] != 0x21)) { | ||||||
| 		NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); | 		NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -112,20 +119,21 @@ nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | ||||||
| 	if (link_bw > 162000) | 	if (link_bw > 162000) | ||||||
| 		clksor |= 0x00040000; | 		clksor |= 0x00040000; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x614300 + (or * 0x800), clksor); | 	nv_wr32(device, 0x614300 + (or * 0x800), clksor); | ||||||
| 	nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), dpctrl); | 	nv_wr32(device, NV50_SOR_DP_CTRL(or, link), dpctrl); | ||||||
| 
 | 
 | ||||||
| 	mask = 0; | 	mask = 0; | ||||||
| 	for (i = 0; i < link_nr; i++) | 	for (i = 0; i < link_nr; i++) | ||||||
| 		mask |= 1 << (nv50_sor_dp_lane_map(dev, dcb, i) >> 3); | 		mask |= 1 << (nv50_sor_dp_lane_map(dev, dcb, i) >> 3); | ||||||
| 	nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask); | 	nv_mask(device, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) | nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) | ||||||
| { | { | ||||||
| 	u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & 0x000f0000; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)); | 	u32 dpctrl = nv_rd32(device, NV50_SOR_DP_CTRL(or, link)) & 0x000f0000; | ||||||
|  | 	u32 clksor = nv_rd32(device, 0x614300 + (or * 0x800)); | ||||||
| 	if (clksor & 0x000c0000) | 	if (clksor & 0x000c0000) | ||||||
| 		*bw = 270000; | 		*bw = 270000; | ||||||
| 	else | 	else | ||||||
|  | @ -139,6 +147,8 @@ nv50_sor_dp_link_get(struct drm_device *dev, u32 or, u32 link, u32 *nr, u32 *bw) | ||||||
| void | void | ||||||
| nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) | nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	const u32 symbol = 100000; | 	const u32 symbol = 100000; | ||||||
| 	int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; | 	int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0; | ||||||
| 	int TU, VTUi, VTUf, VTUa; | 	int TU, VTUi, VTUf, VTUa; | ||||||
|  | @ -206,7 +216,7 @@ nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!bestTU) { | 	if (!bestTU) { | ||||||
| 		NV_ERROR(dev, "DP: unable to find suitable config\n"); | 		NV_ERROR(drm, "DP: unable to find suitable config\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -217,8 +227,8 @@ nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) | ||||||
| 	r = do_div(unk, symbol); | 	r = do_div(unk, symbol); | ||||||
| 	unk += 6; | 	unk += 6; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); | 	nv_mask(device, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2); | ||||||
| 	nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | | 	nv_mask(device, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 | | ||||||
| 							     bestVTUf << 16 | | 							     bestVTUf << 16 | | ||||||
| 							     bestVTUi << 8 | | 							     bestVTUi << 8 | | ||||||
| 							     unk); | 							     unk); | ||||||
|  | @ -227,6 +237,7 @@ static void | ||||||
| nv50_sor_disconnect(struct drm_encoder *encoder) | nv50_sor_disconnect(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct nouveau_channel *evo = nv50_display(dev)->master; | 	struct nouveau_channel *evo = nv50_display(dev)->master; | ||||||
| 	int ret; | 	int ret; | ||||||
|  | @ -235,11 +246,11 @@ nv50_sor_disconnect(struct drm_encoder *encoder) | ||||||
| 		return; | 		return; | ||||||
| 	nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); | 	nv50_crtc_blank(nouveau_crtc(nv_encoder->crtc), true); | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "Disconnecting SOR %d\n", nv_encoder->or); | 	NV_DEBUG(drm, "Disconnecting SOR %d\n", nv_encoder->or); | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 4); | 	ret = RING_SPACE(evo, 4); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while disconnecting SOR\n"); | 		NV_ERROR(drm, "no space while disconnecting SOR\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); | 	BEGIN_NV04(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); | ||||||
|  | @ -256,13 +267,15 @@ nv50_sor_disconnect(struct drm_encoder *encoder) | ||||||
| static void | static void | ||||||
| nv50_sor_dpms(struct drm_encoder *encoder, int mode) | nv50_sor_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(encoder->dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_encoder *enc; | 	struct drm_encoder *enc; | ||||||
| 	uint32_t val; | 	uint32_t val; | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); | 	NV_DEBUG(drm, "or %d type %d mode %d\n", or, nv_encoder->dcb->type, mode); | ||||||
| 
 | 
 | ||||||
| 	nv_encoder->last_dpms = mode; | 	nv_encoder->last_dpms = mode; | ||||||
| 	list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { | 	list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { | ||||||
|  | @ -280,27 +293,27 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* wait for it to be done */ | 	/* wait for it to be done */ | ||||||
| 	if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), | 	if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or), | ||||||
| 		     NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { | 		     NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { | ||||||
| 		NV_ERROR(dev, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); | 		NV_ERROR(drm, "timeout: SOR_DPMS_CTRL_PENDING(%d) == 0\n", or); | ||||||
| 		NV_ERROR(dev, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, | 		NV_ERROR(drm, "SOR_DPMS_CTRL(%d) = 0x%08x\n", or, | ||||||
| 			 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); | 			 nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	val = nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); | 	val = nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or)); | ||||||
| 
 | 
 | ||||||
| 	if (mode == DRM_MODE_DPMS_ON) | 	if (mode == DRM_MODE_DPMS_ON) | ||||||
| 		val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON; | 		val |= NV50_PDISPLAY_SOR_DPMS_CTRL_ON; | ||||||
| 	else | 	else | ||||||
| 		val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON; | 		val &= ~NV50_PDISPLAY_SOR_DPMS_CTRL_ON; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | | 	nv_wr32(device, NV50_PDISPLAY_SOR_DPMS_CTRL(or), val | | ||||||
| 		NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); | 		NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING); | ||||||
| 	if (!nv_wait(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or), | 	if (!nv_wait(device, NV50_PDISPLAY_SOR_DPMS_STATE(or), | ||||||
| 		     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { | 		     NV50_PDISPLAY_SOR_DPMS_STATE_WAIT, 0)) { | ||||||
| 		NV_ERROR(dev, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); | 		NV_ERROR(drm, "timeout: SOR_DPMS_STATE_WAIT(%d) == 0\n", or); | ||||||
| 		NV_ERROR(dev, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, | 		NV_ERROR(drm, "SOR_DPMS_STATE(%d) = 0x%08x\n", or, | ||||||
| 			 nv_rd32(dev, NV50_PDISPLAY_SOR_DPMS_STATE(or))); | 			 nv_rd32(device, NV50_PDISPLAY_SOR_DPMS_STATE(or))); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { | 	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { | ||||||
|  | @ -317,13 +330,15 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | ||||||
| static void | static void | ||||||
| nv50_sor_save(struct drm_encoder *encoder) | nv50_sor_save(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	NV_ERROR(encoder->dev, "!!\n"); | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
|  | 	NV_ERROR(drm, "!!\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nv50_sor_restore(struct drm_encoder *encoder) | nv50_sor_restore(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	NV_ERROR(encoder->dev, "!!\n"); | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
|  | 	NV_ERROR(drm, "!!\n"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
|  | @ -331,14 +346,15 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, | ||||||
| 		    const struct drm_display_mode *mode, | 		    const struct drm_display_mode *mode, | ||||||
| 		    struct drm_display_mode *adjusted_mode) | 		    struct drm_display_mode *adjusted_mode) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nouveau_connector *connector; | 	struct nouveau_connector *connector; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "or %d\n", nv_encoder->or); | 	NV_DEBUG(drm, "or %d\n", nv_encoder->or); | ||||||
| 
 | 
 | ||||||
| 	connector = nouveau_encoder_connector_get(nv_encoder); | 	connector = nouveau_encoder_connector_get(nv_encoder); | ||||||
| 	if (!connector) { | 	if (!connector) { | ||||||
| 		NV_ERROR(encoder->dev, "Encoder has no connector\n"); | 		NV_ERROR(drm, "Encoder has no connector\n"); | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -371,13 +387,13 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, | ||||||
| { | { | ||||||
| 	struct nouveau_channel *evo = nv50_display(encoder->dev)->master; | 	struct nouveau_channel *evo = nv50_display(encoder->dev)->master; | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	uint32_t mode_ctl = 0; | 	uint32_t mode_ctl = 0; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", | 	NV_DEBUG(drm, "or %d type %d -> crtc %d\n", | ||||||
| 		     nv_encoder->or, nv_encoder->dcb->type, crtc->index); | 		     nv_encoder->or, nv_encoder->dcb->type, crtc->index); | ||||||
| 	nv_encoder->crtc = encoder->crtc; | 	nv_encoder->crtc = encoder->crtc; | ||||||
| 
 | 
 | ||||||
|  | @ -427,7 +443,7 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, | ||||||
| 
 | 
 | ||||||
| 	ret = RING_SPACE(evo, 2); | 	ret = RING_SPACE(evo, 2); | ||||||
| 	if (ret) { | 	if (ret) { | ||||||
| 		NV_ERROR(dev, "no space while connecting SOR\n"); | 		NV_ERROR(drm, "no space while connecting SOR\n"); | ||||||
| 		nv_encoder->crtc = NULL; | 		nv_encoder->crtc = NULL; | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | @ -458,11 +474,9 @@ static void | ||||||
| nv50_sor_destroy(struct drm_encoder *encoder) | nv50_sor_destroy(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(encoder->dev); | ||||||
| 
 | 
 | ||||||
| 	if (!encoder) | 	NV_DEBUG(drm, "\n"); | ||||||
| 		return; |  | ||||||
| 
 |  | ||||||
| 	NV_DEBUG_KMS(encoder->dev, "\n"); |  | ||||||
| 
 | 
 | ||||||
| 	drm_encoder_cleanup(encoder); | 	drm_encoder_cleanup(encoder); | ||||||
| 
 | 
 | ||||||
|  | @ -478,10 +492,11 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *entry) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = NULL; | 	struct nouveau_encoder *nv_encoder = NULL; | ||||||
| 	struct drm_device *dev = connector->dev; | 	struct drm_device *dev = connector->dev; | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct drm_encoder *encoder; | 	struct drm_encoder *encoder; | ||||||
| 	int type; | 	int type; | ||||||
| 
 | 
 | ||||||
| 	NV_DEBUG_KMS(dev, "\n"); | 	NV_DEBUG(drm, "\n"); | ||||||
| 
 | 
 | ||||||
| 	switch (entry->type) { | 	switch (entry->type) { | ||||||
| 	case DCB_OUTPUT_TMDS: | 	case DCB_OUTPUT_TMDS: | ||||||
|  |  | ||||||
|  | @ -31,6 +31,8 @@ | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| 
 | 
 | ||||||
|  | #include "nv50_display.h" | ||||||
|  | 
 | ||||||
| struct nv84_fence_chan { | struct nv84_fence_chan { | ||||||
| 	struct nouveau_fence_chan base; | 	struct nouveau_fence_chan base; | ||||||
| }; | }; | ||||||
|  | @ -99,6 +101,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) | ||||||
| static int | static int | ||||||
| nv84_fence_context_new(struct nouveau_channel *chan) | nv84_fence_context_new(struct nouveau_channel *chan) | ||||||
| { | { | ||||||
|  | 	struct drm_device *dev = chan->drm->dev; | ||||||
| 	struct nouveau_fifo_chan *fifo = (void *)chan->object; | 	struct nouveau_fifo_chan *fifo = (void *)chan->object; | ||||||
| 	struct nv84_fence_priv *priv = chan->drm->fence; | 	struct nv84_fence_priv *priv = chan->drm->fence; | ||||||
| 	struct nv84_fence_chan *fctx; | 	struct nv84_fence_chan *fctx; | ||||||
|  | @ -123,8 +126,8 @@ nv84_fence_context_new(struct nouveau_channel *chan) | ||||||
| 				 &object); | 				 &object); | ||||||
| 
 | 
 | ||||||
| 	/* dma objects for display sync channel semaphore blocks */ | 	/* dma objects for display sync channel semaphore blocks */ | ||||||
| 	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { | 	for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { | ||||||
| 		struct nouveau_bo *bo = nv50sema(chan->drm->dev, i); | 		struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); | ||||||
| 
 | 
 | ||||||
| 		ret = nouveau_object_new(nv_object(chan->cli), chan->handle, | 		ret = nouveau_object_new(nv_object(chan->cli), chan->handle, | ||||||
| 					 NvEvoSema0 + i, 0x003d, | 					 NvEvoSema0 + i, 0x003d, | ||||||
|  |  | ||||||
|  | @ -23,17 +23,24 @@ | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
| #include <nouveau_bios.h> | #include "nouveau_bios.h" | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/bios.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | #include <subdev/fb.h> | ||||||
|  | 
 | ||||||
| static u32 read_clk(struct drm_device *, int, bool); | static u32 read_clk(struct drm_device *, int, bool); | ||||||
| static u32 read_pll(struct drm_device *, int, u32); | static u32 read_pll(struct drm_device *, int, u32); | ||||||
| 
 | 
 | ||||||
| static u32 | static u32 | ||||||
| read_vco(struct drm_device *dev, int clk) | read_vco(struct drm_device *dev, int clk) | ||||||
| { | { | ||||||
| 	u32 sctl = nv_rd32(dev, 0x4120 + (clk * 4)); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	u32 sctl = nv_rd32(device, 0x4120 + (clk * 4)); | ||||||
| 	if ((sctl & 0x00000030) != 0x00000030) | 	if ((sctl & 0x00000030) != 0x00000030) | ||||||
| 		return read_pll(dev, 0x41, 0x00e820); | 		return read_pll(dev, 0x41, 0x00e820); | ||||||
| 	return read_pll(dev, 0x42, 0x00e8a0); | 	return read_pll(dev, 0x42, 0x00e8a0); | ||||||
|  | @ -42,26 +49,27 @@ read_vco(struct drm_device *dev, int clk) | ||||||
| static u32 | static u32 | ||||||
| read_clk(struct drm_device *dev, int clk, bool ignore_en) | read_clk(struct drm_device *dev, int clk, bool ignore_en) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	u32 sctl, sdiv, sclk; | 	u32 sctl, sdiv, sclk; | ||||||
| 
 | 
 | ||||||
| 	/* refclk for the 0xe8xx plls is a fixed frequency */ | 	/* refclk for the 0xe8xx plls is a fixed frequency */ | ||||||
| 	if (clk >= 0x40) { | 	if (clk >= 0x40) { | ||||||
| 		if (dev_priv->chipset == 0xaf) { | 		if (nv_device(drm->device)->chipset == 0xaf) { | ||||||
| 			/* no joke.. seriously.. sigh.. */ | 			/* no joke.. seriously.. sigh.. */ | ||||||
| 			return nv_rd32(dev, 0x00471c) * 1000; | 			return nv_rd32(device, 0x00471c) * 1000; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		return dev_priv->crystal; | 		return device->crystal; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	sctl = nv_rd32(dev, 0x4120 + (clk * 4)); | 	sctl = nv_rd32(device, 0x4120 + (clk * 4)); | ||||||
| 	if (!ignore_en && !(sctl & 0x00000100)) | 	if (!ignore_en && !(sctl & 0x00000100)) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
| 	switch (sctl & 0x00003000) { | 	switch (sctl & 0x00003000) { | ||||||
| 	case 0x00000000: | 	case 0x00000000: | ||||||
| 		return dev_priv->crystal; | 		return device->crystal; | ||||||
| 	case 0x00002000: | 	case 0x00002000: | ||||||
| 		if (sctl & 0x00000040) | 		if (sctl & 0x00000040) | ||||||
| 			return 108000; | 			return 108000; | ||||||
|  | @ -78,12 +86,13 @@ read_clk(struct drm_device *dev, int clk, bool ignore_en) | ||||||
| static u32 | static u32 | ||||||
| read_pll(struct drm_device *dev, int clk, u32 pll) | read_pll(struct drm_device *dev, int clk, u32 pll) | ||||||
| { | { | ||||||
| 	u32 ctrl = nv_rd32(dev, pll + 0); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	u32 ctrl = nv_rd32(device, pll + 0); | ||||||
| 	u32 sclk = 0, P = 1, N = 1, M = 1; | 	u32 sclk = 0, P = 1, N = 1, M = 1; | ||||||
| 
 | 
 | ||||||
| 	if (!(ctrl & 0x00000008)) { | 	if (!(ctrl & 0x00000008)) { | ||||||
| 		if (ctrl & 0x00000001) { | 		if (ctrl & 0x00000001) { | ||||||
| 			u32 coef = nv_rd32(dev, pll + 4); | 			u32 coef = nv_rd32(device, pll + 4); | ||||||
| 			M = (coef & 0x000000ff) >> 0; | 			M = (coef & 0x000000ff) >> 0; | ||||||
| 			N = (coef & 0x0000ff00) >> 8; | 			N = (coef & 0x0000ff00) >> 8; | ||||||
| 			P = (coef & 0x003f0000) >> 16; | 			P = (coef & 0x003f0000) >> 16; | ||||||
|  | @ -111,6 +120,9 @@ struct creg { | ||||||
| static int | static int | ||||||
| calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) | calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
| 	struct nvbios_pll limits; | 	struct nvbios_pll limits; | ||||||
| 	u32 oclk, sclk, sdiv; | 	u32 oclk, sclk, sdiv; | ||||||
| 	int P, N, M, diff; | 	int P, N, M, diff; | ||||||
|  | @ -119,7 +131,7 @@ calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) | ||||||
| 	reg->pll = 0; | 	reg->pll = 0; | ||||||
| 	reg->clk = 0; | 	reg->clk = 0; | ||||||
| 	if (!khz) { | 	if (!khz) { | ||||||
| 		NV_DEBUG(dev, "no clock for 0x%04x/0x%02x\n", pll, clk); | 		NV_DEBUG(drm, "no clock for 0x%04x/0x%02x\n", pll, clk); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -154,14 +166,14 @@ calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (!pll) { | 		if (!pll) { | ||||||
| 			NV_ERROR(dev, "bad freq %02x: %d %d\n", clk, khz, sclk); | 			NV_ERROR(drm, "bad freq %02x: %d %d\n", clk, khz, sclk); | ||||||
| 			return -ERANGE; | 			return -ERANGE; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ret = get_pll_limits(dev, pll, &limits); | 	ret = nvbios_pll_parse(bios, pll, &limits); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return ret; | 		return ret; | ||||||
| 
 | 
 | ||||||
|  | @ -171,54 +183,60 @@ calc_clk(struct drm_device *dev, int clk, u32 pll, u32 khz, struct creg *reg) | ||||||
| 
 | 
 | ||||||
| 	ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); | 	ret = nva3_calc_pll(dev, &limits, khz, &N, NULL, &M, &P); | ||||||
| 	if (ret >= 0) { | 	if (ret >= 0) { | ||||||
| 		reg->clk = nv_rd32(dev, 0x4120 + (clk * 4)); | 		reg->clk = nv_rd32(device, 0x4120 + (clk * 4)); | ||||||
| 		reg->pll = (P << 16) | (N << 8) | M; | 		reg->pll = (P << 16) | (N << 8) | M; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) | prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	const u32 src0 = 0x004120 + (clk * 4); | 	const u32 src0 = 0x004120 + (clk * 4); | ||||||
| 	const u32 src1 = 0x004160 + (clk * 4); | 	const u32 src1 = 0x004160 + (clk * 4); | ||||||
| 	const u32 ctrl = pll + 0; | 	const u32 ctrl = pll + 0; | ||||||
| 	const u32 coef = pll + 4; | 	const u32 coef = pll + 4; | ||||||
| 
 | 
 | ||||||
| 	if (!reg->clk && !reg->pll) { | 	if (!reg->clk && !reg->pll) { | ||||||
| 		NV_DEBUG(dev, "no clock for %02x\n", clk); | 		NV_DEBUG(drm, "no clock for %02x\n", clk); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (reg->pll) { | 	if (reg->pll) { | ||||||
| 		nv_mask(dev, src0, 0x00000101, 0x00000101); | 		nv_mask(device, src0, 0x00000101, 0x00000101); | ||||||
| 		nv_wr32(dev, coef, reg->pll); | 		nv_wr32(device, coef, reg->pll); | ||||||
| 		nv_mask(dev, ctrl, 0x00000015, 0x00000015); | 		nv_mask(device, ctrl, 0x00000015, 0x00000015); | ||||||
| 		nv_mask(dev, ctrl, 0x00000010, 0x00000000); | 		nv_mask(device, ctrl, 0x00000010, 0x00000000); | ||||||
| 		nv_wait(dev, ctrl, 0x00020000, 0x00020000); | 		nv_wait(device, ctrl, 0x00020000, 0x00020000); | ||||||
| 		nv_mask(dev, ctrl, 0x00000010, 0x00000010); | 		nv_mask(device, ctrl, 0x00000010, 0x00000010); | ||||||
| 		nv_mask(dev, ctrl, 0x00000008, 0x00000000); | 		nv_mask(device, ctrl, 0x00000008, 0x00000000); | ||||||
| 		nv_mask(dev, src1, 0x00000100, 0x00000000); | 		nv_mask(device, src1, 0x00000100, 0x00000000); | ||||||
| 		nv_mask(dev, src1, 0x00000001, 0x00000000); | 		nv_mask(device, src1, 0x00000001, 0x00000000); | ||||||
| 	} else { | 	} else { | ||||||
| 		nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); | 		nv_mask(device, src1, 0x003f3141, 0x00000101 | reg->clk); | ||||||
| 		nv_mask(dev, ctrl, 0x00000018, 0x00000018); | 		nv_mask(device, ctrl, 0x00000018, 0x00000018); | ||||||
| 		udelay(20); | 		udelay(20); | ||||||
| 		nv_mask(dev, ctrl, 0x00000001, 0x00000000); | 		nv_mask(device, ctrl, 0x00000001, 0x00000000); | ||||||
| 		nv_mask(dev, src0, 0x00000100, 0x00000000); | 		nv_mask(device, src0, 0x00000100, 0x00000000); | ||||||
| 		nv_mask(dev, src0, 0x00000001, 0x00000000); | 		nv_mask(device, src0, 0x00000001, 0x00000000); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| prog_clk(struct drm_device *dev, int clk, struct creg *reg) | prog_clk(struct drm_device *dev, int clk, struct creg *reg) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 
 | ||||||
| 	if (!reg->clk) { | 	if (!reg->clk) { | ||||||
| 		NV_DEBUG(dev, "no clock for %02x\n", clk); | 		NV_DEBUG(drm, "no clock for %02x\n", clk); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); | 	nv_mask(device, 0x004120 + (clk * 4), 0x003f3141, 0x00000101 | reg->clk); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
|  | @ -309,10 +327,11 @@ static bool | ||||||
| nva3_pm_grcp_idle(void *data) | nva3_pm_grcp_idle(void *data) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = data; | 	struct drm_device *dev = data; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 
 | 
 | ||||||
| 	if (!(nv_rd32(dev, 0x400304) & 0x00000001)) | 	if (!(nv_rd32(device, 0x400304) & 0x00000001)) | ||||||
| 		return true; | 		return true; | ||||||
| 	if (nv_rd32(dev, 0x400308) == 0x0050001c) | 	if (nv_rd32(device, 0x400308) == 0x0050001c) | ||||||
| 		return true; | 		return true; | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  | @ -320,83 +339,91 @@ nva3_pm_grcp_idle(void *data) | ||||||
| static void | static void | ||||||
| mclk_precharge(struct nouveau_mem_exec_func *exec) | mclk_precharge(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
| 	nv_wr32(exec->dev, 0x1002d4, 0x00000001); | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	nv_wr32(device, 0x1002d4, 0x00000001); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_refresh(struct nouveau_mem_exec_func *exec) | mclk_refresh(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
| 	nv_wr32(exec->dev, 0x1002d0, 0x00000001); | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	nv_wr32(device, 0x1002d0, 0x00000001); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) | mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) | ||||||
| { | { | ||||||
| 	nv_wr32(exec->dev, 0x100210, enable ? 0x80000000 : 0x00000000); | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	nv_wr32(device, 0x100210, enable ? 0x80000000 : 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) | mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) | ||||||
| { | { | ||||||
| 	nv_wr32(exec->dev, 0x1002dc, enable ? 0x00000001 : 0x00000000); | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	nv_wr32(device, 0x1002dc, enable ? 0x00000001 : 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) | mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) | ||||||
| { | { | ||||||
| 	volatile u32 post = nv_rd32(exec->dev, 0); (void)post; | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	volatile u32 post = nv_rd32(device, 0); (void)post; | ||||||
| 	udelay((nsec + 500) / 1000); | 	udelay((nsec + 500) / 1000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static u32 | static u32 | ||||||
| mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	if (mr <= 1) | 	if (mr <= 1) | ||||||
| 		return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4)); | 		return nv_rd32(device, 0x1002c0 + ((mr - 0) * 4)); | ||||||
| 	if (mr <= 3) | 	if (mr <= 3) | ||||||
| 		return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4)); | 		return nv_rd32(device, 0x1002e0 + ((mr - 2) * 4)); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
| 	if (mr <= 1) { | 	if (mr <= 1) { | ||||||
| 		if (nvfb_vram_rank_B(exec->dev)) | 		if (pfb->ram.ranks > 1) | ||||||
| 			nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data); | 			nv_wr32(device, 0x1002c8 + ((mr - 0) * 4), data); | ||||||
| 		nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data); | 		nv_wr32(device, 0x1002c0 + ((mr - 0) * 4), data); | ||||||
| 	} else | 	} else | ||||||
| 	if (mr <= 3) { | 	if (mr <= 3) { | ||||||
| 		if (nvfb_vram_rank_B(exec->dev)) | 		if (pfb->ram.ranks > 1) | ||||||
| 			nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data); | 			nv_wr32(device, 0x1002e8 + ((mr - 2) * 4), data); | ||||||
| 		nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data); | 		nv_wr32(device, 0x1002e0 + ((mr - 2) * 4), data); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_clock_set(struct nouveau_mem_exec_func *exec) | mclk_clock_set(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = exec->dev; | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	struct nva3_pm_state *info = exec->priv; | 	struct nva3_pm_state *info = exec->priv; | ||||||
| 	u32 ctrl; | 	u32 ctrl; | ||||||
| 
 | 
 | ||||||
| 	ctrl = nv_rd32(dev, 0x004000); | 	ctrl = nv_rd32(device, 0x004000); | ||||||
| 	if (!(ctrl & 0x00000008) && info->mclk.pll) { | 	if (!(ctrl & 0x00000008) && info->mclk.pll) { | ||||||
| 		nv_wr32(dev, 0x004000, (ctrl |=  0x00000008)); | 		nv_wr32(device, 0x004000, (ctrl |=  0x00000008)); | ||||||
| 		nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); | 		nv_mask(device, 0x1110e0, 0x00088000, 0x00088000); | ||||||
| 		nv_wr32(dev, 0x004018, 0x00001000); | 		nv_wr32(device, 0x004018, 0x00001000); | ||||||
| 		nv_wr32(dev, 0x004000, (ctrl &= ~0x00000001)); | 		nv_wr32(device, 0x004000, (ctrl &= ~0x00000001)); | ||||||
| 		nv_wr32(dev, 0x004004, info->mclk.pll); | 		nv_wr32(device, 0x004004, info->mclk.pll); | ||||||
| 		nv_wr32(dev, 0x004000, (ctrl |=  0x00000001)); | 		nv_wr32(device, 0x004000, (ctrl |=  0x00000001)); | ||||||
| 		udelay(64); | 		udelay(64); | ||||||
| 		nv_wr32(dev, 0x004018, 0x00005000 | info->r004018); | 		nv_wr32(device, 0x004018, 0x00005000 | info->r004018); | ||||||
| 		udelay(20); | 		udelay(20); | ||||||
| 	} else | 	} else | ||||||
| 	if (!info->mclk.pll) { | 	if (!info->mclk.pll) { | ||||||
| 		nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk); | 		nv_mask(device, 0x004168, 0x003f3040, info->mclk.clk); | ||||||
| 		nv_wr32(dev, 0x004000, (ctrl |= 0x00000008)); | 		nv_wr32(device, 0x004000, (ctrl |= 0x00000008)); | ||||||
| 		nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); | 		nv_mask(device, 0x1110e0, 0x00088000, 0x00088000); | ||||||
| 		nv_wr32(dev, 0x004018, 0x0000d000 | info->r004018); | 		nv_wr32(device, 0x004018, 0x0000d000 | info->r004018); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (info->rammap) { | 	if (info->rammap) { | ||||||
|  | @ -408,67 +435,68 @@ mclk_clock_set(struct nouveau_mem_exec_func *exec) | ||||||
| 				     (info->ramcfg[3] & 0x0f) << 16 | | 				     (info->ramcfg[3] & 0x0f) << 16 | | ||||||
| 				     (info->ramcfg[9] & 0x0f) | | 				     (info->ramcfg[9] & 0x0f) | | ||||||
| 				     0x80000000; | 				     0x80000000; | ||||||
| 			nv_wr32(dev, 0x1005a0, unk5a0); | 			nv_wr32(device, 0x1005a0, unk5a0); | ||||||
| 			nv_wr32(dev, 0x1005a4, unk5a4); | 			nv_wr32(device, 0x1005a4, unk5a4); | ||||||
| 			nv_wr32(dev, 0x10f804, unk804); | 			nv_wr32(device, 0x10f804, unk804); | ||||||
| 			nv_mask(dev, 0x10053c, 0x00001000, 0x00000000); | 			nv_mask(device, 0x10053c, 0x00001000, 0x00000000); | ||||||
| 		} else { | 		} else { | ||||||
| 			nv_mask(dev, 0x10053c, 0x00001000, 0x00001000); | 			nv_mask(device, 0x10053c, 0x00001000, 0x00001000); | ||||||
| 			nv_mask(dev, 0x10f804, 0x80000000, 0x00000000); | 			nv_mask(device, 0x10f804, 0x80000000, 0x00000000); | ||||||
| 			nv_mask(dev, 0x100760, 0x22222222, info->r100760); | 			nv_mask(device, 0x100760, 0x22222222, info->r100760); | ||||||
| 			nv_mask(dev, 0x1007a0, 0x22222222, info->r100760); | 			nv_mask(device, 0x1007a0, 0x22222222, info->r100760); | ||||||
| 			nv_mask(dev, 0x1007e0, 0x22222222, info->r100760); | 			nv_mask(device, 0x1007e0, 0x22222222, info->r100760); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (info->mclk.pll) { | 	if (info->mclk.pll) { | ||||||
| 		nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000); | 		nv_mask(device, 0x1110e0, 0x00088000, 0x00011000); | ||||||
| 		nv_wr32(dev, 0x004000, (ctrl &= ~0x00000008)); | 		nv_wr32(device, 0x004000, (ctrl &= ~0x00000008)); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_timing_set(struct nouveau_mem_exec_func *exec) | mclk_timing_set(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = exec->dev; | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	struct nva3_pm_state *info = exec->priv; | 	struct nva3_pm_state *info = exec->priv; | ||||||
| 	struct nouveau_pm_level *perflvl = info->perflvl; | 	struct nouveau_pm_level *perflvl = info->perflvl; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 9; i++) | 	for (i = 0; i < 9; i++) | ||||||
| 		nv_wr32(dev, 0x100220 + (i * 4), perflvl->timing.reg[i]); | 		nv_wr32(device, 0x100220 + (i * 4), perflvl->timing.reg[i]); | ||||||
| 
 | 
 | ||||||
| 	if (info->ramcfg) { | 	if (info->ramcfg) { | ||||||
| 		u32 data = (info->ramcfg[2] & 0x08) ? 0x00000000 : 0x00001000; | 		u32 data = (info->ramcfg[2] & 0x08) ? 0x00000000 : 0x00001000; | ||||||
| 		nv_mask(dev, 0x100200, 0x00001000, data); | 		nv_mask(device, 0x100200, 0x00001000, data); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (info->ramcfg) { | 	if (info->ramcfg) { | ||||||
| 		u32 unk714 = nv_rd32(dev, 0x100714) & ~0xf0000010; | 		u32 unk714 = nv_rd32(device, 0x100714) & ~0xf0000010; | ||||||
| 		u32 unk718 = nv_rd32(dev, 0x100718) & ~0x00000100; | 		u32 unk718 = nv_rd32(device, 0x100718) & ~0x00000100; | ||||||
| 		u32 unk71c = nv_rd32(dev, 0x10071c) & ~0x00000100; | 		u32 unk71c = nv_rd32(device, 0x10071c) & ~0x00000100; | ||||||
| 		if ( (info->ramcfg[2] & 0x20)) | 		if ( (info->ramcfg[2] & 0x20)) | ||||||
| 			unk714 |= 0xf0000000; | 			unk714 |= 0xf0000000; | ||||||
| 		if (!(info->ramcfg[2] & 0x04)) | 		if (!(info->ramcfg[2] & 0x04)) | ||||||
| 			unk714 |= 0x00000010; | 			unk714 |= 0x00000010; | ||||||
| 		nv_wr32(dev, 0x100714, unk714); | 		nv_wr32(device, 0x100714, unk714); | ||||||
| 
 | 
 | ||||||
| 		if (info->ramcfg[2] & 0x01) | 		if (info->ramcfg[2] & 0x01) | ||||||
| 			unk71c |= 0x00000100; | 			unk71c |= 0x00000100; | ||||||
| 		nv_wr32(dev, 0x10071c, unk71c); | 		nv_wr32(device, 0x10071c, unk71c); | ||||||
| 
 | 
 | ||||||
| 		if (info->ramcfg[2] & 0x02) | 		if (info->ramcfg[2] & 0x02) | ||||||
| 			unk718 |= 0x00000100; | 			unk718 |= 0x00000100; | ||||||
| 		nv_wr32(dev, 0x100718, unk718); | 		nv_wr32(device, 0x100718, unk718); | ||||||
| 
 | 
 | ||||||
| 		if (info->ramcfg[2] & 0x10) | 		if (info->ramcfg[2] & 0x10) | ||||||
| 			nv_wr32(dev, 0x111100, 0x48000000); /*XXX*/ | 			nv_wr32(device, 0x111100, 0x48000000); /*XXX*/ | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| prog_mem(struct drm_device *dev, struct nva3_pm_state *info) | prog_mem(struct drm_device *dev, struct nva3_pm_state *info) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_mem_exec_func exec = { | 	struct nouveau_mem_exec_func exec = { | ||||||
| 		.dev = dev, | 		.dev = dev, | ||||||
| 		.precharge = mclk_precharge, | 		.precharge = mclk_precharge, | ||||||
|  | @ -490,17 +518,17 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info) | ||||||
| 		info->r100760 = 0x22222222; | 		info->r100760 = 0x22222222; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	ctrl = nv_rd32(dev, 0x004000); | 	ctrl = nv_rd32(device, 0x004000); | ||||||
| 	if (ctrl & 0x00000008) { | 	if (ctrl & 0x00000008) { | ||||||
| 		if (info->mclk.pll) { | 		if (info->mclk.pll) { | ||||||
| 			nv_mask(dev, 0x004128, 0x00000101, 0x00000101); | 			nv_mask(device, 0x004128, 0x00000101, 0x00000101); | ||||||
| 			nv_wr32(dev, 0x004004, info->mclk.pll); | 			nv_wr32(device, 0x004004, info->mclk.pll); | ||||||
| 			nv_wr32(dev, 0x004000, (ctrl |= 0x00000001)); | 			nv_wr32(device, 0x004000, (ctrl |= 0x00000001)); | ||||||
| 			nv_wr32(dev, 0x004000, (ctrl &= 0xffffffef)); | 			nv_wr32(device, 0x004000, (ctrl &= 0xffffffef)); | ||||||
| 			nv_wait(dev, 0x004000, 0x00020000, 0x00020000); | 			nv_wait(device, 0x004000, 0x00020000, 0x00020000); | ||||||
| 			nv_wr32(dev, 0x004000, (ctrl |= 0x00000010)); | 			nv_wr32(device, 0x004000, (ctrl |= 0x00000010)); | ||||||
| 			nv_wr32(dev, 0x004018, 0x00005000 | info->r004018); | 			nv_wr32(device, 0x004018, 0x00005000 | info->r004018); | ||||||
| 			nv_wr32(dev, 0x004000, (ctrl |= 0x00000004)); | 			nv_wr32(device, 0x004000, (ctrl |= 0x00000004)); | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		u32 ssel = 0x00000101; | 		u32 ssel = 0x00000101; | ||||||
|  | @ -508,68 +536,67 @@ prog_mem(struct drm_device *dev, struct nva3_pm_state *info) | ||||||
| 			ssel |= info->mclk.clk; | 			ssel |= info->mclk.clk; | ||||||
| 		else | 		else | ||||||
| 			ssel |= 0x00080000; /* 324MHz, shouldn't matter... */ | 			ssel |= 0x00080000; /* 324MHz, shouldn't matter... */ | ||||||
| 		nv_mask(dev, 0x004168, 0x003f3141, ctrl); | 		nv_mask(device, 0x004168, 0x003f3141, ctrl); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (info->ramcfg) { | 	if (info->ramcfg) { | ||||||
| 		if (info->ramcfg[2] & 0x10) { | 		if (info->ramcfg[2] & 0x10) { | ||||||
| 			nv_mask(dev, 0x111104, 0x00000600, 0x00000000); | 			nv_mask(device, 0x111104, 0x00000600, 0x00000000); | ||||||
| 		} else { | 		} else { | ||||||
| 			nv_mask(dev, 0x111100, 0x40000000, 0x40000000); | 			nv_mask(device, 0x111100, 0x40000000, 0x40000000); | ||||||
| 			nv_mask(dev, 0x111104, 0x00000180, 0x00000000); | 			nv_mask(device, 0x111104, 0x00000180, 0x00000000); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if (info->rammap && !(info->rammap[4] & 0x02)) | 	if (info->rammap && !(info->rammap[4] & 0x02)) | ||||||
| 		nv_mask(dev, 0x100200, 0x00000800, 0x00000000); | 		nv_mask(device, 0x100200, 0x00000800, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x611200, 0x00003300); | 	nv_wr32(device, 0x611200, 0x00003300); | ||||||
| 	if (!(info->ramcfg[2] & 0x10)) | 	if (!(info->ramcfg[2] & 0x10)) | ||||||
| 		nv_wr32(dev, 0x111100, 0x4c020000); /*XXX*/ | 		nv_wr32(device, 0x111100, 0x4c020000); /*XXX*/ | ||||||
| 
 | 
 | ||||||
| 	nouveau_mem_exec(&exec, info->perflvl); | 	nouveau_mem_exec(&exec, info->perflvl); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x611200, 0x00003330); | 	nv_wr32(device, 0x611200, 0x00003330); | ||||||
| 	if (info->rammap && (info->rammap[4] & 0x02)) | 	if (info->rammap && (info->rammap[4] & 0x02)) | ||||||
| 		nv_mask(dev, 0x100200, 0x00000800, 0x00000800); | 		nv_mask(device, 0x100200, 0x00000800, 0x00000800); | ||||||
| 	if (info->ramcfg) { | 	if (info->ramcfg) { | ||||||
| 		if (info->ramcfg[2] & 0x10) { | 		if (info->ramcfg[2] & 0x10) { | ||||||
| 			nv_mask(dev, 0x111104, 0x00000180, 0x00000180); | 			nv_mask(device, 0x111104, 0x00000180, 0x00000180); | ||||||
| 			nv_mask(dev, 0x111100, 0x40000000, 0x00000000); | 			nv_mask(device, 0x111100, 0x40000000, 0x00000000); | ||||||
| 		} else { | 		} else { | ||||||
| 			nv_mask(dev, 0x111104, 0x00000600, 0x00000600); | 			nv_mask(device, 0x111104, 0x00000600, 0x00000600); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (info->mclk.pll) { | 	if (info->mclk.pll) { | ||||||
| 		nv_mask(dev, 0x004168, 0x00000001, 0x00000000); | 		nv_mask(device, 0x004168, 0x00000001, 0x00000000); | ||||||
| 		nv_mask(dev, 0x004168, 0x00000100, 0x00000000); | 		nv_mask(device, 0x004168, 0x00000100, 0x00000000); | ||||||
| 	} else { | 	} else { | ||||||
| 		nv_mask(dev, 0x004000, 0x00000001, 0x00000000); | 		nv_mask(device, 0x004000, 0x00000001, 0x00000000); | ||||||
| 		nv_mask(dev, 0x004128, 0x00000001, 0x00000000); | 		nv_mask(device, 0x004128, 0x00000001, 0x00000000); | ||||||
| 		nv_mask(dev, 0x004128, 0x00000100, 0x00000000); | 		nv_mask(device, 0x004128, 0x00000100, 0x00000000); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) | nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nva3_pm_state *info = pre_state; | 	struct nva3_pm_state *info = pre_state; | ||||||
| 	unsigned long flags; |  | ||||||
| 	int ret = -EAGAIN; | 	int ret = -EAGAIN; | ||||||
| 
 | 
 | ||||||
| 	/* prevent any new grctx switches from starting */ | 	/* prevent any new grctx switches from starting */ | ||||||
| 	spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 	nv_wr32(device, 0x400324, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x400324, 0x00000000); | 	nv_wr32(device, 0x400328, 0x0050001c); /* wait flag 0x1c */ | ||||||
| 	nv_wr32(dev, 0x400328, 0x0050001c); /* wait flag 0x1c */ |  | ||||||
| 	/* wait for any pending grctx switches to complete */ | 	/* wait for any pending grctx switches to complete */ | ||||||
| 	if (!nv_wait_cb(dev, nva3_pm_grcp_idle, dev)) { | 	if (!nv_wait_cb(device, nva3_pm_grcp_idle, dev)) { | ||||||
| 		NV_ERROR(dev, "pm: ctxprog didn't go idle\n"); | 		NV_ERROR(drm, "pm: ctxprog didn't go idle\n"); | ||||||
| 		goto cleanup; | 		goto cleanup; | ||||||
| 	} | 	} | ||||||
| 	/* freeze PFIFO */ | 	/* freeze PFIFO */ | ||||||
| 	nv_mask(dev, 0x002504, 0x00000001, 0x00000001); | 	nv_mask(device, 0x002504, 0x00000001, 0x00000001); | ||||||
| 	if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) { | 	if (!nv_wait(device, 0x002504, 0x00000010, 0x00000010)) { | ||||||
| 		NV_ERROR(dev, "pm: fifo didn't go idle\n"); | 		NV_ERROR(drm, "pm: fifo didn't go idle\n"); | ||||||
| 		goto cleanup; | 		goto cleanup; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -585,14 +612,13 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) | ||||||
| 
 | 
 | ||||||
| cleanup: | cleanup: | ||||||
| 	/* unfreeze PFIFO */ | 	/* unfreeze PFIFO */ | ||||||
| 	nv_mask(dev, 0x002504, 0x00000001, 0x00000000); | 	nv_mask(device, 0x002504, 0x00000001, 0x00000000); | ||||||
| 	/* restore ctxprog to normal */ | 	/* restore ctxprog to normal */ | ||||||
| 	nv_wr32(dev, 0x400324, 0x00000000); | 	nv_wr32(device, 0x400324, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x400328, 0x0070009c); /* set flag 0x1c */ | 	nv_wr32(device, 0x400328, 0x0070009c); /* set flag 0x1c */ | ||||||
| 	/* unblock it if necessary */ | 	/* unblock it if necessary */ | ||||||
| 	if (nv_rd32(dev, 0x400308) == 0x0050001c) | 	if (nv_rd32(device, 0x400308) == 0x0050001c) | ||||||
| 		nv_mask(dev, 0x400824, 0x10000000, 0x10000000); | 		nv_mask(device, 0x400824, 0x10000000, 0x10000000); | ||||||
| 	spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |  | ||||||
| 	kfree(info); | 	kfree(info); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ int | ||||||
| nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -65,7 +65,7 @@ int | ||||||
| nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -93,7 +93,7 @@ int | ||||||
| nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) | ||||||
| { | { | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(nfbdev->dev); | 	struct nouveau_drm *drm = nouveau_drm(nfbdev->dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	uint32_t width, dwords, *data = (uint32_t *)image->data; | 	uint32_t width, dwords, *data = (uint32_t *)image->data; | ||||||
| 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); | 	uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel)); | ||||||
|  | @ -152,7 +152,7 @@ nvc0_fbcon_accel_init(struct fb_info *info) | ||||||
| 	struct nouveau_fbdev *nfbdev = info->par; | 	struct nouveau_fbdev *nfbdev = info->par; | ||||||
| 	struct drm_device *dev = nfbdev->dev; | 	struct drm_device *dev = nfbdev->dev; | ||||||
| 	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; | 	struct nouveau_framebuffer *fb = &nfbdev->nouveau_fb; | ||||||
| 	struct nouveau_drm *drm = nouveau_newpriv(dev); | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_channel *chan = drm->channel; | 	struct nouveau_channel *chan = drm->channel; | ||||||
| 	struct nouveau_object *object; | 	struct nouveau_object *object; | ||||||
| 	int ret, format; | 	int ret, format; | ||||||
|  |  | ||||||
|  | @ -32,6 +32,8 @@ | ||||||
| #include "nouveau_dma.h" | #include "nouveau_dma.h" | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| 
 | 
 | ||||||
|  | #include "nv50_display.h" | ||||||
|  | 
 | ||||||
| struct nvc0_fence_priv { | struct nvc0_fence_priv { | ||||||
| 	struct nouveau_fence_priv base; | 	struct nouveau_fence_priv base; | ||||||
| 	struct nouveau_bo *bo; | 	struct nouveau_bo *bo; | ||||||
|  | @ -114,13 +116,13 @@ nvc0_fence_context_del(struct nouveau_channel *chan) | ||||||
| 
 | 
 | ||||||
| 	if (nv_device(chan->drm->device)->card_type >= NV_D0) { | 	if (nv_device(chan->drm->device)->card_type >= NV_D0) { | ||||||
| 		for (i = 0; i < dev->mode_config.num_crtc; i++) { | 		for (i = 0; i < dev->mode_config.num_crtc; i++) { | ||||||
| 			struct nouveau_bo *bo = nvd0sema(dev, i); | 			struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); | ||||||
| 			nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); | 			nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); | ||||||
| 		} | 		} | ||||||
| 	} else | 	} else | ||||||
| 	if (nv_device(chan->drm->device)->card_type >= NV_50) { | 	if (nv_device(chan->drm->device)->card_type >= NV_50) { | ||||||
| 		for (i = 0; i < dev->mode_config.num_crtc; i++) { | 		for (i = 0; i < dev->mode_config.num_crtc; i++) { | ||||||
| 			struct nouveau_bo *bo = nv50sema(dev, i); | 			struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); | ||||||
| 			nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); | 			nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -154,9 +156,9 @@ nvc0_fence_context_new(struct nouveau_channel *chan) | ||||||
| 	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { | 	for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { | ||||||
| 		struct nouveau_bo *bo; | 		struct nouveau_bo *bo; | ||||||
| 		if (nv_device(chan->drm->device)->card_type >= NV_D0) | 		if (nv_device(chan->drm->device)->card_type >= NV_D0) | ||||||
| 			bo = nvd0sema(chan->drm->dev, i); | 			bo = nvd0_display_crtc_sema(chan->drm->dev, i); | ||||||
| 		else | 		else | ||||||
| 			bo = nv50sema(chan->drm->dev, i); | 			bo = nv50_display_crtc_sema(chan->drm->dev, i); | ||||||
| 
 | 
 | ||||||
| 		ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); | 		ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -22,18 +22,24 @@ | ||||||
|  * Authors: Ben Skeggs |  * Authors: Ben Skeggs | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| #include "drmP.h" | #include "nouveau_drm.h" | ||||||
| #include "nouveau_drv.h" | #include "nouveau_bios.h" | ||||||
| #include <nouveau_bios.h> |  | ||||||
| #include "nouveau_pm.h" | #include "nouveau_pm.h" | ||||||
| 
 | 
 | ||||||
|  | #include <subdev/bios/pll.h> | ||||||
|  | #include <subdev/bios.h> | ||||||
|  | #include <subdev/clock.h> | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | #include <subdev/fb.h> | ||||||
|  | 
 | ||||||
| static u32 read_div(struct drm_device *, int, u32, u32); | static u32 read_div(struct drm_device *, int, u32, u32); | ||||||
| static u32 read_pll(struct drm_device *, u32); | static u32 read_pll(struct drm_device *, u32); | ||||||
| 
 | 
 | ||||||
| static u32 | static u32 | ||||||
| read_vco(struct drm_device *dev, u32 dsrc) | read_vco(struct drm_device *dev, u32 dsrc) | ||||||
| { | { | ||||||
| 	u32 ssrc = nv_rd32(dev, dsrc); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	u32 ssrc = nv_rd32(device, dsrc); | ||||||
| 	if (!(ssrc & 0x00000100)) | 	if (!(ssrc & 0x00000100)) | ||||||
| 		return read_pll(dev, 0x00e800); | 		return read_pll(dev, 0x00e800); | ||||||
| 	return read_pll(dev, 0x00e820); | 	return read_pll(dev, 0x00e820); | ||||||
|  | @ -42,8 +48,9 @@ read_vco(struct drm_device *dev, u32 dsrc) | ||||||
| static u32 | static u32 | ||||||
| read_pll(struct drm_device *dev, u32 pll) | read_pll(struct drm_device *dev, u32 pll) | ||||||
| { | { | ||||||
| 	u32 ctrl = nv_rd32(dev, pll + 0); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 coef = nv_rd32(dev, pll + 4); | 	u32 ctrl = nv_rd32(device, pll + 0); | ||||||
|  | 	u32 coef = nv_rd32(device, pll + 4); | ||||||
| 	u32 P = (coef & 0x003f0000) >> 16; | 	u32 P = (coef & 0x003f0000) >> 16; | ||||||
| 	u32 N = (coef & 0x0000ff00) >> 8; | 	u32 N = (coef & 0x0000ff00) >> 8; | ||||||
| 	u32 M = (coef & 0x000000ff) >> 0; | 	u32 M = (coef & 0x000000ff) >> 0; | ||||||
|  | @ -83,8 +90,9 @@ read_pll(struct drm_device *dev, u32 pll) | ||||||
| static u32 | static u32 | ||||||
| read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) | read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) | ||||||
| { | { | ||||||
| 	u32 ssrc = nv_rd32(dev, dsrc + (doff * 4)); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 sctl = nv_rd32(dev, dctl + (doff * 4)); | 	u32 ssrc = nv_rd32(device, dsrc + (doff * 4)); | ||||||
|  | 	u32 sctl = nv_rd32(device, dctl + (doff * 4)); | ||||||
| 
 | 
 | ||||||
| 	switch (ssrc & 0x00000003) { | 	switch (ssrc & 0x00000003) { | ||||||
| 	case 0: | 	case 0: | ||||||
|  | @ -109,7 +117,8 @@ read_div(struct drm_device *dev, int doff, u32 dsrc, u32 dctl) | ||||||
| static u32 | static u32 | ||||||
| read_mem(struct drm_device *dev) | read_mem(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	u32 ssel = nv_rd32(dev, 0x1373f0); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	u32 ssel = nv_rd32(device, 0x1373f0); | ||||||
| 	if (ssel & 0x00000001) | 	if (ssel & 0x00000001) | ||||||
| 		return read_div(dev, 0, 0x137300, 0x137310); | 		return read_div(dev, 0, 0x137300, 0x137310); | ||||||
| 	return read_pll(dev, 0x132000); | 	return read_pll(dev, 0x132000); | ||||||
|  | @ -118,8 +127,9 @@ read_mem(struct drm_device *dev) | ||||||
| static u32 | static u32 | ||||||
| read_clk(struct drm_device *dev, int clk) | read_clk(struct drm_device *dev, int clk) | ||||||
| { | { | ||||||
| 	u32 sctl = nv_rd32(dev, 0x137250 + (clk * 4)); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	u32 ssel = nv_rd32(dev, 0x137100); | 	u32 sctl = nv_rd32(device, 0x137250 + (clk * 4)); | ||||||
|  | 	u32 ssel = nv_rd32(device, 0x137100); | ||||||
| 	u32 sclk, sdiv; | 	u32 sclk, sdiv; | ||||||
| 
 | 
 | ||||||
| 	if (ssel & (1 << clk)) { | 	if (ssel & (1 << clk)) { | ||||||
|  | @ -212,10 +222,12 @@ calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) | ||||||
| static u32 | static u32 | ||||||
| calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) | calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
| 	struct nvbios_pll limits; | 	struct nvbios_pll limits; | ||||||
| 	int N, M, P, ret; | 	int N, M, P, ret; | ||||||
| 
 | 
 | ||||||
| 	ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); | 	ret = nvbios_pll_parse(bios, 0x137000 + (clk * 0x20), &limits); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		return 0; | 		return 0; | ||||||
| 
 | 
 | ||||||
|  | @ -308,31 +320,33 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) | ||||||
| static int | static int | ||||||
| calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) | calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_bios *bios = nouveau_bios(device); | ||||||
| 	struct nvbios_pll pll; | 	struct nvbios_pll pll; | ||||||
| 	int N, M, P, ret; | 	int N, M, P, ret; | ||||||
| 	u32 ctrl; | 	u32 ctrl; | ||||||
| 
 | 
 | ||||||
| 	/* mclk pll input freq comes from another pll, make sure it's on */ | 	/* mclk pll input freq comes from another pll, make sure it's on */ | ||||||
| 	ctrl = nv_rd32(dev, 0x132020); | 	ctrl = nv_rd32(device, 0x132020); | ||||||
| 	if (!(ctrl & 0x00000001)) { | 	if (!(ctrl & 0x00000001)) { | ||||||
| 		/* if not, program it to 567MHz.  nfi where this value comes
 | 		/* if not, program it to 567MHz.  nfi where this value comes
 | ||||||
| 		 * from - it looks like it's in the pll limits table for | 		 * from - it looks like it's in the pll limits table for | ||||||
| 		 * 132000 but the binary driver ignores all my attempts to | 		 * 132000 but the binary driver ignores all my attempts to | ||||||
| 		 * change this value. | 		 * change this value. | ||||||
| 		 */ | 		 */ | ||||||
| 		nv_wr32(dev, 0x137320, 0x00000103); | 		nv_wr32(device, 0x137320, 0x00000103); | ||||||
| 		nv_wr32(dev, 0x137330, 0x81200606); | 		nv_wr32(device, 0x137330, 0x81200606); | ||||||
| 		nv_wait(dev, 0x132020, 0x00010000, 0x00010000); | 		nv_wait(device, 0x132020, 0x00010000, 0x00010000); | ||||||
| 		nv_wr32(dev, 0x132024, 0x0001150f); | 		nv_wr32(device, 0x132024, 0x0001150f); | ||||||
| 		nv_mask(dev, 0x132020, 0x00000001, 0x00000001); | 		nv_mask(device, 0x132020, 0x00000001, 0x00000001); | ||||||
| 		nv_wait(dev, 0x137390, 0x00020000, 0x00020000); | 		nv_wait(device, 0x137390, 0x00020000, 0x00020000); | ||||||
| 		nv_mask(dev, 0x132020, 0x00000004, 0x00000004); | 		nv_mask(device, 0x132020, 0x00000004, 0x00000004); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* for the moment, until the clock tree is better understood, use
 | 	/* for the moment, until the clock tree is better understood, use
 | ||||||
| 	 * pll mode for all clock frequencies | 	 * pll mode for all clock frequencies | ||||||
| 	 */ | 	 */ | ||||||
| 	ret = get_pll_limits(dev, 0x132000, &pll); | 	ret = nvbios_pll_parse(bios, 0x132000, &pll); | ||||||
| 	if (ret == 0) { | 	if (ret == 0) { | ||||||
| 		pll.refclk = read_pll(dev, 0x132020); | 		pll.refclk = read_pll(dev, 0x132020); | ||||||
| 		if (pll.refclk) { | 		if (pll.refclk) { | ||||||
|  | @ -350,7 +364,7 @@ calc_mem(struct drm_device *dev, struct nvc0_pm_clock *info, u32 freq) | ||||||
| void * | void * | ||||||
| nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nvc0_pm_state *info; | 	struct nvc0_pm_state *info; | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
|  | @ -364,7 +378,7 @@ nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| 	 * are always the same freq with the binary driver even when the | 	 * are always the same freq with the binary driver even when the | ||||||
| 	 * performance table says they should differ. | 	 * performance table says they should differ. | ||||||
| 	 */ | 	 */ | ||||||
| 	if (dev_priv->chipset == 0xd9) | 	if (device->chipset == 0xd9) | ||||||
| 		perflvl->rop = 0; | 		perflvl->rop = 0; | ||||||
| 
 | 
 | ||||||
| 	if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) || | 	if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) || | ||||||
|  | @ -394,38 +408,40 @@ nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | ||||||
| static void | static void | ||||||
| prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info) | prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 
 | ||||||
| 	/* program dividers at 137160/1371d0 first */ | 	/* program dividers at 137160/1371d0 first */ | ||||||
| 	if (clk < 7 && !info->ssel) { | 	if (clk < 7 && !info->ssel) { | ||||||
| 		nv_mask(dev, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); | 		nv_mask(device, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); | ||||||
| 		nv_wr32(dev, 0x137160 + (clk * 0x04), info->dsrc); | 		nv_wr32(device, 0x137160 + (clk * 0x04), info->dsrc); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* switch clock to non-pll mode */ | 	/* switch clock to non-pll mode */ | ||||||
| 	nv_mask(dev, 0x137100, (1 << clk), 0x00000000); | 	nv_mask(device, 0x137100, (1 << clk), 0x00000000); | ||||||
| 	nv_wait(dev, 0x137100, (1 << clk), 0x00000000); | 	nv_wait(device, 0x137100, (1 << clk), 0x00000000); | ||||||
| 
 | 
 | ||||||
| 	/* reprogram pll */ | 	/* reprogram pll */ | ||||||
| 	if (clk < 7) { | 	if (clk < 7) { | ||||||
| 		/* make sure it's disabled first... */ | 		/* make sure it's disabled first... */ | ||||||
| 		u32 base = 0x137000 + (clk * 0x20); | 		u32 base = 0x137000 + (clk * 0x20); | ||||||
| 		u32 ctrl = nv_rd32(dev, base + 0x00); | 		u32 ctrl = nv_rd32(device, base + 0x00); | ||||||
| 		if (ctrl & 0x00000001) { | 		if (ctrl & 0x00000001) { | ||||||
| 			nv_mask(dev, base + 0x00, 0x00000004, 0x00000000); | 			nv_mask(device, base + 0x00, 0x00000004, 0x00000000); | ||||||
| 			nv_mask(dev, base + 0x00, 0x00000001, 0x00000000); | 			nv_mask(device, base + 0x00, 0x00000001, 0x00000000); | ||||||
| 		} | 		} | ||||||
| 		/* program it to new values, if necessary */ | 		/* program it to new values, if necessary */ | ||||||
| 		if (info->ssel) { | 		if (info->ssel) { | ||||||
| 			nv_wr32(dev, base + 0x04, info->coef); | 			nv_wr32(device, base + 0x04, info->coef); | ||||||
| 			nv_mask(dev, base + 0x00, 0x00000001, 0x00000001); | 			nv_mask(device, base + 0x00, 0x00000001, 0x00000001); | ||||||
| 			nv_wait(dev, base + 0x00, 0x00020000, 0x00020000); | 			nv_wait(device, base + 0x00, 0x00020000, 0x00020000); | ||||||
| 			nv_mask(dev, base + 0x00, 0x00020004, 0x00000004); | 			nv_mask(device, base + 0x00, 0x00020004, 0x00000004); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* select pll/non-pll mode, and program final clock divider */ | 	/* select pll/non-pll mode, and program final clock divider */ | ||||||
| 	nv_mask(dev, 0x137100, (1 << clk), info->ssel); | 	nv_mask(device, 0x137100, (1 << clk), info->ssel); | ||||||
| 	nv_wait(dev, 0x137100, (1 << clk), info->ssel); | 	nv_wait(device, 0x137100, (1 << clk), info->ssel); | ||||||
| 	nv_mask(dev, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); | 	nv_mask(device, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -441,7 +457,8 @@ mclk_refresh(struct nouveau_mem_exec_func *exec) | ||||||
| static void | static void | ||||||
| mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) | mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) | ||||||
| { | { | ||||||
| 	nv_wr32(exec->dev, 0x10f210, enable ? 0x80000000 : 0x00000000); | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
|  | 	nv_wr32(device, 0x10f210, enable ? 0x80000000 : 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -458,81 +475,84 @@ mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) | ||||||
| static u32 | static u32 | ||||||
| mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = exec->dev; | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
|  | 	if (pfb->ram.type != NV_MEM_TYPE_GDDR5) { | ||||||
| 		if (mr <= 1) | 		if (mr <= 1) | ||||||
| 			return nv_rd32(dev, 0x10f300 + ((mr - 0) * 4)); | 			return nv_rd32(device, 0x10f300 + ((mr - 0) * 4)); | ||||||
| 		return nv_rd32(dev, 0x10f320 + ((mr - 2) * 4)); | 		return nv_rd32(device, 0x10f320 + ((mr - 2) * 4)); | ||||||
| 	} else { | 	} else { | ||||||
| 		if (mr == 0) | 		if (mr == 0) | ||||||
| 			return nv_rd32(dev, 0x10f300 + (mr * 4)); | 			return nv_rd32(device, 0x10f300 + (mr * 4)); | ||||||
| 		else | 		else | ||||||
| 		if (mr <= 7) | 		if (mr <= 7) | ||||||
| 			return nv_rd32(dev, 0x10f32c + (mr * 4)); | 			return nv_rd32(device, 0x10f32c + (mr * 4)); | ||||||
| 		return nv_rd32(dev, 0x10f34c); | 		return nv_rd32(device, 0x10f34c); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = exec->dev; | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	if (nvfb_vram_type(dev) != NV_MEM_TYPE_GDDR5) { | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
|  | 	if (pfb->ram.type != NV_MEM_TYPE_GDDR5) { | ||||||
| 		if (mr <= 1) { | 		if (mr <= 1) { | ||||||
| 			nv_wr32(dev, 0x10f300 + ((mr - 0) * 4), data); | 			nv_wr32(device, 0x10f300 + ((mr - 0) * 4), data); | ||||||
| 			if (nvfb_vram_rank_B(dev)) | 			if (pfb->ram.ranks > 1) | ||||||
| 				nv_wr32(dev, 0x10f308 + ((mr - 0) * 4), data); | 				nv_wr32(device, 0x10f308 + ((mr - 0) * 4), data); | ||||||
| 		} else | 		} else | ||||||
| 		if (mr <= 3) { | 		if (mr <= 3) { | ||||||
| 			nv_wr32(dev, 0x10f320 + ((mr - 2) * 4), data); | 			nv_wr32(device, 0x10f320 + ((mr - 2) * 4), data); | ||||||
| 			if (nvfb_vram_rank_B(dev)) | 			if (pfb->ram.ranks > 1) | ||||||
| 				nv_wr32(dev, 0x10f328 + ((mr - 2) * 4), data); | 				nv_wr32(device, 0x10f328 + ((mr - 2) * 4), data); | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		if      (mr ==  0) nv_wr32(dev, 0x10f300 + (mr * 4), data); | 		if      (mr ==  0) nv_wr32(device, 0x10f300 + (mr * 4), data); | ||||||
| 		else if (mr <=  7) nv_wr32(dev, 0x10f32c + (mr * 4), data); | 		else if (mr <=  7) nv_wr32(device, 0x10f32c + (mr * 4), data); | ||||||
| 		else if (mr == 15) nv_wr32(dev, 0x10f34c, data); | 		else if (mr == 15) nv_wr32(device, 0x10f34c, data); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_clock_set(struct nouveau_mem_exec_func *exec) | mclk_clock_set(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	struct nvc0_pm_state *info = exec->priv; | 	struct nvc0_pm_state *info = exec->priv; | ||||||
| 	struct drm_device *dev = exec->dev; | 	u32 ctrl = nv_rd32(device, 0x132000); | ||||||
| 	u32 ctrl = nv_rd32(dev, 0x132000); |  | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x137360, 0x00000001); | 	nv_wr32(device, 0x137360, 0x00000001); | ||||||
| 	nv_wr32(dev, 0x137370, 0x00000000); | 	nv_wr32(device, 0x137370, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x137380, 0x00000000); | 	nv_wr32(device, 0x137380, 0x00000000); | ||||||
| 	if (ctrl & 0x00000001) | 	if (ctrl & 0x00000001) | ||||||
| 		nv_wr32(dev, 0x132000, (ctrl &= ~0x00000001)); | 		nv_wr32(device, 0x132000, (ctrl &= ~0x00000001)); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x132004, info->mem.coef); | 	nv_wr32(device, 0x132004, info->mem.coef); | ||||||
| 	nv_wr32(dev, 0x132000, (ctrl |= 0x00000001)); | 	nv_wr32(device, 0x132000, (ctrl |= 0x00000001)); | ||||||
| 	nv_wait(dev, 0x137390, 0x00000002, 0x00000002); | 	nv_wait(device, 0x137390, 0x00000002, 0x00000002); | ||||||
| 	nv_wr32(dev, 0x132018, 0x00005000); | 	nv_wr32(device, 0x132018, 0x00005000); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x137370, 0x00000001); | 	nv_wr32(device, 0x137370, 0x00000001); | ||||||
| 	nv_wr32(dev, 0x137380, 0x00000001); | 	nv_wr32(device, 0x137380, 0x00000001); | ||||||
| 	nv_wr32(dev, 0x137360, 0x00000000); | 	nv_wr32(device, 0x137360, 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| mclk_timing_set(struct nouveau_mem_exec_func *exec) | mclk_timing_set(struct nouveau_mem_exec_func *exec) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(exec->dev); | ||||||
| 	struct nvc0_pm_state *info = exec->priv; | 	struct nvc0_pm_state *info = exec->priv; | ||||||
| 	struct nouveau_pm_level *perflvl = info->perflvl; | 	struct nouveau_pm_level *perflvl = info->perflvl; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 5; i++) | 	for (i = 0; i < 5; i++) | ||||||
| 		nv_wr32(exec->dev, 0x10f290 + (i * 4), perflvl->timing.reg[i]); | 		nv_wr32(device, 0x10f290 + (i * 4), perflvl->timing.reg[i]); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) | prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nouveau_mem_exec_func exec = { | 	struct nouveau_mem_exec_func exec = { | ||||||
| 		.dev = dev, | 		.dev = dev, | ||||||
| 		.precharge = mclk_precharge, | 		.precharge = mclk_precharge, | ||||||
|  | @ -547,17 +567,17 @@ prog_mem(struct drm_device *dev, struct nvc0_pm_state *info) | ||||||
| 		.priv = info | 		.priv = info | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset < 0xd0) | 	if (device->chipset < 0xd0) | ||||||
| 		nv_wr32(dev, 0x611200, 0x00003300); | 		nv_wr32(device, 0x611200, 0x00003300); | ||||||
| 	else | 	else | ||||||
| 		nv_wr32(dev, 0x62c000, 0x03030000); | 		nv_wr32(device, 0x62c000, 0x03030000); | ||||||
| 
 | 
 | ||||||
| 	nouveau_mem_exec(&exec, info->perflvl); | 	nouveau_mem_exec(&exec, info->perflvl); | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->chipset < 0xd0) | 	if (device->chipset < 0xd0) | ||||||
| 		nv_wr32(dev, 0x611200, 0x00003330); | 		nv_wr32(device, 0x611200, 0x00003330); | ||||||
| 	else | 	else | ||||||
| 		nv_wr32(dev, 0x62c000, 0x03030300); | 		nv_wr32(device, 0x62c000, 0x03030300); | ||||||
| } | } | ||||||
| int | int | ||||||
| nvc0_pm_clocks_set(struct drm_device *dev, void *data) | nvc0_pm_clocks_set(struct drm_device *dev, void *data) | ||||||
|  |  | ||||||
|  | @ -27,14 +27,21 @@ | ||||||
| #include "drmP.h" | #include "drmP.h" | ||||||
| #include "drm_crtc_helper.h" | #include "drm_crtc_helper.h" | ||||||
| 
 | 
 | ||||||
| #include "nouveau_drv.h" | #include "nouveau_drm.h" | ||||||
|  | #include "nouveau_dma.h" | ||||||
|  | #include "nouveau_gem.h" | ||||||
| #include "nouveau_connector.h" | #include "nouveau_connector.h" | ||||||
| #include "nouveau_encoder.h" | #include "nouveau_encoder.h" | ||||||
| #include "nouveau_crtc.h" | #include "nouveau_crtc.h" | ||||||
| #include "nouveau_fb.h" |  | ||||||
| #include "nouveau_fence.h" | #include "nouveau_fence.h" | ||||||
| #include "nv50_display.h" | #include "nv50_display.h" | ||||||
| 
 | 
 | ||||||
|  | #include <core/gpuobj.h> | ||||||
|  | 
 | ||||||
|  | #include <subdev/timer.h> | ||||||
|  | #include <subdev/bar.h> | ||||||
|  | #include <subdev/fb.h> | ||||||
|  | 
 | ||||||
| #define EVO_DMA_NR 9 | #define EVO_DMA_NR 9 | ||||||
| 
 | 
 | ||||||
| #define EVO_MASTER  (0x00) | #define EVO_MASTER  (0x00) | ||||||
|  | @ -71,8 +78,7 @@ struct nvd0_display { | ||||||
| static struct nvd0_display * | static struct nvd0_display * | ||||||
| nvd0_display(struct drm_device *dev) | nvd0_display(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	return nouveau_display(dev)->priv; | ||||||
| 	return dev_priv->engine.display.priv; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static struct drm_crtc * | static struct drm_crtc * | ||||||
|  | @ -87,28 +93,31 @@ nvd0_display_crtc_get(struct drm_encoder *encoder) | ||||||
| static inline int | static inline int | ||||||
| evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) | evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int ret = 0; | 	int ret = 0; | ||||||
| 	nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); | 	nv_mask(device, 0x610700 + (id * 0x10), 0x00000001, 0x00000001); | ||||||
| 	nv_wr32(dev, 0x610704 + (id * 0x10), data); | 	nv_wr32(device, 0x610704 + (id * 0x10), data); | ||||||
| 	nv_mask(dev, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); | 	nv_mask(device, 0x610704 + (id * 0x10), 0x80000ffc, 0x80000000 | mthd); | ||||||
| 	if (!nv_wait(dev, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) | 	if (!nv_wait(device, 0x610704 + (id * 0x10), 0x80000000, 0x00000000)) | ||||||
| 		ret = -EBUSY; | 		ret = -EBUSY; | ||||||
| 	nv_mask(dev, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); | 	nv_mask(device, 0x610700 + (id * 0x10), 0x00000001, 0x00000000); | ||||||
| 	return ret; | 	return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static u32 * | static u32 * | ||||||
| evo_wait(struct drm_device *dev, int id, int nr) | evo_wait(struct drm_device *dev, int id, int nr) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 	u32 put = nv_rd32(dev, 0x640000 + (id * 0x1000)) / 4; | 	u32 put = nv_rd32(device, 0x640000 + (id * 0x1000)) / 4; | ||||||
| 
 | 
 | ||||||
| 	if (put + nr >= (PAGE_SIZE / 4)) { | 	if (put + nr >= (PAGE_SIZE / 4)) { | ||||||
| 		disp->evo[id].ptr[put] = 0x20000000; | 		disp->evo[id].ptr[put] = 0x20000000; | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, 0x640000 + (id * 0x1000), 0x00000000); | 		nv_wr32(device, 0x640000 + (id * 0x1000), 0x00000000); | ||||||
| 		if (!nv_wait(dev, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { | 		if (!nv_wait(device, 0x640004 + (id * 0x1000), ~0, 0x00000000)) { | ||||||
| 			NV_ERROR(dev, "evo %d dma stalled\n", id); | 			NV_ERROR(drm, "evo %d dma stalled\n", id); | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -121,9 +130,10 @@ evo_wait(struct drm_device *dev, int id, int nr) | ||||||
| static void | static void | ||||||
| evo_kick(u32 *push, struct drm_device *dev, int id) | evo_kick(u32 *push, struct drm_device *dev, int id) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); | 	nv_wr32(device, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) | #define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) | ||||||
|  | @ -132,6 +142,8 @@ evo_kick(u32 *push, struct drm_device *dev, int id) | ||||||
| static int | static int | ||||||
| evo_init_dma(struct drm_device *dev, int ch) | evo_init_dma(struct drm_device *dev, int ch) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 	u32 flags; | 	u32 flags; | ||||||
| 
 | 
 | ||||||
|  | @ -139,68 +151,76 @@ evo_init_dma(struct drm_device *dev, int ch) | ||||||
| 	if (ch == EVO_MASTER) | 	if (ch == EVO_MASTER) | ||||||
| 		flags |= 0x01000000; | 		flags |= 0x01000000; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3); | 	nv_wr32(device, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3); | ||||||
| 	nv_wr32(dev, 0x610498 + (ch * 0x0010), 0x00010000); | 	nv_wr32(device, 0x610498 + (ch * 0x0010), 0x00010000); | ||||||
| 	nv_wr32(dev, 0x61049c + (ch * 0x0010), 0x00000001); | 	nv_wr32(device, 0x61049c + (ch * 0x0010), 0x00000001); | ||||||
| 	nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); | 	nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); | ||||||
| 	nv_wr32(dev, 0x640000 + (ch * 0x1000), 0x00000000); | 	nv_wr32(device, 0x640000 + (ch * 0x1000), 0x00000000); | ||||||
| 	nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000013 | flags); | 	nv_wr32(device, 0x610490 + (ch * 0x0010), 0x00000013 | flags); | ||||||
| 	if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) { | 	if (!nv_wait(device, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) { | ||||||
| 		NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, | 		NV_ERROR(drm, "PDISP: ch%d 0x%08x\n", ch, | ||||||
| 			      nv_rd32(dev, 0x610490 + (ch * 0x0010))); | 			      nv_rd32(device, 0x610490 + (ch * 0x0010))); | ||||||
| 		return -EBUSY; | 		return -EBUSY; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); | 	nv_mask(device, 0x610090, (1 << ch), (1 << ch)); | ||||||
| 	nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); | 	nv_mask(device, 0x6100a0, (1 << ch), (1 << ch)); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| evo_fini_dma(struct drm_device *dev, int ch) | evo_fini_dma(struct drm_device *dev, int ch) | ||||||
| { | { | ||||||
| 	if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000010)) | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!(nv_rd32(device, 0x610490 + (ch * 0x0010)) & 0x00000010)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000); | 	nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000); | ||||||
| 	nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000); | 	nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000); | ||||||
| 	nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000); | 	nv_wait(device, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000); | ||||||
| 	nv_mask(dev, 0x610090, (1 << ch), 0x00000000); | 	nv_mask(device, 0x610090, (1 << ch), 0x00000000); | ||||||
| 	nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); | 	nv_mask(device, 0x6100a0, (1 << ch), 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static inline void | static inline void | ||||||
| evo_piow(struct drm_device *dev, int ch, u16 mthd, u32 data) | evo_piow(struct drm_device *dev, int ch, u16 mthd, u32 data) | ||||||
| { | { | ||||||
| 	nv_wr32(dev, 0x640000 + (ch * 0x1000) + mthd, data); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	nv_wr32(device, 0x640000 + (ch * 0x1000) + mthd, data); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static int | static int | ||||||
| evo_init_pio(struct drm_device *dev, int ch) | evo_init_pio(struct drm_device *dev, int ch) | ||||||
| { | { | ||||||
| 	nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000001); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) { | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 		NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, | 
 | ||||||
| 			      nv_rd32(dev, 0x610490 + (ch * 0x0010))); | 	nv_wr32(device, 0x610490 + (ch * 0x0010), 0x00000001); | ||||||
|  | 	if (!nv_wait(device, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) { | ||||||
|  | 		NV_ERROR(drm, "PDISP: ch%d 0x%08x\n", ch, | ||||||
|  | 			      nv_rd32(device, 0x610490 + (ch * 0x0010))); | ||||||
| 		return -EBUSY; | 		return -EBUSY; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); | 	nv_mask(device, 0x610090, (1 << ch), (1 << ch)); | ||||||
| 	nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); | 	nv_mask(device, 0x6100a0, (1 << ch), (1 << ch)); | ||||||
| 	return 0; | 	return 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| evo_fini_pio(struct drm_device *dev, int ch) | evo_fini_pio(struct drm_device *dev, int ch) | ||||||
| { | { | ||||||
| 	if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000001)) | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 
 | ||||||
|  | 	if (!(nv_rd32(device, 0x610490 + (ch * 0x0010)) & 0x00000001)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); | 	nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); | ||||||
| 	nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000); | 	nv_mask(device, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000); | ||||||
| 	nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000); | 	nv_wait(device, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000); | ||||||
| 	nv_mask(dev, 0x610090, (1 << ch), 0x00000000); | 	nv_mask(device, 0x610090, (1 << ch), 0x00000000); | ||||||
| 	nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); | 	nv_mask(device, 0x6100a0, (1 << ch), 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
|  | @ -212,6 +232,7 @@ evo_sync_wait(void *data) | ||||||
| static int | static int | ||||||
| evo_sync(struct drm_device *dev, int ch) | evo_sync(struct drm_device *dev, int ch) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 	u32 *push = evo_wait(dev, ch, 8); | 	u32 *push = evo_wait(dev, ch, 8); | ||||||
| 	if (push) { | 	if (push) { | ||||||
|  | @ -222,7 +243,7 @@ evo_sync(struct drm_device *dev, int ch) | ||||||
| 		evo_data(push, 0x00000000); | 		evo_data(push, 0x00000000); | ||||||
| 		evo_data(push, 0x00000000); | 		evo_data(push, 0x00000000); | ||||||
| 		evo_kick(push, dev, ch); | 		evo_kick(push, dev, ch); | ||||||
| 		if (nv_wait_cb(dev, evo_sync_wait, disp->sync)) | 		if (nv_wait_cb(device, evo_sync_wait, disp->sync)) | ||||||
| 			return 0; | 			return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -350,7 +371,7 @@ nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | ||||||
| static int | static int | ||||||
| nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) | nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(nv_crtc->base.dev); | ||||||
| 	struct drm_device *dev = nv_crtc->base.dev; | 	struct drm_device *dev = nv_crtc->base.dev; | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct drm_connector *connector; | 	struct drm_connector *connector; | ||||||
|  | @ -373,7 +394,7 @@ nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) | ||||||
| 		mode |= nv_connector->dithering_depth; | 		mode |= nv_connector->dithering_depth; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (dev_priv->card_type < NV_E0) | 	if (nv_device(drm->device)->card_type < NV_E0) | ||||||
| 		mthd = 0x0490 + (nv_crtc->index * 0x0300); | 		mthd = 0x0490 + (nv_crtc->index * 0x0300); | ||||||
| 	else | 	else | ||||||
| 		mthd = 0x04a0 + (nv_crtc->index * 0x0300); | 		mthd = 0x04a0 + (nv_crtc->index * 0x0300); | ||||||
|  | @ -688,11 +709,12 @@ static int | ||||||
| nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | ||||||
| 			struct drm_framebuffer *old_fb) | 			struct drm_framebuffer *old_fb) | ||||||
| { | { | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(crtc->dev); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | ||||||
| 	int ret; | 	int ret; | ||||||
| 
 | 
 | ||||||
| 	if (!crtc->fb) { | 	if (!crtc->fb) { | ||||||
| 		NV_DEBUG_KMS(crtc->dev, "No FB bound\n"); | 		NV_DEBUG(drm, "No FB bound\n"); | ||||||
| 		return 0; | 		return 0; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -910,6 +932,7 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 dpms_ctrl; | 	u32 dpms_ctrl; | ||||||
| 
 | 
 | ||||||
|  | @ -919,9 +942,9 @@ nvd0_dac_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 	if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) | 	if (mode == DRM_MODE_DPMS_SUSPEND || mode == DRM_MODE_DPMS_OFF) | ||||||
| 		dpms_ctrl |= 0x00000004; | 		dpms_ctrl |= 0x00000004; | ||||||
| 
 | 
 | ||||||
| 	nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); | 	nv_wait(device, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); | ||||||
| 	nv_mask(dev, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); | 	nv_mask(device, 0x61a004 + (or * 0x0800), 0xc000007f, dpms_ctrl); | ||||||
| 	nv_wait(dev, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); | 	nv_wait(device, 0x61a004 + (or * 0x0800), 0x80000000, 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static bool | static bool | ||||||
|  | @ -1012,18 +1035,19 @@ nvd0_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | ||||||
| 	enum drm_connector_status status = connector_status_disconnected; | 	enum drm_connector_status status = connector_status_disconnected; | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 load; | 	u32 load; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00100000); | 	nv_wr32(device, 0x61a00c + (or * 0x800), 0x00100000); | ||||||
| 	udelay(9500); | 	udelay(9500); | ||||||
| 	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x80000000); | 	nv_wr32(device, 0x61a00c + (or * 0x800), 0x80000000); | ||||||
| 
 | 
 | ||||||
| 	load = nv_rd32(dev, 0x61a00c + (or * 0x800)); | 	load = nv_rd32(device, 0x61a00c + (or * 0x800)); | ||||||
| 	if ((load & 0x38000000) == 0x38000000) | 	if ((load & 0x38000000) == 0x38000000) | ||||||
| 		status = connector_status_connected; | 		status = connector_status_connected; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x61a00c + (or * 0x800), 0x00000000); | 	nv_wr32(device, 0x61a00c + (or * 0x800), 0x00000000); | ||||||
| 	return status; | 	return status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1081,24 +1105,25 @@ nvd0_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int i, or = nv_encoder->or * 0x30; | 	int i, or = nv_encoder->or * 0x30; | ||||||
| 
 | 
 | ||||||
| 	nv_connector = nouveau_encoder_connector_get(nv_encoder); | 	nv_connector = nouveau_encoder_connector_get(nv_encoder); | ||||||
| 	if (!drm_detect_monitor_audio(nv_connector->edid)) | 	if (!drm_detect_monitor_audio(nv_connector->edid)) | ||||||
| 		return; | 		return; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000001); | 	nv_mask(device, 0x10ec10 + or, 0x80000003, 0x80000001); | ||||||
| 
 | 
 | ||||||
| 	drm_edid_to_eld(&nv_connector->base, nv_connector->edid); | 	drm_edid_to_eld(&nv_connector->base, nv_connector->edid); | ||||||
| 	if (nv_connector->base.eld[0]) { | 	if (nv_connector->base.eld[0]) { | ||||||
| 		u8 *eld = nv_connector->base.eld; | 		u8 *eld = nv_connector->base.eld; | ||||||
| 
 | 
 | ||||||
| 		for (i = 0; i < eld[2] * 4; i++) | 		for (i = 0; i < eld[2] * 4; i++) | ||||||
| 			nv_wr32(dev, 0x10ec00 + or, (i << 8) | eld[i]); | 			nv_wr32(device, 0x10ec00 + or, (i << 8) | eld[i]); | ||||||
| 		for (i = eld[2] * 4; i < 0x60; i++) | 		for (i = eld[2] * 4; i < 0x60; i++) | ||||||
| 			nv_wr32(dev, 0x10ec00 + or, (i << 8) | 0x00); | 			nv_wr32(device, 0x10ec00 + or, (i << 8) | 0x00); | ||||||
| 
 | 
 | ||||||
| 		nv_mask(dev, 0x10ec10 + or, 0x80000002, 0x80000002); | 		nv_mask(device, 0x10ec10 + or, 0x80000002, 0x80000002); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -1107,9 +1132,10 @@ nvd0_audio_disconnect(struct drm_encoder *encoder) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int or = nv_encoder->or * 0x30; | 	int or = nv_encoder->or * 0x30; | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000000); | 	nv_mask(device, 0x10ec10 + or, 0x80000003, 0x80000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|  | @ -1122,6 +1148,7 @@ nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int head = nv_crtc->index * 0x800; | 	int head = nv_crtc->index * 0x800; | ||||||
| 	u32 rekey = 56; /* binary driver, and tegra constant */ | 	u32 rekey = 56; /* binary driver, and tegra constant */ | ||||||
| 	u32 max_ac_packet; | 	u32 max_ac_packet; | ||||||
|  | @ -1136,25 +1163,25 @@ nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) | ||||||
| 	max_ac_packet /= 32; | 	max_ac_packet /= 32; | ||||||
| 
 | 
 | ||||||
| 	/* AVI InfoFrame */ | 	/* AVI InfoFrame */ | ||||||
| 	nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); | 	nv_mask(device, 0x616714 + head, 0x00000001, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x61671c + head, 0x000d0282); | 	nv_wr32(device, 0x61671c + head, 0x000d0282); | ||||||
| 	nv_wr32(dev, 0x616720 + head, 0x0000006f); | 	nv_wr32(device, 0x616720 + head, 0x0000006f); | ||||||
| 	nv_wr32(dev, 0x616724 + head, 0x00000000); | 	nv_wr32(device, 0x616724 + head, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x616728 + head, 0x00000000); | 	nv_wr32(device, 0x616728 + head, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x61672c + head, 0x00000000); | 	nv_wr32(device, 0x61672c + head, 0x00000000); | ||||||
| 	nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000001); | 	nv_mask(device, 0x616714 + head, 0x00000001, 0x00000001); | ||||||
| 
 | 
 | ||||||
| 	/* ??? InfoFrame? */ | 	/* ??? InfoFrame? */ | ||||||
| 	nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); | 	nv_mask(device, 0x6167a4 + head, 0x00000001, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6167ac + head, 0x00000010); | 	nv_wr32(device, 0x6167ac + head, 0x00000010); | ||||||
| 	nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000001); | 	nv_mask(device, 0x6167a4 + head, 0x00000001, 0x00000001); | ||||||
| 
 | 
 | ||||||
| 	/* HDMI_CTRL */ | 	/* HDMI_CTRL */ | ||||||
| 	nv_mask(dev, 0x616798 + head, 0x401f007f, 0x40000000 | rekey | | 	nv_mask(device, 0x616798 + head, 0x401f007f, 0x40000000 | rekey | | ||||||
| 						  max_ac_packet << 16); | 						  max_ac_packet << 16); | ||||||
| 
 | 
 | ||||||
| 	/* NFI, audio doesn't work without it though.. */ | 	/* NFI, audio doesn't work without it though.. */ | ||||||
| 	nv_mask(dev, 0x616548 + head, 0x00000070, 0x00000000); | 	nv_mask(device, 0x616548 + head, 0x00000070, 0x00000000); | ||||||
| 
 | 
 | ||||||
| 	nvd0_audio_mode_set(encoder, mode); | 	nvd0_audio_mode_set(encoder, mode); | ||||||
| } | } | ||||||
|  | @ -1165,13 +1192,14 @@ nvd0_hdmi_disconnect(struct drm_encoder *encoder) | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int head = nv_crtc->index * 0x800; | 	int head = nv_crtc->index * 0x800; | ||||||
| 
 | 
 | ||||||
| 	nvd0_audio_disconnect(encoder); | 	nvd0_audio_disconnect(encoder); | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x616798 + head, 0x40000000, 0x00000000); | 	nv_mask(device, 0x616798 + head, 0x40000000, 0x00000000); | ||||||
| 	nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); | 	nv_mask(device, 0x6167a4 + head, 0x00000001, 0x00000000); | ||||||
| 	nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); | 	nv_mask(device, 0x616714 + head, 0x00000001, 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|  | @ -1187,15 +1215,18 @@ nvd0_sor_dp_lane_map(struct drm_device *dev, struct dcb_output *dcb, u8 lane) | ||||||
| static void | static void | ||||||
| nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) | nvd0_sor_dp_train_set(struct drm_device *dev, struct dcb_output *dcb, u8 pattern) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	const u32 loff = (or * 0x800) + (link * 0x80); | 	const u32 loff = (or * 0x800) + (link * 0x80); | ||||||
| 	nv_mask(dev, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); | 	nv_mask(device, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 		      u8 lane, u8 swing, u8 preem) | 		      u8 lane, u8 swing, u8 preem) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	const u32 loff = (or * 0x800) + (link * 0x80); | 	const u32 loff = (or * 0x800) + (link * 0x80); | ||||||
| 	u32 shift = nvd0_sor_dp_lane_map(dev, dcb, lane); | 	u32 shift = nvd0_sor_dp_lane_map(dev, dcb, lane); | ||||||
|  | @ -1223,25 +1254,26 @@ nvd0_sor_dp_train_adj(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (!config) { | 	if (!config) { | ||||||
| 		NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n"); | 		NV_ERROR(drm, "PDISP: unsupported DP table for chipset\n"); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_mask(dev, 0x61c118 + loff, mask, config[1] << shift); | 	nv_mask(device, 0x61c118 + loff, mask, config[1] << shift); | ||||||
| 	nv_mask(dev, 0x61c120 + loff, mask, config[2] << shift); | 	nv_mask(device, 0x61c120 + loff, mask, config[2] << shift); | ||||||
| 	nv_mask(dev, 0x61c130 + loff, 0x0000ff00, config[3] << 8); | 	nv_mask(device, 0x61c130 + loff, 0x0000ff00, config[3] << 8); | ||||||
| 	nv_mask(dev, 0x61c13c + loff, 0x00000000, 0x00000000); | 	nv_mask(device, 0x61c13c + loff, 0x00000000, 0x00000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | ||||||
| 		     int link_nr, u32 link_bw, bool enhframe) | 		     int link_nr, u32 link_bw, bool enhframe) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	const u32 loff = (or * 0x800) + (link * 0x80); | 	const u32 loff = (or * 0x800) + (link * 0x80); | ||||||
| 	const u32 soff = (or * 0x800); | 	const u32 soff = (or * 0x800); | ||||||
| 	u32 dpctrl = nv_rd32(dev, 0x61c10c + loff) & ~0x001f4000; | 	u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & ~0x001f4000; | ||||||
| 	u32 clksor = nv_rd32(dev, 0x612300 + soff) & ~0x007c0000; | 	u32 clksor = nv_rd32(device, 0x612300 + soff) & ~0x007c0000; | ||||||
| 	u32 script = 0x0000, lane_mask = 0; | 	u32 script = 0x0000, lane_mask = 0; | ||||||
| 	u8 *table, *entry; | 	u8 *table, *entry; | ||||||
| 	int i; | 	int i; | ||||||
|  | @ -1271,20 +1303,21 @@ nvd0_sor_dp_link_set(struct drm_device *dev, struct dcb_output *dcb, int crtc, | ||||||
| 	for (i = 0; i < link_nr; i++) | 	for (i = 0; i < link_nr; i++) | ||||||
| 		lane_mask |= 1 << (nvd0_sor_dp_lane_map(dev, dcb, i) >> 3); | 		lane_mask |= 1 << (nvd0_sor_dp_lane_map(dev, dcb, i) >> 3); | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x612300 + soff, clksor); | 	nv_wr32(device, 0x612300 + soff, clksor); | ||||||
| 	nv_wr32(dev, 0x61c10c + loff, dpctrl); | 	nv_wr32(device, 0x61c10c + loff, dpctrl); | ||||||
| 	nv_mask(dev, 0x61c130 + loff, 0x0000000f, lane_mask); | 	nv_mask(device, 0x61c130 + loff, 0x0000000f, lane_mask); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_output *dcb, | nvd0_sor_dp_link_get(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 		     u32 *link_nr, u32 *link_bw) | 		     u32 *link_nr, u32 *link_bw) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | 	const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); | ||||||
| 	const u32 loff = (or * 0x800) + (link * 0x80); | 	const u32 loff = (or * 0x800) + (link * 0x80); | ||||||
| 	const u32 soff = (or * 0x800); | 	const u32 soff = (or * 0x800); | ||||||
| 	u32 dpctrl = nv_rd32(dev, 0x61c10c + loff) & 0x000f0000; | 	u32 dpctrl = nv_rd32(device, 0x61c10c + loff) & 0x000f0000; | ||||||
| 	u32 clksor = nv_rd32(dev, 0x612300 + soff); | 	u32 clksor = nv_rd32(device, 0x612300 + soff); | ||||||
| 
 | 
 | ||||||
| 	if      (dpctrl > 0x00030000) *link_nr = 4; | 	if      (dpctrl > 0x00030000) *link_nr = 4; | ||||||
| 	else if (dpctrl > 0x00010000) *link_nr = 2; | 	else if (dpctrl > 0x00010000) *link_nr = 2; | ||||||
|  | @ -1298,6 +1331,7 @@ static void | ||||||
| nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, | nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 		    u32 crtc, u32 datarate) | 		    u32 crtc, u32 datarate) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	const u32 symbol = 100000; | 	const u32 symbol = 100000; | ||||||
| 	const u32 TU = 64; | 	const u32 TU = 64; | ||||||
| 	u32 link_nr, link_bw; | 	u32 link_nr, link_bw; | ||||||
|  | @ -1317,7 +1351,7 @@ nvd0_sor_dp_calc_tu(struct drm_device *dev, struct dcb_output *dcb, | ||||||
| 	value += 5; | 	value += 5; | ||||||
| 	value |= 0x08000000; | 	value |= 0x08000000; | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x616610 + (crtc * 0x800), value); | 	nv_wr32(device, 0x616610 + (crtc * 0x800), value); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -1325,6 +1359,7 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) | ||||||
| { | { | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct drm_encoder *partner; | 	struct drm_encoder *partner; | ||||||
| 	int or = nv_encoder->or; | 	int or = nv_encoder->or; | ||||||
| 	u32 dpms_ctrl; | 	u32 dpms_ctrl; | ||||||
|  | @ -1348,10 +1383,10 @@ nvd0_sor_dpms(struct drm_encoder *encoder, int mode) | ||||||
| 	dpms_ctrl  = (mode == DRM_MODE_DPMS_ON); | 	dpms_ctrl  = (mode == DRM_MODE_DPMS_ON); | ||||||
| 	dpms_ctrl |= 0x80000000; | 	dpms_ctrl |= 0x80000000; | ||||||
| 
 | 
 | ||||||
| 	nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); | 	nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); | ||||||
| 	nv_mask(dev, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); | 	nv_mask(device, 0x61c004 + (or * 0x0800), 0x80000001, dpms_ctrl); | ||||||
| 	nv_wait(dev, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); | 	nv_wait(device, 0x61c004 + (or * 0x0800), 0x80000000, 0x00000000); | ||||||
| 	nv_wait(dev, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); | 	nv_wait(device, 0x61c030 + (or * 0x0800), 0x10000000, 0x00000000); | ||||||
| 
 | 
 | ||||||
| 	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { | 	if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { | ||||||
| 		struct dp_train_func func = { | 		struct dp_train_func func = { | ||||||
|  | @ -1428,11 +1463,11 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, | ||||||
| 		  struct drm_display_mode *mode) | 		  struct drm_display_mode *mode) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = encoder->dev; | 	struct drm_device *dev = encoder->dev; | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||||||
| 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | 	struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); | ||||||
| 	struct nouveau_connector *nv_connector; | 	struct nouveau_connector *nv_connector; | ||||||
| 	struct nvbios *bios = &dev_priv->vbios; | 	struct nvbios *bios = &drm->vbios; | ||||||
| 	u32 mode_ctrl = (1 << nv_crtc->index); | 	u32 mode_ctrl = (1 << nv_crtc->index); | ||||||
| 	u32 syncs, magic, *push; | 	u32 syncs, magic, *push; | ||||||
| 	u32 or_config; | 	u32 or_config; | ||||||
|  | @ -1587,7 +1622,7 @@ nvd0_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) | ||||||
| static struct dcb_output * | static struct dcb_output * | ||||||
| lookup_dcb(struct drm_device *dev, int id, u32 mc) | lookup_dcb(struct drm_device *dev, int id, u32 mc) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int type, or, i, link = -1; | 	int type, or, i, link = -1; | ||||||
| 
 | 
 | ||||||
| 	if (id < 4) { | 	if (id < 4) { | ||||||
|  | @ -1602,32 +1637,33 @@ lookup_dcb(struct drm_device *dev, int id, u32 mc) | ||||||
| 		case 0x00000800: link = 0; type = DCB_OUTPUT_DP; break; | 		case 0x00000800: link = 0; type = DCB_OUTPUT_DP; break; | ||||||
| 		case 0x00000900: link = 1; type = DCB_OUTPUT_DP; break; | 		case 0x00000900: link = 1; type = DCB_OUTPUT_DP; break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_ERROR(dev, "PDISP: unknown SOR mc 0x%08x\n", mc); | 			NV_ERROR(drm, "PDISP: unknown SOR mc 0x%08x\n", mc); | ||||||
| 			return NULL; | 			return NULL; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		or = id - 4; | 		or = id - 4; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < dev_priv->vbios.dcb.entries; i++) { | 	for (i = 0; i < drm->vbios.dcb.entries; i++) { | ||||||
| 		struct dcb_output *dcb = &dev_priv->vbios.dcb.entry[i]; | 		struct dcb_output *dcb = &drm->vbios.dcb.entry[i]; | ||||||
| 		if (dcb->type == type && (dcb->or & (1 << or)) && | 		if (dcb->type == type && (dcb->or & (1 << or)) && | ||||||
| 		    (link < 0 || link == !(dcb->sorconf.link & 1))) | 		    (link < 0 || link == !(dcb->sorconf.link & 1))) | ||||||
| 			return dcb; | 			return dcb; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	NV_ERROR(dev, "PDISP: DCB for %d/0x%08x not found\n", id, mc); | 	NV_ERROR(drm, "PDISP: DCB for %d/0x%08x not found\n", id, mc); | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) | nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct dcb_output *dcb; | 	struct dcb_output *dcb; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; mask && i < 8; i++) { | 	for (i = 0; mask && i < 8; i++) { | ||||||
| 		u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); | 		u32 mcc = nv_rd32(device, 0x640180 + (i * 0x20)); | ||||||
| 		if (!(mcc & (1 << crtc))) | 		if (!(mcc & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -1638,20 +1674,22 @@ nvd0_display_unk1_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| 		nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); | 		nouveau_bios_run_display_table(dev, 0x0000, -1, dcb, crtc); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x6101d4, 0x00000000); | 	nv_wr32(device, 0x6101d4, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6109d4, 0x00000000); | 	nv_wr32(device, 0x6109d4, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6101d0, 0x80000000); | 	nv_wr32(device, 0x6101d0, 0x80000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) | nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct dcb_output *dcb; | 	struct dcb_output *dcb; | ||||||
| 	u32 or, tmp, pclk; | 	u32 or, tmp, pclk; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; mask && i < 8; i++) { | 	for (i = 0; mask && i < 8; i++) { | ||||||
| 		u32 mcc = nv_rd32(dev, 0x640180 + (i * 0x20)); | 		u32 mcc = nv_rd32(device, 0x640180 + (i * 0x20)); | ||||||
| 		if (!(mcc & (1 << crtc))) | 		if (!(mcc & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -1662,16 +1700,16 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| 		nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); | 		nouveau_bios_run_display_table(dev, 0x0000, -2, dcb, crtc); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; | 	pclk = nv_rd32(device, 0x660450 + (crtc * 0x300)) / 1000; | ||||||
| 	NV_DEBUG_KMS(dev, "PDISP: crtc %d pclk %d mask 0x%08x\n", | 	NV_DEBUG(drm, "PDISP: crtc %d pclk %d mask 0x%08x\n", | ||||||
| 			  crtc, pclk, mask); | 			  crtc, pclk, mask); | ||||||
| 	if (pclk && (mask & 0x00010000)) { | 	if (pclk && (mask & 0x00010000)) { | ||||||
| 		nv50_crtc_set_clock(dev, crtc, pclk); | 		nv50_crtc_set_clock(dev, crtc, pclk); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; mask && i < 8; i++) { | 	for (i = 0; mask && i < 8; i++) { | ||||||
| 		u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); | 		u32 mcp = nv_rd32(device, 0x660180 + (i * 0x20)); | ||||||
| 		u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); | 		u32 cfg = nv_rd32(device, 0x660184 + (i * 0x20)); | ||||||
| 		if (!(mcp & (1 << crtc))) | 		if (!(mcp & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -1682,10 +1720,10 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| 
 | 
 | ||||||
| 		nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); | 		nouveau_bios_run_display_table(dev, cfg, pclk, dcb, crtc); | ||||||
| 
 | 
 | ||||||
| 		nv_wr32(dev, 0x612200 + (crtc * 0x800), 0x00000000); | 		nv_wr32(device, 0x612200 + (crtc * 0x800), 0x00000000); | ||||||
| 		switch (dcb->type) { | 		switch (dcb->type) { | ||||||
| 		case DCB_OUTPUT_ANALOG: | 		case DCB_OUTPUT_ANALOG: | ||||||
| 			nv_wr32(dev, 0x612280 + (or * 0x800), 0x00000000); | 			nv_wr32(device, 0x612280 + (or * 0x800), 0x00000000); | ||||||
| 			break; | 			break; | ||||||
| 		case DCB_OUTPUT_TMDS: | 		case DCB_OUTPUT_TMDS: | ||||||
| 		case DCB_OUTPUT_LVDS: | 		case DCB_OUTPUT_LVDS: | ||||||
|  | @ -1695,7 +1733,7 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| 			else | 			else | ||||||
| 				tmp = 0x00000000; | 				tmp = 0x00000000; | ||||||
| 
 | 
 | ||||||
| 			nv_mask(dev, 0x612300 + (or * 0x800), 0x00000707, tmp); | 			nv_mask(device, 0x612300 + (or * 0x800), 0x00000707, tmp); | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			break; | 			break; | ||||||
|  | @ -1704,22 +1742,23 @@ nvd0_display_unk2_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x6101d4, 0x00000000); | 	nv_wr32(device, 0x6101d4, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6109d4, 0x00000000); | 	nv_wr32(device, 0x6109d4, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6101d0, 0x80000000); | 	nv_wr32(device, 0x6101d0, 0x80000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) | nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| { | { | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct dcb_output *dcb; | 	struct dcb_output *dcb; | ||||||
| 	int pclk, i; | 	int pclk, i; | ||||||
| 
 | 
 | ||||||
| 	pclk = nv_rd32(dev, 0x660450 + (crtc * 0x300)) / 1000; | 	pclk = nv_rd32(device, 0x660450 + (crtc * 0x300)) / 1000; | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; mask && i < 8; i++) { | 	for (i = 0; mask && i < 8; i++) { | ||||||
| 		u32 mcp = nv_rd32(dev, 0x660180 + (i * 0x20)); | 		u32 mcp = nv_rd32(device, 0x660180 + (i * 0x20)); | ||||||
| 		u32 cfg = nv_rd32(dev, 0x660184 + (i * 0x20)); | 		u32 cfg = nv_rd32(device, 0x660184 + (i * 0x20)); | ||||||
| 		if (!(mcp & (1 << crtc))) | 		if (!(mcp & (1 << crtc))) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
|  | @ -1730,34 +1769,36 @@ nvd0_display_unk4_handler(struct drm_device *dev, u32 crtc, u32 mask) | ||||||
| 		nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); | 		nouveau_bios_run_display_table(dev, cfg, -pclk, dcb, crtc); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nv_wr32(dev, 0x6101d4, 0x00000000); | 	nv_wr32(device, 0x6101d4, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6109d4, 0x00000000); | 	nv_wr32(device, 0x6109d4, 0x00000000); | ||||||
| 	nv_wr32(dev, 0x6101d0, 0x80000000); | 	nv_wr32(device, 0x6101d0, 0x80000000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| nvd0_display_bh(unsigned long data) | nvd0_display_bh(unsigned long data) | ||||||
| { | { | ||||||
| 	struct drm_device *dev = (struct drm_device *)data; | 	struct drm_device *dev = (struct drm_device *)data; | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 	u32 mask = 0, crtc = ~0; | 	u32 mask = 0, crtc = ~0; | ||||||
| 	int i; | 	int i; | ||||||
| 
 | 
 | ||||||
| 	if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { | 	if (drm_debug & (DRM_UT_DRIVER | DRM_UT_KMS)) { | ||||||
| 		NV_INFO(dev, "PDISP: modeset req %d\n", disp->modeset); | 		NV_INFO(drm, "PDISP: modeset req %d\n", disp->modeset); | ||||||
| 		NV_INFO(dev, " STAT: 0x%08x 0x%08x 0x%08x\n", | 		NV_INFO(drm, " STAT: 0x%08x 0x%08x 0x%08x\n", | ||||||
| 			 nv_rd32(dev, 0x6101d0), | 			 nv_rd32(device, 0x6101d0), | ||||||
| 			 nv_rd32(dev, 0x6101d4), nv_rd32(dev, 0x6109d4)); | 			 nv_rd32(device, 0x6101d4), nv_rd32(device, 0x6109d4)); | ||||||
| 		for (i = 0; i < 8; i++) { | 		for (i = 0; i < 8; i++) { | ||||||
| 			NV_INFO(dev, " %s%d: 0x%08x 0x%08x\n", | 			NV_INFO(drm, " %s%d: 0x%08x 0x%08x\n", | ||||||
| 				i < 4 ? "DAC" : "SOR", i, | 				i < 4 ? "DAC" : "SOR", i, | ||||||
| 				nv_rd32(dev, 0x640180 + (i * 0x20)), | 				nv_rd32(device, 0x640180 + (i * 0x20)), | ||||||
| 				nv_rd32(dev, 0x660180 + (i * 0x20))); | 				nv_rd32(device, 0x660180 + (i * 0x20))); | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	while (!mask && ++crtc < dev->mode_config.num_crtc) | 	while (!mask && ++crtc < dev->mode_config.num_crtc) | ||||||
| 		mask = nv_rd32(dev, 0x6101d4 + (crtc * 0x800)); | 		mask = nv_rd32(device, 0x6101d4 + (crtc * 0x800)); | ||||||
| 
 | 
 | ||||||
| 	if (disp->modeset & 0x00000001) | 	if (disp->modeset & 0x00000001) | ||||||
| 		nvd0_display_unk1_handler(dev, crtc, mask); | 		nvd0_display_unk1_handler(dev, crtc, mask); | ||||||
|  | @ -1767,51 +1808,52 @@ nvd0_display_bh(unsigned long data) | ||||||
| 		nvd0_display_unk4_handler(dev, crtc, mask); | 		nvd0_display_unk4_handler(dev, crtc, mask); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | void | ||||||
| nvd0_display_intr(struct drm_device *dev) | nvd0_display_intr(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 	u32 intr = nv_rd32(dev, 0x610088); | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	int i; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	u32 intr = nv_rd32(device, 0x610088); | ||||||
| 
 | 
 | ||||||
| 	if (intr & 0x00000001) { | 	if (intr & 0x00000001) { | ||||||
| 		u32 stat = nv_rd32(dev, 0x61008c); | 		u32 stat = nv_rd32(device, 0x61008c); | ||||||
| 		nv_wr32(dev, 0x61008c, stat); | 		nv_wr32(device, 0x61008c, stat); | ||||||
| 		intr &= ~0x00000001; | 		intr &= ~0x00000001; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (intr & 0x00000002) { | 	if (intr & 0x00000002) { | ||||||
| 		u32 stat = nv_rd32(dev, 0x61009c); | 		u32 stat = nv_rd32(device, 0x61009c); | ||||||
| 		int chid = ffs(stat) - 1; | 		int chid = ffs(stat) - 1; | ||||||
| 		if (chid >= 0) { | 		if (chid >= 0) { | ||||||
| 			u32 mthd = nv_rd32(dev, 0x6101f0 + (chid * 12)); | 			u32 mthd = nv_rd32(device, 0x6101f0 + (chid * 12)); | ||||||
| 			u32 data = nv_rd32(dev, 0x6101f4 + (chid * 12)); | 			u32 data = nv_rd32(device, 0x6101f4 + (chid * 12)); | ||||||
| 			u32 unkn = nv_rd32(dev, 0x6101f8 + (chid * 12)); | 			u32 unkn = nv_rd32(device, 0x6101f8 + (chid * 12)); | ||||||
| 
 | 
 | ||||||
| 			NV_INFO(dev, "EvoCh: chid %d mthd 0x%04x data 0x%08x " | 			NV_INFO(drm, "EvoCh: chid %d mthd 0x%04x data 0x%08x " | ||||||
| 				     "0x%08x 0x%08x\n", | 				     "0x%08x 0x%08x\n", | ||||||
| 				chid, (mthd & 0x0000ffc), data, mthd, unkn); | 				chid, (mthd & 0x0000ffc), data, mthd, unkn); | ||||||
| 			nv_wr32(dev, 0x61009c, (1 << chid)); | 			nv_wr32(device, 0x61009c, (1 << chid)); | ||||||
| 			nv_wr32(dev, 0x6101f0 + (chid * 12), 0x90000000); | 			nv_wr32(device, 0x6101f0 + (chid * 12), 0x90000000); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		intr &= ~0x00000002; | 		intr &= ~0x00000002; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (intr & 0x00100000) { | 	if (intr & 0x00100000) { | ||||||
| 		u32 stat = nv_rd32(dev, 0x6100ac); | 		u32 stat = nv_rd32(device, 0x6100ac); | ||||||
| 
 | 
 | ||||||
| 		if (stat & 0x00000007) { | 		if (stat & 0x00000007) { | ||||||
| 			disp->modeset = stat; | 			disp->modeset = stat; | ||||||
| 			tasklet_schedule(&disp->tasklet); | 			tasklet_schedule(&disp->tasklet); | ||||||
| 
 | 
 | ||||||
| 			nv_wr32(dev, 0x6100ac, (stat & 0x00000007)); | 			nv_wr32(device, 0x6100ac, (stat & 0x00000007)); | ||||||
| 			stat &= ~0x00000007; | 			stat &= ~0x00000007; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (stat) { | 		if (stat) { | ||||||
| 			NV_INFO(dev, "PDISP: unknown intr24 0x%08x\n", stat); | 			NV_INFO(drm, "PDISP: unknown intr24 0x%08x\n", stat); | ||||||
| 			nv_wr32(dev, 0x6100ac, stat); | 			nv_wr32(device, 0x6100ac, stat); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		intr &= ~0x00100000; | 		intr &= ~0x00100000; | ||||||
|  | @ -1819,7 +1861,7 @@ nvd0_display_intr(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 	intr &= ~0x0f000000; /* vblank, handled in core */ | 	intr &= ~0x0f000000; /* vblank, handled in core */ | ||||||
| 	if (intr) | 	if (intr) | ||||||
| 		NV_INFO(dev, "PDISP: unknown intr 0x%08x\n", intr); | 		NV_INFO(drm, "PDISP: unknown intr 0x%08x\n", intr); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /******************************************************************************
 | /******************************************************************************
 | ||||||
|  | @ -1846,15 +1888,17 @@ int | ||||||
| nvd0_display_init(struct drm_device *dev) | nvd0_display_init(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
|  | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
|  | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
| 	int ret, i; | 	int ret, i; | ||||||
| 	u32 *push; | 	u32 *push; | ||||||
| 
 | 
 | ||||||
| 	if (nv_rd32(dev, 0x6100ac) & 0x00000100) { | 	if (nv_rd32(device, 0x6100ac) & 0x00000100) { | ||||||
| 		nv_wr32(dev, 0x6100ac, 0x00000100); | 		nv_wr32(device, 0x6100ac, 0x00000100); | ||||||
| 		nv_mask(dev, 0x6194e8, 0x00000001, 0x00000000); | 		nv_mask(device, 0x6194e8, 0x00000001, 0x00000000); | ||||||
| 		if (!nv_wait(dev, 0x6194e8, 0x00000002, 0x00000000)) { | 		if (!nv_wait(device, 0x6194e8, 0x00000002, 0x00000000)) { | ||||||
| 			NV_ERROR(dev, "PDISP: 0x6194e8 0x%08x\n", | 			NV_ERROR(drm, "PDISP: 0x6194e8 0x%08x\n", | ||||||
| 				 nv_rd32(dev, 0x6194e8)); | 				 nv_rd32(device, 0x6194e8)); | ||||||
| 			return -EBUSY; | 			return -EBUSY; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | @ -1863,27 +1907,27 @@ nvd0_display_init(struct drm_device *dev) | ||||||
| 	 * work at all unless you do the SOR part below. | 	 * work at all unless you do the SOR part below. | ||||||
| 	 */ | 	 */ | ||||||
| 	for (i = 0; i < 3; i++) { | 	for (i = 0; i < 3; i++) { | ||||||
| 		u32 dac = nv_rd32(dev, 0x61a000 + (i * 0x800)); | 		u32 dac = nv_rd32(device, 0x61a000 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x6101c0 + (i * 0x800), dac); | 		nv_wr32(device, 0x6101c0 + (i * 0x800), dac); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < 4; i++) { | 	for (i = 0; i < 4; i++) { | ||||||
| 		u32 sor = nv_rd32(dev, 0x61c000 + (i * 0x800)); | 		u32 sor = nv_rd32(device, 0x61c000 + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); | 		nv_wr32(device, 0x6301c4 + (i * 0x800), sor); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (i = 0; i < dev->mode_config.num_crtc; i++) { | 	for (i = 0; i < dev->mode_config.num_crtc; i++) { | ||||||
| 		u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); | 		u32 crtc0 = nv_rd32(device, 0x616104 + (i * 0x800)); | ||||||
| 		u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); | 		u32 crtc1 = nv_rd32(device, 0x616108 + (i * 0x800)); | ||||||
| 		u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); | 		u32 crtc2 = nv_rd32(device, 0x61610c + (i * 0x800)); | ||||||
| 		nv_wr32(dev, 0x6101b4 + (i * 0x800), crtc0); | 		nv_wr32(device, 0x6101b4 + (i * 0x800), crtc0); | ||||||
| 		nv_wr32(dev, 0x6101b8 + (i * 0x800), crtc1); | 		nv_wr32(device, 0x6101b8 + (i * 0x800), crtc1); | ||||||
| 		nv_wr32(dev, 0x6101bc + (i * 0x800), crtc2); | 		nv_wr32(device, 0x6101bc + (i * 0x800), crtc2); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* point at our hash table / objects, enable interrupts */ | 	/* point at our hash table / objects, enable interrupts */ | ||||||
| 	nv_wr32(dev, 0x610010, (disp->mem->addr >> 8) | 9); | 	nv_wr32(device, 0x610010, (disp->mem->addr >> 8) | 9); | ||||||
| 	nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); | 	nv_mask(device, 0x6100b0, 0x00000307, 0x00000307); | ||||||
| 
 | 
 | ||||||
| 	/* init master */ | 	/* init master */ | ||||||
| 	ret = evo_init_dma(dev, EVO_MASTER); | 	ret = evo_init_dma(dev, EVO_MASTER); | ||||||
|  | @ -1923,7 +1967,6 @@ error: | ||||||
| void | void | ||||||
| nvd0_display_destroy(struct drm_device *dev) | nvd0_display_destroy(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; |  | ||||||
| 	struct nvd0_display *disp = nvd0_display(dev); | 	struct nvd0_display *disp = nvd0_display(dev); | ||||||
| 	struct pci_dev *pdev = dev->pdev; | 	struct pci_dev *pdev = dev->pdev; | ||||||
| 	int i; | 	int i; | ||||||
|  | @ -1936,17 +1979,19 @@ nvd0_display_destroy(struct drm_device *dev) | ||||||
| 	nouveau_gpuobj_ref(NULL, &disp->mem); | 	nouveau_gpuobj_ref(NULL, &disp->mem); | ||||||
| 	nouveau_bo_unmap(disp->sync); | 	nouveau_bo_unmap(disp->sync); | ||||||
| 	nouveau_bo_ref(NULL, &disp->sync); | 	nouveau_bo_ref(NULL, &disp->sync); | ||||||
| 	nouveau_irq_unregister(dev, 26); |  | ||||||
| 
 | 
 | ||||||
| 	dev_priv->engine.display.priv = NULL; | 	nouveau_display(dev)->priv = NULL; | ||||||
| 	kfree(disp); | 	kfree(disp); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int | int | ||||||
| nvd0_display_create(struct drm_device *dev) | nvd0_display_create(struct drm_device *dev) | ||||||
| { | { | ||||||
| 	struct drm_nouveau_private *dev_priv = dev->dev_private; | 	struct nouveau_device *device = nouveau_dev(dev); | ||||||
| 	struct dcb_table *dcb = &dev_priv->vbios.dcb; | 	struct nouveau_drm *drm = nouveau_drm(dev); | ||||||
|  | 	struct nouveau_bar *bar = nouveau_bar(device); | ||||||
|  | 	struct nouveau_fb *pfb = nouveau_fb(device); | ||||||
|  | 	struct dcb_table *dcb = &drm->vbios.dcb; | ||||||
| 	struct drm_connector *connector, *tmp; | 	struct drm_connector *connector, *tmp; | ||||||
| 	struct pci_dev *pdev = dev->pdev; | 	struct pci_dev *pdev = dev->pdev; | ||||||
| 	struct nvd0_display *disp; | 	struct nvd0_display *disp; | ||||||
|  | @ -1956,10 +2001,14 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 	disp = kzalloc(sizeof(*disp), GFP_KERNEL); | 	disp = kzalloc(sizeof(*disp), GFP_KERNEL); | ||||||
| 	if (!disp) | 	if (!disp) | ||||||
| 		return -ENOMEM; | 		return -ENOMEM; | ||||||
| 	dev_priv->engine.display.priv = disp; | 
 | ||||||
|  | 	nouveau_display(dev)->priv = disp; | ||||||
|  | 	nouveau_display(dev)->dtor = nvd0_display_destroy; | ||||||
|  | 	nouveau_display(dev)->init = nvd0_display_init; | ||||||
|  | 	nouveau_display(dev)->fini = nvd0_display_fini; | ||||||
| 
 | 
 | ||||||
| 	/* create crtc objects to represent the hw heads */ | 	/* create crtc objects to represent the hw heads */ | ||||||
| 	crtcs = nv_rd32(dev, 0x022448); | 	crtcs = nv_rd32(device, 0x022448); | ||||||
| 	for (i = 0; i < crtcs; i++) { | 	for (i = 0; i < crtcs; i++) { | ||||||
| 		ret = nvd0_crtc_create(dev, i); | 		ret = nvd0_crtc_create(dev, i); | ||||||
| 		if (ret) | 		if (ret) | ||||||
|  | @ -1973,7 +2022,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		if (dcbe->location != DCB_LOC_ON_CHIP) { | 		if (dcbe->location != DCB_LOC_ON_CHIP) { | ||||||
| 			NV_WARN(dev, "skipping off-chip encoder %d/%d\n", | 			NV_WARN(drm, "skipping off-chip encoder %d/%d\n", | ||||||
| 				dcbe->type, ffs(dcbe->or) - 1); | 				dcbe->type, ffs(dcbe->or) - 1); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | @ -1988,7 +2037,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 			nvd0_dac_create(connector, dcbe); | 			nvd0_dac_create(connector, dcbe); | ||||||
| 			break; | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			NV_WARN(dev, "skipping unsupported encoder %d/%d\n", | 			NV_WARN(drm, "skipping unsupported encoder %d/%d\n", | ||||||
| 				dcbe->type, ffs(dcbe->or) - 1); | 				dcbe->type, ffs(dcbe->or) - 1); | ||||||
| 			continue; | 			continue; | ||||||
| 		} | 		} | ||||||
|  | @ -1999,14 +2048,13 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 		if (connector->encoder_ids[0]) | 		if (connector->encoder_ids[0]) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		NV_WARN(dev, "%s has no encoders, removing\n", | 		NV_WARN(drm, "%s has no encoders, removing\n", | ||||||
| 			drm_get_connector_name(connector)); | 			drm_get_connector_name(connector)); | ||||||
| 		connector->funcs->destroy(connector); | 		connector->funcs->destroy(connector); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/* setup interrupt handling */ | 	/* setup interrupt handling */ | ||||||
| 	tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); | 	tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); | ||||||
| 	nouveau_irq_register(dev, 26, nvd0_display_intr); |  | ||||||
| 
 | 
 | ||||||
| 	/* small shared memory area we use for notifiers and semaphores */ | 	/* small shared memory area we use for notifiers and semaphores */ | ||||||
| 	ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, | 	ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, | ||||||
|  | @ -2023,7 +2071,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 		goto out; | 		goto out; | ||||||
| 
 | 
 | ||||||
| 	/* hash table and dma objects for the memory areas we care about */ | 	/* hash table and dma objects for the memory areas we care about */ | ||||||
| 	ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, | 	ret = nouveau_gpuobj_new(nv_object(device), NULL, 0x4000, 0x10000, | ||||||
| 				 NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); | 				 NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); | ||||||
| 	if (ret) | 	if (ret) | ||||||
| 		goto out; | 		goto out; | ||||||
|  | @ -2055,7 +2103,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 		nv_wo32(disp->mem, dmao + 0x20, 0x00000049); | 		nv_wo32(disp->mem, dmao + 0x20, 0x00000049); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x24, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x24, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x28, (nvfb_vram_size(dev) - 1) >> 8); | 		nv_wo32(disp->mem, dmao + 0x28, (pfb->ram.size - 1) >> 8); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x30, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x30, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x34, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x34, 0x00000000); | ||||||
|  | @ -2065,7 +2113,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 		nv_wo32(disp->mem, dmao + 0x40, 0x00000009); | 		nv_wo32(disp->mem, dmao + 0x40, 0x00000009); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x44, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x44, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x48, (nvfb_vram_size(dev) - 1) >> 8); | 		nv_wo32(disp->mem, dmao + 0x48, (pfb->ram.size - 1) >> 8); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x50, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x50, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x54, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x54, 0x00000000); | ||||||
|  | @ -2075,7 +2123,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 
 | 
 | ||||||
| 		nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); | 		nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x64, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x64, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x68, (nvfb_vram_size(dev) - 1) >> 8); | 		nv_wo32(disp->mem, dmao + 0x68, (pfb->ram.size - 1) >> 8); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x70, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x70, 0x00000000); | ||||||
| 		nv_wo32(disp->mem, dmao + 0x74, 0x00000000); | 		nv_wo32(disp->mem, dmao + 0x74, 0x00000000); | ||||||
|  | @ -2084,7 +2132,7 @@ nvd0_display_create(struct drm_device *dev) | ||||||
| 						((dmao + 0x60) << 9)); | 						((dmao + 0x60) << 9)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	nvimem_flush(dev); | 	bar->flush(bar); | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| 	if (ret) | 	if (ret) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Ben Skeggs
						Ben Skeggs