Commit abd32008 authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-next' of...

Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-core-next

* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (57 commits)
  drm/nouveau: map first page of mmio early and determine chipset earlier
  drm/nvd0/disp: disconnect encoders before reprogramming them
  drm/nvd0/disp: move syncs/magic setup to or mode_set
  drm/nouveau/dp: account for channel coding overhead in link training
  drm/nvd0/disp: fix dcb sor link matching in supervisor handler
  drm/nvd0/disp: initial implementation of displayport
  drm/nouveau/dp: make dp dpms function common, call from sor code instead
  drm/nv50/hwsq: some nv92 fixes
  drm/nouveau/dp: move all nv50/sor-specific code out of nouveau_dp.c
  drm/nouveau/dp: make functions for executing various bios tables
  drm/nouveau/pm: fix oops if chipset has no pm support at all
  drm/nouveau/bios: rework vbios shadowing
  drm/nouveau/bios: attempt acpi rom fetch before pcirom
  drm/nvd0/disp: attempt to handle more than 2 crtcs if possible
  drm/nvc0/vram: get part count from PUNITS
  drm/nv40/pm: fix fanspeed regression
  drm/nouveau/pm: several fixes for nvc0 memory timings
  drm/nvc0/pm: restrict pll mode to clocks that can actually use it
  drm/nouveau/dp: fix bad comparison in dp_link_train_commit()
  drm/nouveau/mxm: call mxmi to determine revision before calling mxms
  ...
parents 83465324 2f5394c3
...@@ -14,7 +14,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ ...@@ -14,7 +14,8 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \
nv04_timer.o \ nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \ nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ nv04_fb.o nv10_fb.o nv20_fb.o nv30_fb.o nv40_fb.o \
nv50_fb.o nvc0_fb.o \
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \ nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \
nv04_graph.o nv10_graph.o nv20_graph.o \ nv04_graph.o nv10_graph.o nv20_graph.o \
nv40_graph.o nv50_graph.o nvc0_graph.o \ nv40_graph.o nv50_graph.o nvc0_graph.o \
......
This diff is collapsed.
...@@ -75,6 +75,8 @@ enum dcb_connector_type { ...@@ -75,6 +75,8 @@ enum dcb_connector_type {
DCB_CONNECTOR_eDP = 0x47, DCB_CONNECTOR_eDP = 0x47,
DCB_CONNECTOR_HDMI_0 = 0x60, DCB_CONNECTOR_HDMI_0 = 0x60,
DCB_CONNECTOR_HDMI_1 = 0x61, DCB_CONNECTOR_HDMI_1 = 0x61,
DCB_CONNECTOR_DMS59_DP0 = 0x64,
DCB_CONNECTOR_DMS59_DP1 = 0x65,
DCB_CONNECTOR_NONE = 0xff DCB_CONNECTOR_NONE = 0xff
}; };
...@@ -209,6 +211,8 @@ struct nvbios { ...@@ -209,6 +211,8 @@ struct nvbios {
NVBIOS_BIT NVBIOS_BIT
} type; } type;
uint16_t offset; uint16_t offset;
uint32_t length;
uint8_t *data;
uint8_t chip_version; uint8_t chip_version;
...@@ -219,8 +223,6 @@ struct nvbios { ...@@ -219,8 +223,6 @@ struct nvbios {
spinlock_t lock; spinlock_t lock;
uint8_t data[NV_PROM_SIZE];
unsigned int length;
bool execute; bool execute;
uint8_t major_version; uint8_t major_version;
......
...@@ -519,6 +519,19 @@ nouveau_connector_set_property(struct drm_connector *connector, ...@@ -519,6 +519,19 @@ nouveau_connector_set_property(struct drm_connector *connector,
return nv_crtc->set_dither(nv_crtc, true); return nv_crtc->set_dither(nv_crtc, true);
} }
if (nv_crtc && nv_crtc->set_color_vibrance) {
/* Hue */
if (property == disp->vibrant_hue_property) {
nv_crtc->vibrant_hue = value - 90;
return nv_crtc->set_color_vibrance(nv_crtc, true);
}
/* Saturation */
if (property == disp->color_vibrance_property) {
nv_crtc->color_vibrance = value - 100;
return nv_crtc->set_color_vibrance(nv_crtc, true);
}
}
if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV)
return get_slave_funcs(encoder)->set_property( return get_slave_funcs(encoder)->set_property(
encoder, connector, property, value); encoder, connector, property, value);
...@@ -858,6 +871,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb) ...@@ -858,6 +871,8 @@ drm_conntype_from_dcb(enum dcb_connector_type dcb)
case DCB_CONNECTOR_DVI_D : return DRM_MODE_CONNECTOR_DVID; case DCB_CONNECTOR_DVI_D : return DRM_MODE_CONNECTOR_DVID;
case DCB_CONNECTOR_LVDS : case DCB_CONNECTOR_LVDS :
case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS; case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS;
case DCB_CONNECTOR_DMS59_DP0:
case DCB_CONNECTOR_DMS59_DP1:
case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort; case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort;
case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP;
case DCB_CONNECTOR_HDMI_0 : case DCB_CONNECTOR_HDMI_0 :
...@@ -1002,7 +1017,9 @@ nouveau_connector_create(struct drm_device *dev, int index) ...@@ -1002,7 +1017,9 @@ nouveau_connector_create(struct drm_device *dev, int index)
nv_connector->type == DCB_CONNECTOR_DVI_I || nv_connector->type == DCB_CONNECTOR_DVI_I ||
nv_connector->type == DCB_CONNECTOR_HDMI_0 || nv_connector->type == DCB_CONNECTOR_HDMI_0 ||
nv_connector->type == DCB_CONNECTOR_HDMI_1 || nv_connector->type == DCB_CONNECTOR_HDMI_1 ||
nv_connector->type == DCB_CONNECTOR_DP)) { nv_connector->type == DCB_CONNECTOR_DP ||
nv_connector->type == DCB_CONNECTOR_DMS59_DP0 ||
nv_connector->type == DCB_CONNECTOR_DMS59_DP1)) {
drm_connector_attach_property(connector, drm_connector_attach_property(connector,
disp->underscan_property, disp->underscan_property,
UNDERSCAN_OFF); UNDERSCAN_OFF);
...@@ -1014,6 +1031,16 @@ nouveau_connector_create(struct drm_device *dev, int index) ...@@ -1014,6 +1031,16 @@ nouveau_connector_create(struct drm_device *dev, int index)
0); 0);
} }
/* Add hue and saturation options */
if (disp->vibrant_hue_property)
drm_connector_attach_property(connector,
disp->vibrant_hue_property,
90);
if (disp->color_vibrance_property)
drm_connector_attach_property(connector,
disp->color_vibrance_property,
150);
switch (nv_connector->type) { switch (nv_connector->type) {
case DCB_CONNECTOR_VGA: case DCB_CONNECTOR_VGA:
if (dev_priv->card_type >= NV_50) { if (dev_priv->card_type >= NV_50) {
......
...@@ -35,6 +35,8 @@ struct nouveau_crtc { ...@@ -35,6 +35,8 @@ struct nouveau_crtc {
uint32_t dpms_saved_fp_control; uint32_t dpms_saved_fp_control;
uint32_t fp_users; uint32_t fp_users;
int saturation; int saturation;
int color_vibrance;
int vibrant_hue;
int sharpness; int sharpness;
int last_dpms; int last_dpms;
...@@ -67,6 +69,7 @@ struct nouveau_crtc { ...@@ -67,6 +69,7 @@ struct nouveau_crtc {
int (*set_dither)(struct nouveau_crtc *crtc, bool update); int (*set_dither)(struct nouveau_crtc *crtc, bool update);
int (*set_scale)(struct nouveau_crtc *crtc, bool update); int (*set_scale)(struct nouveau_crtc *crtc, bool update);
int (*set_color_vibrance)(struct nouveau_crtc *crtc, bool update);
}; };
static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc) static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc)
......
...@@ -286,6 +286,20 @@ nouveau_display_create(struct drm_device *dev) ...@@ -286,6 +286,20 @@ nouveau_display_create(struct drm_device *dev)
disp->underscan_vborder_property = disp->underscan_vborder_property =
drm_property_create_range(dev, 0, "underscan vborder", 0, 128); drm_property_create_range(dev, 0, "underscan vborder", 0, 128);
if (gen == 1) {
disp->vibrant_hue_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"vibrant hue", 2);
disp->vibrant_hue_property->values[0] = 0;
disp->vibrant_hue_property->values[1] = 180; /* -90..+90 */
disp->color_vibrance_property =
drm_property_create(dev, DRM_MODE_PROP_RANGE,
"color vibrance", 2);
disp->color_vibrance_property->values[0] = 0;
disp->color_vibrance_property->values[1] = 200; /* -100..+100 */
}
dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs;
dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1);
......
This diff is collapsed.
...@@ -57,6 +57,10 @@ MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); ...@@ -57,6 +57,10 @@ MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
int nouveau_vram_notify = 0; int nouveau_vram_notify = 0;
module_param_named(vram_notify, nouveau_vram_notify, int, 0400); 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)"); MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
int nouveau_duallink = 1; int nouveau_duallink = 1;
module_param_named(duallink, nouveau_duallink, int, 0400); module_param_named(duallink, nouveau_duallink, int, 0400);
...@@ -89,7 +93,7 @@ MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type"); ...@@ -89,7 +93,7 @@ MODULE_PARM_DESC(override_conntype, "Ignore DCB connector type");
int nouveau_override_conntype = 0; int nouveau_override_conntype = 0;
module_param_named(override_conntype, nouveau_override_conntype, int, 0400); module_param_named(override_conntype, nouveau_override_conntype, int, 0400);
MODULE_PARM_DESC(tv_disable, "Disable TV-out detection\n"); MODULE_PARM_DESC(tv_disable, "Disable TV-out detection");
int nouveau_tv_disable = 0; int nouveau_tv_disable = 0;
module_param_named(tv_disable, nouveau_tv_disable, int, 0400); module_param_named(tv_disable, nouveau_tv_disable, int, 0400);
...@@ -104,27 +108,27 @@ module_param_named(tv_norm, nouveau_tv_norm, charp, 0400); ...@@ -104,27 +108,27 @@ module_param_named(tv_norm, nouveau_tv_norm, charp, 0400);
MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n" MODULE_PARM_DESC(reg_debug, "Register access debug bitmask:\n"
"\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n" "\t\t0x1 mc, 0x2 video, 0x4 fb, 0x8 extdev,\n"
"\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n" "\t\t0x10 crtc, 0x20 ramdac, 0x40 vgacrtc, 0x80 rmvio,\n"
"\t\t0x100 vgaattr, 0x200 EVO (G80+). "); "\t\t0x100 vgaattr, 0x200 EVO (G80+)");
int nouveau_reg_debug; int nouveau_reg_debug;
module_param_named(reg_debug, nouveau_reg_debug, int, 0600); module_param_named(reg_debug, nouveau_reg_debug, int, 0600);
MODULE_PARM_DESC(perflvl, "Performance level (default: boot)\n"); MODULE_PARM_DESC(perflvl, "Performance level (default: boot)");
char *nouveau_perflvl; char *nouveau_perflvl;
module_param_named(perflvl, nouveau_perflvl, charp, 0400); module_param_named(perflvl, nouveau_perflvl, charp, 0400);
MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)\n"); MODULE_PARM_DESC(perflvl_wr, "Allow perflvl changes (warning: dangerous!)");
int nouveau_perflvl_wr; int nouveau_perflvl_wr;
module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400); module_param_named(perflvl_wr, nouveau_perflvl_wr, int, 0400);
MODULE_PARM_DESC(msi, "Enable MSI (default: off)\n"); MODULE_PARM_DESC(msi, "Enable MSI (default: off)");
int nouveau_msi; int nouveau_msi;
module_param_named(msi, nouveau_msi, int, 0400); module_param_named(msi, nouveau_msi, int, 0400);
MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)");
int nouveau_ctxfw; int nouveau_ctxfw;
module_param_named(ctxfw, nouveau_ctxfw, int, 0400); module_param_named(ctxfw, nouveau_ctxfw, int, 0400);
MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS\n"); MODULE_PARM_DESC(mxmdcb, "Santise DCB table according to MXM-SIS");
int nouveau_mxmdcb = 1; int nouveau_mxmdcb = 1;
module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400);
......
...@@ -406,6 +406,9 @@ struct nouveau_display_engine { ...@@ -406,6 +406,9 @@ struct nouveau_display_engine {
struct drm_property *underscan_property; struct drm_property *underscan_property;
struct drm_property *underscan_hborder_property; struct drm_property *underscan_hborder_property;
struct drm_property *underscan_vborder_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_gpio_engine { struct nouveau_gpio_engine {
...@@ -432,58 +435,85 @@ struct nouveau_pm_voltage { ...@@ -432,58 +435,85 @@ struct nouveau_pm_voltage {
int nr_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 { struct nouveau_pm_memtiming {
int id; int id;
u32 reg_0; /* 0x10f290 on Fermi, 0x100220 for older */
u32 reg_1; u32 reg[9];
u32 reg_2; u32 mr[4];
u32 reg_3;
u32 reg_4; u8 tCWL;
u32 reg_5;
u32 reg_6; u8 odt;
u32 reg_7; u8 drive_strength;
u32 reg_8;
/* To be written to 0x1002c0 */
u8 CL;
u8 WR;
}; };
struct nouveau_pm_tbl_header{ struct nouveau_pm_tbl_header {
u8 version; u8 version;
u8 header_len; u8 header_len;
u8 entry_cnt; u8 entry_cnt;
u8 entry_len; u8 entry_len;
}; };
struct nouveau_pm_tbl_entry{ struct nouveau_pm_tbl_entry {
u8 tWR; u8 tWR;
u8 tUNK_1; u8 tWTR;
u8 tCL; u8 tCL;
u8 tRP; /* Byte 3 */ u8 tRC;
u8 empty_4; u8 empty_4;
u8 tRAS; /* Byte 5 */ u8 tRFC; /* Byte 5 */
u8 empty_6; u8 empty_6;
u8 tRFC; /* Byte 7 */ u8 tRAS; /* Byte 7 */
u8 empty_8; u8 empty_8;
u8 tRC; /* Byte 9 */ u8 tRP; /* Byte 9 */
u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14; u8 tRCDRD;
u8 empty_15,empty_16,empty_17; u8 tRCDWR;
u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21; 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;
}; };
/* nouveau_mem.c */ struct nouveau_pm_profile;
void nv30_mem_timing_entry(struct drm_device *dev, struct nouveau_pm_tbl_header *hdr, struct nouveau_pm_profile_func {
struct nouveau_pm_tbl_entry *e, uint8_t magic_number, void (*destroy)(struct nouveau_pm_profile *);
struct nouveau_pm_memtiming *timing); 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 #define NOUVEAU_PM_MAX_LEVEL 8
struct nouveau_pm_level { struct nouveau_pm_level {
struct nouveau_pm_profile profile;
struct device_attribute dev_attr; struct device_attribute dev_attr;
char name[32]; char name[32];
int id; int id;
u32 core; struct nouveau_pm_memtiming timing;
u32 memory; u32 memory;
u16 memscript;
u32 core;
u32 shader; u32 shader;
u32 rop; u32 rop;
u32 copy; u32 copy;
...@@ -498,9 +528,6 @@ struct nouveau_pm_level { ...@@ -498,9 +528,6 @@ struct nouveau_pm_level {
u32 volt_min; /* microvolts */ u32 volt_min; /* microvolts */
u32 volt_max; u32 volt_max;
u8 fanspeed; u8 fanspeed;
u16 memscript;
struct nouveau_pm_memtiming *timing;
}; };
struct nouveau_pm_temp_sensor_constants { struct nouveau_pm_temp_sensor_constants {
...@@ -517,27 +544,26 @@ struct nouveau_pm_threshold_temp { ...@@ -517,27 +544,26 @@ struct nouveau_pm_threshold_temp {
s16 fan_boost; s16 fan_boost;
}; };
struct nouveau_pm_memtimings {
bool supported;
struct nouveau_pm_memtiming *timing;
int nr_timing;
};
struct nouveau_pm_fan { struct nouveau_pm_fan {
u32 percent;
u32 min_duty; u32 min_duty;
u32 max_duty; u32 max_duty;
u32 pwm_freq; u32 pwm_freq;
u32 pwm_divisor;
}; };
struct nouveau_pm_engine { struct nouveau_pm_engine {
struct nouveau_pm_voltage voltage; struct nouveau_pm_voltage voltage;
struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL];
int nr_perflvl; int nr_perflvl;
struct nouveau_pm_memtimings memtimings;
struct nouveau_pm_temp_sensor_constants sensor_constants; struct nouveau_pm_temp_sensor_constants sensor_constants;
struct nouveau_pm_threshold_temp threshold_temp; struct nouveau_pm_threshold_temp threshold_temp;
struct nouveau_pm_fan fan; struct nouveau_pm_fan fan;
u32 pwm_divisor;
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 boot;
struct nouveau_pm_level *cur; struct nouveau_pm_level *cur;
...@@ -669,14 +695,14 @@ struct nv04_mode_state { ...@@ -669,14 +695,14 @@ struct nv04_mode_state {
}; };
enum nouveau_card_type { enum nouveau_card_type {
NV_04 = 0x00, NV_04 = 0x04,
NV_10 = 0x10, NV_10 = 0x10,
NV_20 = 0x20, NV_20 = 0x20,
NV_30 = 0x30, NV_30 = 0x30,
NV_40 = 0x40, NV_40 = 0x40,
NV_50 = 0x50, NV_50 = 0x50,
NV_C0 = 0xc0, NV_C0 = 0xc0,
NV_D0 = 0xd0 NV_D0 = 0xd0,
}; };
struct drm_nouveau_private { struct drm_nouveau_private {
...@@ -772,8 +798,22 @@ struct drm_nouveau_private { ...@@ -772,8 +798,22 @@ struct drm_nouveau_private {
} tile; } tile;
/* VRAM/fb configuration */ /* VRAM/fb configuration */
enum {
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
} vram_type;
uint64_t vram_size; uint64_t vram_size;
uint64_t vram_sys_base; uint64_t vram_sys_base;
bool vram_rank_B;
uint64_t fb_available_size; uint64_t fb_available_size;
uint64_t fb_mappable_pages; uint64_t fb_mappable_pages;
...@@ -846,6 +886,7 @@ extern int nouveau_uscript_lvds; ...@@ -846,6 +886,7 @@ extern int nouveau_uscript_lvds;
extern int nouveau_uscript_tmds; extern int nouveau_uscript_tmds;
extern int nouveau_vram_pushbuf; extern int nouveau_vram_pushbuf;
extern int nouveau_vram_notify; extern int nouveau_vram_notify;
extern char *nouveau_vram_type;
extern int nouveau_fbpercrtc; extern int nouveau_fbpercrtc;
extern int nouveau_tv_disable; extern int nouveau_tv_disable;
extern char *nouveau_tv_norm; extern char *nouveau_tv_norm;
...@@ -894,8 +935,12 @@ extern void nouveau_mem_gart_fini(struct drm_device *); ...@@ -894,8 +935,12 @@ extern void nouveau_mem_gart_fini(struct drm_device *);
extern int nouveau_mem_init_agp(struct drm_device *); extern int nouveau_mem_init_agp(struct drm_device *);
extern int nouveau_mem_reset_agp(struct drm_device *); extern int nouveau_mem_reset_agp(struct drm_device *);
extern void nouveau_mem_close(struct drm_device *); extern void nouveau_mem_close(struct drm_device *);
extern int nouveau_mem_detect(struct drm_device *);
extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags); extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
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 *);
extern int nouveau_mem_vbios_type(struct drm_device *);
extern struct nouveau_tile_reg *nv10_mem_set_tiling( extern struct nouveau_tile_reg *nv10_mem_set_tiling(
struct drm_device *dev, uint32_t addr, uint32_t size, struct drm_device *dev, uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags); uint32_t pitch, uint32_t flags);
...@@ -1117,19 +1162,14 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); ...@@ -1117,19 +1162,14 @@ int nouveau_ttm_mmap(struct file *, struct vm_area_struct *);
/* nouveau_hdmi.c */ /* nouveau_hdmi.c */
void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
/* nouveau_dp.c */
int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
uint8_t *data, int data_nr);
bool nouveau_dp_detect(struct drm_encoder *);
bool nouveau_dp_link_train(struct drm_encoder *, u32 datarate);
void nouveau_dp_tu_update(struct drm_device *, int, int, u32, u32);
u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **);
/* nv04_fb.c */ /* nv04_fb.c */
extern int nv04_fb_vram_init(struct drm_device *);
extern int nv04_fb_init(struct drm_device *); extern int nv04_fb_init(struct drm_device *);
extern void nv04_fb_takedown(struct drm_device *); extern void nv04_fb_takedown(struct drm_device *);
/* nv10_fb.c */ /* nv10_fb.c */
extern int nv10_fb_vram_init(struct drm_device *dev);
extern int nv1a_fb_vram_init(struct drm_device *dev);
extern int nv10_fb_init(struct drm_device *); extern int nv10_fb_init(struct drm_device *);
extern void nv10_fb_takedown(struct drm_device *); extern void nv10_fb_takedown(struct drm_device *);
extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
...@@ -1138,6 +1178,16 @@ extern void nv10_fb_init_tile_region(struct drm_device *dev, int i, ...@@ -1138,6 +1178,16 @@ extern void nv10_fb_init_tile_region(struct drm_device *dev, int i,
extern void nv10_fb_set_tile_region(struct drm_device *dev, int i); extern void nv10_fb_set_tile_region(struct drm_device *dev, int i);
extern void nv10_fb_free_tile_region(struct drm_device *dev, int i); extern void nv10_fb_free_tile_region(struct drm_device *dev, int i);
/* nv20_fb.c */
extern int nv20_fb_vram_init(struct drm_device *dev);
extern int nv20_fb_init(struct drm_device *);
extern void nv20_fb_takedown(struct drm_device *);
extern void nv20_fb_init_tile_region(struct drm_device *dev, int i,
uint32_t addr, uint32_t size,
uint32_t pitch, uint32_t flags);
extern void nv20_fb_set_tile_region(struct drm_device *dev, int i);
extern void nv20_fb_free_tile_region(struct drm_device *dev, int i);
/* nv30_fb.c */ /* nv30_fb.c */
extern int nv30_fb_init(struct drm_device *); extern int nv30_fb_init(struct drm_device *);
extern void nv30_fb_takedown(struct drm_device *); extern void nv30_fb_takedown(struct drm_device *);
...@@ -1147,6 +1197,7 @@ extern void nv30_fb_init_tile_region(struct drm_device *dev, int i, ...@@ -1147,6 +1197,7 @@ extern void nv30_fb_init_tile_region(struct drm_device *dev, int i,
extern void nv30_fb_free_tile_region(struct drm_device *dev, int i); extern void nv30_fb_free_tile_region(struct drm_device *dev, int i);
/* nv40_fb.c */ /* nv40_fb.c */
extern int nv40_fb_vram_init(struct drm_device *dev);
extern int nv40_fb_init(struct drm_device *); extern int nv40_fb_init(struct drm_device *);
extern void nv40_fb_takedown(struct drm_device *); extern void nv40_fb_takedown(struct drm_device *);
extern void nv40_fb_set_tile_region(struct drm_device *dev, int i); extern void nv40_fb_set_tile_region(struct drm_device *dev, int i);
...@@ -1703,6 +1754,7 @@ nv44_graph_class(struct drm_device *dev) ...@@ -1703,6 +1754,7 @@ nv44_graph_class(struct drm_device *dev)
#define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO) #define NV_MEM_ACCESS_RW (NV_MEM_ACCESS_RO | NV_MEM_ACCESS_WO)
#define NV_MEM_ACCESS_SYS 4 #define NV_MEM_ACCESS_SYS 4
#define NV_MEM_ACCESS_VM 8 #define NV_MEM_ACCESS_VM 8
#define NV_MEM_ACCESS_NOSNOOP 16
#define NV_MEM_TARGET_VRAM 0 #define NV_MEM_TARGET_VRAM 0
#define NV_MEM_TARGET_PCI 1 #define NV_MEM_TARGET_PCI 1
......
...@@ -32,6 +32,14 @@ ...@@ -32,6 +32,14 @@
#define NV_DPMS_CLEARED 0x80 #define NV_DPMS_CLEARED 0x80
struct dp_train_func {
void (*link_set)(struct drm_device *, struct dcb_entry *, int crtc,
int nr, u32 bw, bool enhframe);
void (*train_set)(struct drm_device *, struct dcb_entry *, u8 pattern);
void (*train_adj)(struct drm_device *, struct dcb_entry *,
u8 lane, u8 swing, u8 preem);
};
struct nouveau_encoder { struct nouveau_encoder {
struct drm_encoder_slave base; struct drm_encoder_slave base;
...@@ -78,9 +86,19 @@ get_slave_funcs(struct drm_encoder *enc) ...@@ -78,9 +86,19 @@ get_slave_funcs(struct drm_encoder *enc)
return to_encoder_slave(enc)->slave_funcs; return to_encoder_slave(enc)->slave_funcs;
} }
/* nouveau_dp.c */
int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
uint8_t *data, int data_nr);
bool nouveau_dp_detect(struct drm_encoder *);
void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate,
struct dp_train_func *);
u8 *nouveau_dp_bios_data(struct drm_device *, struct dcb_entry *, u8 **);
struct nouveau_connector * struct nouveau_connector *
nouveau_encoder_connector_get(struct nouveau_encoder *encoder); nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
int nv50_sor_create(struct drm_connector *, struct dcb_entry *); int nv50_sor_create(struct drm_connector *, struct dcb_entry *);
void nv50_sor_dp_calc_tu(struct drm_device *, int, int, u32, u32);
int nv50_dac_create(struct drm_connector *, struct dcb_entry *); int nv50_dac_create(struct drm_connector *, struct dcb_entry *);
#endif /* __NOUVEAU_ENCODER_H__ */ #endif /* __NOUVEAU_ENCODER_H__ */
This diff is collapsed.
...@@ -582,6 +582,35 @@ mxm_shadow_dsm(struct drm_device *dev, u8 version) ...@@ -582,6 +582,35 @@ mxm_shadow_dsm(struct drm_device *dev, u8 version)
#define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0" #define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0"
static u8
wmi_wmmx_mxmi(struct drm_device *dev, u8 version)
{
u32 mxmi_args[] = { 0x494D584D /* MXMI */, version, 0 };
struct acpi_buffer args = { sizeof(mxmi_args), mxmi_args };
struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL };
union acpi_object *obj;
acpi_status status;
status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn);
if (ACPI_FAILURE(status)) {
MXM_DBG(dev, "WMMX MXMI returned %d\n", status);
return 0x00;
}
obj = retn.pointer;
if (obj->type == ACPI_TYPE_INTEGER) {
version = obj->integer.value;
MXM_DBG(dev, "WMMX MXMI version %d.%d\n",
(version >> 4), version & 0x0f);
} else {
version = 0;
MXM_DBG(dev, "WMMX MXMI returned non-integer\n");
}
kfree(obj);
return version;
}
static bool static bool
mxm_shadow_wmi(struct drm_device *dev, u8 version) mxm_shadow_wmi(struct drm_device *dev, u8 version)
{ {
...@@ -592,7 +621,15 @@ mxm_shadow_wmi(struct drm_device *dev, u8 version) ...@@ -592,7 +621,15 @@ mxm_shadow_wmi(struct drm_device *dev, u8 version)
union acpi_object *obj; union acpi_object *obj;
acpi_status status; acpi_status status;
if (!wmi_has_guid(WMI_WMMX_GUID)) if (!wmi_has_guid(WMI_WMMX_GUID)) {
MXM_DBG(dev, "WMMX GUID not found\n");
return false;
}
mxms_args[1] = wmi_wmmx_mxmi(dev, 0x00);
if (!mxms_args[1])
mxms_args[1] = wmi_wmmx_mxmi(dev, version);
if (!mxms_args[1])
return false; return false;
status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn);
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,10 +25,30 @@ ...@@ -25,10 +25,30 @@
#ifndef __NOUVEAU_PM_H__ #ifndef __NOUVEAU_PM_H__
#define __NOUVEAU_PM_H__ #define __NOUVEAU_PM_H__
struct nouveau_mem_exec_func {
struct drm_device *dev;
void (*precharge)(struct nouveau_mem_exec_func *);
void (*refresh)(struct nouveau_mem_exec_func *);
void (*refresh_auto)(struct nouveau_mem_exec_func *, bool);
void (*refresh_self)(struct nouveau_mem_exec_func *, bool);
void (*wait)(struct nouveau_mem_exec_func *, u32 nsec);
u32 (*mrg)(struct nouveau_mem_exec_func *, int mr);
void (*mrs)(struct nouveau_mem_exec_func *, int mr, u32 data);
void (*clock_set)(struct nouveau_mem_exec_func *);
void (*timing_set)(struct nouveau_mem_exec_func *);
void *priv;
};
/* nouveau_mem.c */
int nouveau_mem_exec(struct nouveau_mem_exec_func *,
struct nouveau_pm_level *);
/* nouveau_pm.c */ /* nouveau_pm.c */
int nouveau_pm_init(struct drm_device *dev); int nouveau_pm_init(struct drm_device *dev);
void nouveau_pm_fini(struct drm_device *dev); void nouveau_pm_fini(struct drm_device *dev);
void nouveau_pm_resume(struct drm_device *dev); void nouveau_pm_resume(struct drm_device *dev);
extern const struct nouveau_pm_profile_func nouveau_pm_static_profile_func;
void nouveau_pm_trigger(struct drm_device *dev);
/* nouveau_volt.c */ /* nouveau_volt.c */
void nouveau_volt_init(struct drm_device *); void nouveau_volt_init(struct drm_device *);
...@@ -41,6 +61,8 @@ int nouveau_voltage_gpio_set(struct drm_device *, int voltage); ...@@ -41,6 +61,8 @@ int nouveau_voltage_gpio_set(struct drm_device *, int voltage);
/* nouveau_perf.c */ /* nouveau_perf.c */
void nouveau_perf_init(struct drm_device *); void nouveau_perf_init(struct drm_device *);
void nouveau_perf_fini(struct drm_device *); void nouveau_perf_fini(struct drm_device *);
u8 *nouveau_perf_timing(struct drm_device *, u32 freq, u8 *ver, u8 *len);
u8 *nouveau_perf_ramcfg(struct drm_device *, u32 freq, u8 *ver, u8 *len);
/* nouveau_mem.c */ /* nouveau_mem.c */
void nouveau_mem_timing_init(struct drm_device *); void nouveau_mem_timing_init(struct drm_device *);
......
...@@ -87,7 +87,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -87,7 +87,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_get = nv04_pm_clocks_get;
engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_pre = nv04_pm_clocks_pre;
engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.clocks_set = nv04_pm_clocks_set;
engine->vram.init = nouveau_mem_detect; engine->vram.init = nv04_fb_vram_init;
engine->vram.takedown = nouveau_stub_takedown; engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid; engine->vram.flags_valid = nouveau_mem_flags_valid;
break; break;
...@@ -134,7 +134,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -134,7 +134,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_get = nv04_pm_clocks_get;
engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_pre = nv04_pm_clocks_pre;
engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.clocks_set = nv04_pm_clocks_set;
engine->vram.init = nouveau_mem_detect; if (dev_priv->chipset == 0x1a ||
dev_priv->chipset == 0x1f)
engine->vram.init = nv1a_fb_vram_init;
else
engine->vram.init = nv10_fb_vram_init;
engine->vram.takedown = nouveau_stub_takedown; engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid; engine->vram.flags_valid = nouveau_mem_flags_valid;
break; break;
...@@ -153,11 +157,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -153,11 +157,11 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->timer.init = nv04_timer_init; engine->timer.init = nv04_timer_init;
engine->timer.read = nv04_timer_read; engine->timer.read = nv04_timer_read;
engine->timer.takedown = nv04_timer_takedown; engine->timer.takedown = nv04_timer_takedown;
engine->fb.init = nv10_fb_init; engine->fb.init = nv20_fb_init;
engine->fb.takedown = nv10_fb_takedown; engine->fb.takedown = nv20_fb_takedown;
engine->fb.init_tile_region = nv10_fb_init_tile_region; engine->fb.init_tile_region = nv20_fb_init_tile_region;
engine->fb.set_tile_region = nv10_fb_set_tile_region; engine->fb.set_tile_region = nv20_fb_set_tile_region;
engine->fb.free_tile_region = nv10_fb_free_tile_region; engine->fb.free_tile_region = nv20_fb_free_tile_region;
engine->fifo.channels = 32; engine->fifo.channels = 32;
engine->fifo.init = nv10_fifo_init; engine->fifo.init = nv10_fifo_init;
engine->fifo.takedown = nv04_fifo_fini; engine->fifo.takedown = nv04_fifo_fini;
...@@ -181,7 +185,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -181,7 +185,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clocks_get = nv04_pm_clocks_get; engine->pm.clocks_get = nv04_pm_clocks_get;
engine->pm.clocks_pre = nv04_pm_clocks_pre; engine->pm.clocks_pre = nv04_pm_clocks_pre;
engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.clocks_set = nv04_pm_clocks_set;
engine->vram.init = nouveau_mem_detect; engine->vram.init = nv20_fb_vram_init;
engine->vram.takedown = nouveau_stub_takedown; engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid; engine->vram.flags_valid = nouveau_mem_flags_valid;
break; break;
...@@ -230,7 +234,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -230,7 +234,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.clocks_set = nv04_pm_clocks_set; engine->pm.clocks_set = nv04_pm_clocks_set;
engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_get = nouveau_voltage_gpio_get;
engine->pm.voltage_set = nouveau_voltage_gpio_set; engine->pm.voltage_set = nouveau_voltage_gpio_set;
engine->vram.init = nouveau_mem_detect; engine->vram.init = nv20_fb_vram_init;
engine->vram.takedown = nouveau_stub_takedown; engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid; engine->vram.flags_valid = nouveau_mem_flags_valid;
break; break;
...@@ -286,7 +290,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -286,7 +290,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
engine->pm.temp_get = nv40_temp_get; engine->pm.temp_get = nv40_temp_get;
engine->pm.pwm_get = nv40_pm_pwm_get; engine->pm.pwm_get = nv40_pm_pwm_get;
engine->pm.pwm_set = nv40_pm_pwm_set; engine->pm.pwm_set = nv40_pm_pwm_set;
engine->vram.init = nouveau_mem_detect; engine->vram.init = nv40_fb_vram_init;
engine->vram.takedown = nouveau_stub_takedown; engine->vram.takedown = nouveau_stub_takedown;
engine->vram.flags_valid = nouveau_mem_flags_valid; engine->vram.flags_valid = nouveau_mem_flags_valid;
break; break;
...@@ -588,47 +592,45 @@ nouveau_card_init(struct drm_device *dev) ...@@ -588,47 +592,45 @@ nouveau_card_init(struct drm_device *dev)
nv_mask(dev, 0x00088080, 0x00000800, 0x00000000); nv_mask(dev, 0x00088080, 0x00000800, 0x00000000);
} }
nouveau_pm_init(dev); /* PMC */
ret = engine->mc.init(dev);
ret = engine->vram.init(dev);
if (ret) if (ret)
goto out_bios; goto out_bios;
ret = nouveau_gpuobj_init(dev); /* PTIMER */
ret = engine->timer.init(dev);
if (ret) if (ret)
goto out_vram; goto out_mc;
ret = engine->instmem.init(dev); /* PFB */
ret = engine->fb.init(dev);
if (ret) if (ret)
goto out_gpuobj; goto out_timer;
ret = nouveau_mem_vram_init(dev); ret = engine->vram.init(dev);
if (ret) if (ret)
goto out_instmem; goto out_fb;
ret = nouveau_mem_gart_init(dev); /* PGPIO */
ret = nouveau_gpio_create(dev);
if (ret) if (ret)
goto out_ttmvram; goto out_vram;
/* PMC */ ret = nouveau_gpuobj_init(dev);
ret = engine->mc.init(dev);
if (ret) if (ret)
goto out_gart; goto out_gpio;
/* PGPIO */ ret = engine->instmem.init(dev);
ret = nouveau_gpio_create(dev);
if (ret) if (ret)
goto out_mc; goto out_gpuobj;
/* PTIMER */ ret = nouveau_mem_vram_init(dev);
ret = engine->timer.init(dev);
if (ret) if (ret)
goto out_gpio; goto out_instmem;
/* PFB */ ret = nouveau_mem_gart_init(dev);
ret = engine->fb.init(dev);
if (ret) if (ret)
goto out_timer; goto out_ttmvram;
if (!dev_priv->noaccel) { if (!dev_priv->noaccel) {
switch (dev_priv->card_type) { switch (dev_priv->card_type) {
...@@ -734,11 +736,12 @@ nouveau_card_init(struct drm_device *dev) ...@@ -734,11 +736,12 @@ nouveau_card_init(struct drm_device *dev)
goto out_irq; goto out_irq;
nouveau_backlight_init(dev); nouveau_backlight_init(dev);
nouveau_pm_init(dev);
if (dev_priv->eng[NVOBJ_ENGINE_GR]) { if (dev_priv->eng[NVOBJ_ENGINE_GR]) {
ret = nouveau_fence_init(dev); ret = nouveau_fence_init(dev);
if (ret) if (ret)
goto out_disp; goto out_pm;
ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL, ret = nouveau_channel_alloc(dev, &dev_priv->channel, NULL,
NvDmaFB, NvDmaTT); NvDmaFB, NvDmaTT);
...@@ -762,7 +765,8 @@ nouveau_card_init(struct drm_device *dev) ...@@ -762,7 +765,8 @@ nouveau_card_init(struct drm_device *dev)
nouveau_channel_put_unlocked(&dev_priv->channel); nouveau_channel_put_unlocked(&dev_priv->channel);
out_fence: out_fence:
nouveau_fence_fini(dev); nouveau_fence_fini(dev);
out_disp: out_pm:
nouveau_pm_fini(dev);
nouveau_backlight_exit(dev); nouveau_backlight_exit(dev);
nouveau_display_destroy(dev); nouveau_display_destroy(dev);
out_irq: out_irq:
...@@ -779,15 +783,6 @@ nouveau_card_init(struct drm_device *dev) ...@@ -779,15 +783,6 @@ nouveau_card_init(struct drm_device *dev)
dev_priv->eng[e]->destroy(dev,e ); dev_priv->eng[e]->destroy(dev,e );
} }
} }
engine->fb.takedown(dev);
out_timer:
engine->timer.takedown(dev);
out_gpio:
nouveau_gpio_destroy(dev);
out_mc:
engine->mc.takedown(dev);
out_gart:
nouveau_mem_gart_fini(dev); nouveau_mem_gart_fini(dev);
out_ttmvram: out_ttmvram:
nouveau_mem_vram_fini(dev); nouveau_mem_vram_fini(dev);
...@@ -795,10 +790,17 @@ nouveau_card_init(struct drm_device *dev) ...@@ -795,10 +790,17 @@ nouveau_card_init(struct drm_device *dev)
engine->instmem.takedown(dev); engine->instmem.takedown(dev);
out_gpuobj: out_gpuobj:
nouveau_gpuobj_takedown(dev); nouveau_gpuobj_takedown(dev);
out_gpio:
nouveau_gpio_destroy(dev);
out_vram: out_vram:
engine->vram.takedown(dev); engine->vram.takedown(dev);
out_fb:
engine->fb.takedown(dev);
out_timer:
engine->timer.takedown(dev);
out_mc:
engine->mc.takedown(dev);
out_bios: out_bios:
nouveau_pm_fini(dev);
nouveau_bios_takedown(dev); nouveau_bios_takedown(dev);
out_display_early: out_display_early:
engine->display.late_takedown(dev); engine->display.late_takedown(dev);
...@@ -823,6 +825,7 @@ static void nouveau_card_takedown(struct drm_device *dev) ...@@ -823,6 +825,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
nouveau_fence_fini(dev); nouveau_fence_fini(dev);
} }
nouveau_pm_fini(dev);
nouveau_backlight_exit(dev); nouveau_backlight_exit(dev);
nouveau_display_destroy(dev); nouveau_display_destroy(dev);
...@@ -835,11 +838,6 @@ static void nouveau_card_takedown(struct drm_device *dev) ...@@ -835,11 +838,6 @@ static void nouveau_card_takedown(struct drm_device *dev)
} }
} }
} }
engine->fb.takedown(dev);
engine->timer.takedown(dev);
nouveau_gpio_destroy(dev);
engine->mc.takedown(dev);
engine->display.late_takedown(dev);
if (dev_priv->vga_ram) { if (dev_priv->vga_ram) {
nouveau_bo_unpin(dev_priv->vga_ram); nouveau_bo_unpin(dev_priv->vga_ram);
...@@ -855,12 +853,17 @@ static void nouveau_card_takedown(struct drm_device *dev) ...@@ -855,12 +853,17 @@ static void nouveau_card_takedown(struct drm_device *dev)
engine->instmem.takedown(dev); engine->instmem.takedown(dev);
nouveau_gpuobj_takedown(dev); nouveau_gpuobj_takedown(dev);
engine->vram.takedown(dev);
nouveau_irq_fini(dev); nouveau_gpio_destroy(dev);
engine->vram.takedown(dev);
engine->fb.takedown(dev);
engine->timer.takedown(dev);
engine->mc.takedown(dev);
nouveau_pm_fini(dev);
nouveau_bios_takedown(dev); nouveau_bios_takedown(dev);
engine->display.late_takedown(dev);
nouveau_irq_fini(dev);
vga_client_register(dev->pdev, NULL, NULL, NULL); vga_client_register(dev->pdev, NULL, NULL, NULL);
} }
...@@ -990,7 +993,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev) ...@@ -990,7 +993,7 @@ static int nouveau_remove_conflicting_drivers(struct drm_device *dev)
int nouveau_load(struct drm_device *dev, unsigned long flags) int nouveau_load(struct drm_device *dev, unsigned long flags)
{ {
struct drm_nouveau_private *dev_priv; struct drm_nouveau_private *dev_priv;
uint32_t reg0, strap; uint32_t reg0 = ~0, strap;
resource_size_t mmio_start_offs; resource_size_t mmio_start_offs;
int ret; int ret;
...@@ -1009,49 +1012,21 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) ...@@ -1009,49 +1012,21 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n", NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
dev->pci_vendor, dev->pci_device, dev->pdev->class); dev->pci_vendor, dev->pci_device, dev->pdev->class);
/* resource 0 is mmio regs */ /* first up, map the start of mmio and determine the chipset */
/* resource 1 is linear FB */ dev_priv->mmio = ioremap(pci_resource_start(dev->pdev, 0), PAGE_SIZE);
/* resource 2 is RAMIN (mmio regs + 0x1000000) */ if (dev_priv->mmio) {
/* resource 6 is bios */
/* map the mmio regs */
mmio_start_offs = pci_resource_start(dev->pdev, 0);
dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000);
if (!dev_priv->mmio) {
NV_ERROR(dev, "Unable to initialize the mmio mapping. "
"Please report your setup to " DRIVER_EMAIL "\n");
ret = -EINVAL;
goto err_priv;
}
NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
(unsigned long long)mmio_start_offs);
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
/* Put the card in BE mode if it's not */ /* put the card into big-endian mode if it's not */
if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001) if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001)
nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001); nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);
DRM_MEMORYBARRIER(); DRM_MEMORYBARRIER();
#endif #endif
/* Time to determine the card architecture */ /* determine chipset and derive architecture from it */
reg0 = nv_rd32(dev, NV03_PMC_BOOT_0); reg0 = nv_rd32(dev, NV03_PMC_BOOT_0);
/* We're dealing with >=NV10 */
if ((reg0 & 0x0f000000) > 0) { if ((reg0 & 0x0f000000) > 0) {
/* Bit 27-20 contain the architecture in hex */
dev_priv->chipset = (reg0 & 0xff00000) >> 20; dev_priv->chipset = (reg0 & 0xff00000) >> 20;
/* NV04 or NV05 */
} else if ((reg0 & 0xff00fff0) == 0x20004000) {
if (reg0 & 0x00f00000)
dev_priv->chipset = 0x05;
else
dev_priv->chipset = 0x04;
} else
dev_priv->chipset = 0xff;
switch (dev_priv->chipset & 0xf0) { switch (dev_priv->chipset & 0xf0) {
case 0x00:
case 0x10: case 0x10:
case 0x20: case 0x20:
case 0x30: case 0x30:
...@@ -1074,14 +1049,41 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) ...@@ -1074,14 +1049,41 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
dev_priv->card_type = NV_D0; dev_priv->card_type = NV_D0;
break; break;
default: default:
NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); break;
}
} else
if ((reg0 & 0xff00fff0) == 0x20004000) {
if (reg0 & 0x00f00000)
dev_priv->chipset = 0x05;
else
dev_priv->chipset = 0x04;
dev_priv->card_type = NV_04;
}
iounmap(dev_priv->mmio);
}
if (!dev_priv->card_type) {
NV_ERROR(dev, "unsupported chipset 0x%08x\n", reg0);
ret = -EINVAL; ret = -EINVAL;
goto err_mmio; goto err_priv;
} }
NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n",
dev_priv->card_type, reg0); dev_priv->card_type, reg0);
/* map the mmio regs */
mmio_start_offs = pci_resource_start(dev->pdev, 0);
dev_priv->mmio = ioremap(mmio_start_offs, 0x00800000);
if (!dev_priv->mmio) {
NV_ERROR(dev, "Unable to initialize the mmio mapping. "
"Please report your setup to " DRIVER_EMAIL "\n");
ret = -EINVAL;
goto err_priv;
}
NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
(unsigned long long)mmio_start_offs);
/* determine frequency of timing crystal */ /* determine frequency of timing crystal */
strap = nv_rd32(dev, 0x101000); strap = nv_rd32(dev, 0x101000);
if ( dev_priv->chipset < 0x17 || if ( dev_priv->chipset < 0x17 ||
......
...@@ -3,6 +3,40 @@ ...@@ -3,6 +3,40 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
int
nv04_fb_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 boot0 = nv_rd32(dev, NV04_PFB_BOOT_0);
if (boot0 & 0x00000100) {
dev_priv->vram_size = ((boot0 >> 12) & 0xf) * 2 + 2;
dev_priv->vram_size *= 1024 * 1024;
} else {
switch (boot0 & NV04_PFB_BOOT_0_RAM_AMOUNT) {
case NV04_PFB_BOOT_0_RAM_AMOUNT_32MB:
dev_priv->vram_size = 32 * 1024 * 1024;
break;
case NV04_PFB_BOOT_0_RAM_AMOUNT_16MB:
dev_priv->vram_size = 16 * 1024 * 1024;
break;
case NV04_PFB_BOOT_0_RAM_AMOUNT_8MB:
dev_priv->vram_size = 8 * 1024 * 1024;
break;
case NV04_PFB_BOOT_0_RAM_AMOUNT_4MB:
dev_priv->vram_size = 4 * 1024 * 1024;
break;
}
}
if ((boot0 & 0x00000038) <= 0x10)
dev_priv->vram_type = NV_MEM_TYPE_SGRAM;
else
dev_priv->vram_type = NV_MEM_TYPE_SDRAM;
return 0;
}
int int
nv04_fb_init(struct drm_device *dev) nv04_fb_init(struct drm_device *dev)
{ {
......
...@@ -3,81 +3,16 @@ ...@@ -3,81 +3,16 @@
#include "nouveau_drv.h" #include "nouveau_drv.h"
#include "nouveau_drm.h" #include "nouveau_drm.h"
static struct drm_mm_node *
nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct drm_mm_node *mem;
int ret;
ret = drm_mm_pre_get(&pfb->tag_heap);
if (ret)
return NULL;
spin_lock(&dev_priv->tile.lock);
mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
if (mem)
mem = drm_mm_get_block_atomic(mem, size, 0);
spin_unlock(&dev_priv->tile.lock);
return mem;
}
static void
nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node *mem)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
spin_lock(&dev_priv->tile.lock);
drm_mm_put_block(mem);
spin_unlock(&dev_priv->tile.lock);
}
void void
nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr, nv10_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch, uint32_t flags) uint32_t size, uint32_t pitch, uint32_t flags)
{ {
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
tile->addr = addr; tile->addr = 0x80000000 | addr;
tile->limit = max(1u, addr + size) - 1; tile->limit = max(1u, addr + size) - 1;
tile->pitch = pitch; tile->pitch = pitch;
if (dev_priv->card_type == NV_20) {
if (flags & NOUVEAU_GEM_TILE_ZETA) {
/*
* Allocate some of the on-die tag memory,
* used to store Z compression meta-data (most
* likely just a bitmap determining if a given
* tile is compressed or not).
*/
tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
if (tile->tag_mem) {
/* Enable Z compression */
if (dev_priv->chipset >= 0x25)
tile->zcomp = tile->tag_mem->start |
(bpp == 16 ?
NV25_PFB_ZCOMP_MODE_16 :
NV25_PFB_ZCOMP_MODE_32);
else
tile->zcomp = tile->tag_mem->start |
NV20_PFB_ZCOMP_EN |
(bpp == 16 ? 0 :
NV20_PFB_ZCOMP_MODE_32);
}
tile->addr |= 3;
} else {
tile->addr |= 1;
}
} else {
tile->addr |= 1 << 31;
}
} }
void void
...@@ -86,11 +21,6 @@ nv10_fb_free_tile_region(struct drm_device *dev, int i) ...@@ -86,11 +21,6 @@ nv10_fb_free_tile_region(struct drm_device *dev, int i)
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i]; struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
if (tile->tag_mem) {
nv20_fb_free_tag(dev, tile->tag_mem);
tile->tag_mem = NULL;
}
tile->addr = tile->limit = tile->pitch = tile->zcomp = 0; tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
} }
...@@ -103,9 +33,48 @@ nv10_fb_set_tile_region(struct drm_device *dev, int i) ...@@ -103,9 +33,48 @@ nv10_fb_set_tile_region(struct drm_device *dev, int i)
nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit); nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch); nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
nv_wr32(dev, NV10_PFB_TILE(i), tile->addr); nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
}
if (dev_priv->card_type == NV_20) int
nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp); nv1a_fb_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct pci_dev *bridge;
uint32_t mem, mib;
bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
if (!bridge) {
NV_ERROR(dev, "no bridge device\n");
return 0;
}
if (dev_priv->chipset == 0x1a) {
pci_read_config_dword(bridge, 0x7c, &mem);
mib = ((mem >> 6) & 31) + 1;
} else {
pci_read_config_dword(bridge, 0x84, &mem);
mib = ((mem >> 4) & 127) + 1;
}
dev_priv->vram_size = mib * 1024 * 1024;
return 0;
}
int
nv10_fb_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 fifo_data = nv_rd32(dev, NV04_PFB_FIFO_DATA);
u32 cfg0 = nv_rd32(dev, 0x100200);
dev_priv->vram_size = fifo_data & NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK;
if (cfg0 & 0x00000001)
dev_priv->vram_type = NV_MEM_TYPE_DDR1;
else
dev_priv->vram_type = NV_MEM_TYPE_SDRAM;
return 0;
} }
int int
...@@ -115,14 +84,8 @@ nv10_fb_init(struct drm_device *dev) ...@@ -115,14 +84,8 @@ nv10_fb_init(struct drm_device *dev)
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb; struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
int i; int i;
pfb->num_tiles = NV10_PFB_TILE__SIZE;
if (dev_priv->card_type == NV_20)
drm_mm_init(&pfb->tag_heap, 0,
(dev_priv->chipset >= 0x25 ?
64 * 1024 : 32 * 1024));
/* Turn all the tiling regions off. */ /* Turn all the tiling regions off. */
pfb->num_tiles = NV10_PFB_TILE__SIZE;
for (i = 0; i < pfb->num_tiles; i++) for (i = 0; i < pfb->num_tiles; i++)
pfb->set_tile_region(dev, i); pfb->set_tile_region(dev, i);
...@@ -138,7 +101,4 @@ nv10_fb_takedown(struct drm_device *dev) ...@@ -138,7 +101,4 @@ nv10_fb_takedown(struct drm_device *dev)
for (i = 0; i < pfb->num_tiles; i++) for (i = 0; i < pfb->num_tiles; i++)
pfb->free_tile_region(dev, i); pfb->free_tile_region(dev, i);
if (dev_priv->card_type == NV_20)
drm_mm_takedown(&pfb->tag_heap);
} }
#include "drmP.h"
#include "drm.h"
#include "nouveau_drv.h"
#include "nouveau_drm.h"
static struct drm_mm_node *
nv20_fb_alloc_tag(struct drm_device *dev, uint32_t size)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
struct drm_mm_node *mem;
int ret;
ret = drm_mm_pre_get(&pfb->tag_heap);
if (ret)
return NULL;
spin_lock(&dev_priv->tile.lock);
mem = drm_mm_search_free(&pfb->tag_heap, size, 0, 0);
if (mem)
mem = drm_mm_get_block_atomic(mem, size, 0);
spin_unlock(&dev_priv->tile.lock);
return mem;
}
static void
nv20_fb_free_tag(struct drm_device *dev, struct drm_mm_node **pmem)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct drm_mm_node *mem = *pmem;
if (mem) {
spin_lock(&dev_priv->tile.lock);
drm_mm_put_block(mem);
spin_unlock(&dev_priv->tile.lock);
*pmem = NULL;
}
}
void
nv20_fb_init_tile_region(struct drm_device *dev, int i, uint32_t addr,
uint32_t size, uint32_t pitch, uint32_t flags)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
int bpp = (flags & NOUVEAU_GEM_TILE_32BPP ? 32 : 16);
tile->addr = 0x00000001 | addr;
tile->limit = max(1u, addr + size) - 1;
tile->pitch = pitch;
/* Allocate some of the on-die tag memory, used to store Z
* compression meta-data (most likely just a bitmap determining
* if a given tile is compressed or not).
*/
if (flags & NOUVEAU_GEM_TILE_ZETA) {
tile->tag_mem = nv20_fb_alloc_tag(dev, size / 256);
if (tile->tag_mem) {
/* Enable Z compression */
tile->zcomp = tile->tag_mem->start;
if (dev_priv->chipset >= 0x25) {
if (bpp == 16)
tile->zcomp |= NV25_PFB_ZCOMP_MODE_16;
else
tile->zcomp |= NV25_PFB_ZCOMP_MODE_32;
} else {
tile->zcomp |= NV20_PFB_ZCOMP_EN;
if (bpp != 16)
tile->zcomp |= NV20_PFB_ZCOMP_MODE_32;
}
}
tile->addr |= 2;
}
}
void
nv20_fb_free_tile_region(struct drm_device *dev, int i)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
tile->addr = tile->limit = tile->pitch = tile->zcomp = 0;
nv20_fb_free_tag(dev, &tile->tag_mem);
}
void
nv20_fb_set_tile_region(struct drm_device *dev, int i)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_tile_reg *tile = &dev_priv->tile.reg[i];
nv_wr32(dev, NV10_PFB_TLIMIT(i), tile->limit);
nv_wr32(dev, NV10_PFB_TSIZE(i), tile->pitch);
nv_wr32(dev, NV10_PFB_TILE(i), tile->addr);
nv_wr32(dev, NV20_PFB_ZCOMP(i), tile->zcomp);
}
int
nv20_fb_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 mem_size = nv_rd32(dev, 0x10020c);
u32 pbus1218 = nv_rd32(dev, 0x001218);
dev_priv->vram_size = mem_size & 0xff000000;
switch (pbus1218 & 0x00000300) {
case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_GDDR2; break;
}
return 0;
}
int
nv20_fb_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
int i;
if (dev_priv->chipset >= 0x25)
drm_mm_init(&pfb->tag_heap, 0, 64 * 1024);
else
drm_mm_init(&pfb->tag_heap, 0, 32 * 1024);
/* Turn all the tiling regions off. */
pfb->num_tiles = NV10_PFB_TILE__SIZE;
for (i = 0; i < pfb->num_tiles; i++)
pfb->set_tile_region(dev, i);
return 0;
}
void
nv20_fb_takedown(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
int i;
for (i = 0; i < pfb->num_tiles; i++)
pfb->free_tile_region(dev, i);
drm_mm_takedown(&pfb->tag_heap);
}
...@@ -71,6 +71,51 @@ nv44_fb_init_gart(struct drm_device *dev) ...@@ -71,6 +71,51 @@ nv44_fb_init_gart(struct drm_device *dev)
nv_wr32(dev, 0x100800, vinst | 0x00000010); nv_wr32(dev, 0x100800, vinst | 0x00000010);
} }
int
nv40_fb_vram_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
/* 0x001218 is actually present on a few other NV4X I looked at,
* and even contains sane values matching 0x100474. From looking
* at various vbios images however, this isn't the case everywhere.
* So, I chose to use the same regs I've seen NVIDIA reading around
* the memory detection, hopefully that'll get us the right numbers
*/
if (dev_priv->chipset == 0x40) {
u32 pbus1218 = nv_rd32(dev, 0x001218);
switch (pbus1218 & 0x00000300) {
case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_SDRAM; break;
case 0x00000100: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
case 0x00000200: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
case 0x00000300: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break;
}
} else
if (dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b) {
u32 pfb914 = nv_rd32(dev, 0x100914);
switch (pfb914 & 0x00000003) {
case 0x00000000: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
case 0x00000001: dev_priv->vram_type = NV_MEM_TYPE_DDR2; break;
case 0x00000002: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
case 0x00000003: break;
}
} else
if (dev_priv->chipset != 0x4e) {
u32 pfb474 = nv_rd32(dev, 0x100474);
if (pfb474 & 0x00000004)
dev_priv->vram_type = NV_MEM_TYPE_GDDR3;
if (pfb474 & 0x00000002)
dev_priv->vram_type = NV_MEM_TYPE_DDR2;
if (pfb474 & 0x00000001)
dev_priv->vram_type = NV_MEM_TYPE_DDR1;
} else {
dev_priv->vram_type = NV_MEM_TYPE_STOLEN;
}
dev_priv->vram_size = nv_rd32(dev, 0x10020c) & 0xff000000;
return 0;
}
int int
nv40_fb_init(struct drm_device *dev) nv40_fb_init(struct drm_device *dev)
{ {
......
...@@ -170,6 +170,41 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) ...@@ -170,6 +170,41 @@ nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update)
return ret; return ret;
} }
static int
nv50_crtc_set_color_vibrance(struct nouveau_crtc *nv_crtc, bool update)
{
struct drm_device *dev = nv_crtc->base.dev;
struct nouveau_channel *evo = nv50_display(dev)->master;
int ret;
int adj;
u32 hue, vib;
NV_DEBUG_KMS(dev, "vibrance = %i, hue = %i\n",
nv_crtc->color_vibrance, nv_crtc->vibrant_hue);
ret = RING_SPACE(evo, 2 + (update ? 2 : 0));
if (ret) {
NV_ERROR(dev, "no space while setting color vibrance\n");
return ret;
}
adj = (nv_crtc->color_vibrance > 0) ? 50 : 0;
vib = ((nv_crtc->color_vibrance * 2047 + adj) / 100) & 0xfff;
hue = ((nv_crtc->vibrant_hue * 2047) / 100) & 0xfff;
BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
OUT_RING (evo, (hue << 20) | (vib << 8));
if (update) {
BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
OUT_RING (evo, 0);
FIRE_RING (evo);
}
return 0;
}
struct nouveau_connector * struct nouveau_connector *
nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
{ {
...@@ -577,8 +612,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, ...@@ -577,8 +612,6 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
OUT_RING (evo, fb->base.depth == 8 ? OUT_RING (evo, fb->base.depth == 8 ?
NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON); NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
OUT_RING (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1); BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
OUT_RING (evo, (y << 16) | x); OUT_RING (evo, (y << 16) | x);
...@@ -661,6 +694,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, ...@@ -661,6 +694,7 @@ nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode,
nv_crtc->set_dither(nv_crtc, false); nv_crtc->set_dither(nv_crtc, false);
nv_crtc->set_scale(nv_crtc, false); nv_crtc->set_scale(nv_crtc, false);
nv_crtc->set_color_vibrance(nv_crtc, false);
return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
} }
...@@ -721,6 +755,9 @@ nv50_crtc_create(struct drm_device *dev, int index) ...@@ -721,6 +755,9 @@ nv50_crtc_create(struct drm_device *dev, int index)
if (!nv_crtc) if (!nv_crtc)
return -ENOMEM; return -ENOMEM;
nv_crtc->color_vibrance = 50;
nv_crtc->vibrant_hue = 0;
/* Default CLUT parameters, will be activated on the hw upon /* Default CLUT parameters, will be activated on the hw upon
* first mode set. * first mode set.
*/ */
...@@ -751,6 +788,7 @@ nv50_crtc_create(struct drm_device *dev, int index) ...@@ -751,6 +788,7 @@ nv50_crtc_create(struct drm_device *dev, int index)
/* set function pointers */ /* set function pointers */
nv_crtc->set_dither = nv50_crtc_set_dither; nv_crtc->set_dither = nv50_crtc_set_dither;
nv_crtc->set_scale = nv50_crtc_set_scale; nv_crtc->set_scale = nv50_crtc_set_scale;
nv_crtc->set_color_vibrance = nv50_crtc_set_color_vibrance;
drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs); drm_crtc_init(dev, &nv_crtc->base, &nv50_crtc_funcs);
drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs); drm_crtc_helper_add(&nv_crtc->base, &nv50_crtc_helper_funcs);
......
...@@ -50,6 +50,29 @@ nv50_sor_nr(struct drm_device *dev) ...@@ -50,6 +50,29 @@ nv50_sor_nr(struct drm_device *dev)
return 4; return 4;
} }
u32
nv50_display_active_crtcs(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 mask = 0;
int i;
if (dev_priv->chipset < 0x90 ||
dev_priv->chipset == 0x92 ||
dev_priv->chipset == 0xa0) {
for (i = 0; i < 2; i++)
mask |= nv_rd32(dev, NV50_PDISPLAY_SOR_MODE_CTRL_C(i));
} else {
for (i = 0; i < 4; i++)
mask |= nv_rd32(dev, NV90_PDISPLAY_SOR_MODE_CTRL_C(i));
}
for (i = 0; i < 3; i++)
mask |= nv_rd32(dev, NV50_PDISPLAY_DAC_MODE_CTRL_C(i));
return mask & 3;
}
static int static int
evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data) evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data)
{ {
...@@ -840,9 +863,9 @@ nv50_display_unk20_handler(struct drm_device *dev) ...@@ -840,9 +863,9 @@ nv50_display_unk20_handler(struct drm_device *dev)
if (type == OUTPUT_DP) { if (type == OUTPUT_DP) {
int link = !(dcb->dpconf.sor.link & 1); int link = !(dcb->dpconf.sor.link & 1);
if ((mc & 0x000f0000) == 0x00020000) if ((mc & 0x000f0000) == 0x00020000)
nouveau_dp_tu_update(dev, or, link, pclk, 18); nv50_sor_dp_calc_tu(dev, or, link, pclk, 18);
else else
nouveau_dp_tu_update(dev, or, link, pclk, 24); nv50_sor_dp_calc_tu(dev, or, link, pclk, 24);
} }
if (dcb->type != OUTPUT_ANALOG) { if (dcb->type != OUTPUT_ANALOG) {
......
...@@ -74,6 +74,8 @@ void nv50_display_destroy(struct drm_device *dev); ...@@ -74,6 +74,8 @@ void nv50_display_destroy(struct drm_device *dev);
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);
u32 nv50_display_active_crtcs(struct drm_device *);
int nv50_display_sync(struct drm_device *); int nv50_display_sync(struct drm_device *);
int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
struct nouveau_channel *chan); struct nouveau_channel *chan);
......
...@@ -104,7 +104,8 @@ ...@@ -104,7 +104,8 @@
#define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000 #define NV50_EVO_CRTC_SCALE_CTRL_INACTIVE 0x00000000
#define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009 #define NV50_EVO_CRTC_SCALE_CTRL_ACTIVE 0x00000009
#define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8 #define NV50_EVO_CRTC_COLOR_CTRL 0x000008a8
#define NV50_EVO_CRTC_COLOR_CTRL_COLOR 0x00040000 #define NV50_EVO_CRTC_COLOR_CTRL_VIBRANCE 0x000fff00
#define NV50_EVO_CRTC_COLOR_CTRL_HUE 0xfff00000
#define NV50_EVO_CRTC_FB_POS 0x000008c0 #define NV50_EVO_CRTC_FB_POS 0x000008c0
#define NV50_EVO_CRTC_REAL_RES 0x000008c8 #define NV50_EVO_CRTC_REAL_RES 0x000008c8
#define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4 #define NV50_EVO_CRTC_SCALE_CENTER_OFFSET 0x000008d4
......
This diff is collapsed.
...@@ -36,6 +36,193 @@ ...@@ -36,6 +36,193 @@
#include "nouveau_crtc.h" #include "nouveau_crtc.h"
#include "nv50_display.h" #include "nv50_display.h"
static u32
nv50_sor_dp_lane_map(struct drm_device *dev, struct dcb_entry *dcb, u8 lane)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */
static const u8 nv50[] = { 16, 8, 0, 24 };
if (dev_priv->card_type == 0xaf)
return nvaf[lane];
return nv50[lane];
}
static void
nv50_sor_dp_train_set(struct drm_device *dev, struct dcb_entry *dcb, u8 pattern)
{
u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x0f000000, pattern << 24);
}
static void
nv50_sor_dp_train_adj(struct drm_device *dev, struct dcb_entry *dcb,
u8 lane, u8 swing, u8 preem)
{
u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
u32 shift = nv50_sor_dp_lane_map(dev, dcb, lane);
u32 mask = 0x000000ff << shift;
u8 *table, *entry, *config;
table = nouveau_dp_bios_data(dev, dcb, &entry);
if (!table || (table[0] != 0x20 && table[0] != 0x21)) {
NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n");
return;
}
config = entry + table[4];
while (config[0] != swing || config[1] != preem) {
config += table[5];
if (config >= entry + table[4] + entry[4] * table[5])
return;
}
nv_mask(dev, 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(dev, NV50_SOR_DP_UNK130(or, link), 0x0000ff00, config[4] << 8);
}
static void
nv50_sor_dp_link_set(struct drm_device *dev, struct dcb_entry *dcb, int crtc,
int link_nr, u32 link_bw, bool enhframe)
{
u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1);
u32 dpctrl = nv_rd32(dev, NV50_SOR_DP_CTRL(or, link)) & ~0x001f4000;
u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800)) & ~0x000c0000;
u8 *table, *entry, mask;
int i;
table = nouveau_dp_bios_data(dev, dcb, &entry);
if (!table || (table[0] != 0x20 && table[0] != 0x21)) {
NV_ERROR(dev, "PDISP: unsupported DP table for chipset\n");
return;
}
entry = ROMPTR(dev, entry[10]);
if (entry) {
while (link_bw < ROM16(entry[0]) * 10)
entry += 4;
nouveau_bios_run_init_table(dev, ROM16(entry[2]), dcb, crtc);
}
dpctrl |= ((1 << link_nr) - 1) << 16;
if (enhframe)
dpctrl |= 0x00004000;
if (link_bw > 162000)
clksor |= 0x00040000;
nv_wr32(dev, 0x614300 + (or * 0x800), clksor);
nv_wr32(dev, NV50_SOR_DP_CTRL(or, link), dpctrl);
mask = 0;
for (i = 0; i < link_nr; i++)
mask |= 1 << (nv50_sor_dp_lane_map(dev, dcb, i) >> 3);
nv_mask(dev, NV50_SOR_DP_UNK130(or, link), 0x0000000f, mask);
}
static void
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;
u32 clksor = nv_rd32(dev, 0x614300 + (or * 0x800));
if (clksor & 0x000c0000)
*bw = 270000;
else
*bw = 162000;
if (dpctrl > 0x00030000) *nr = 4;
else if (dpctrl > 0x00010000) *nr = 2;
else *nr = 1;
}
void
nv50_sor_dp_calc_tu(struct drm_device *dev, int or, int link, u32 clk, u32 bpp)
{
const u32 symbol = 100000;
int bestTU = 0, bestVTUi = 0, bestVTUf = 0, bestVTUa = 0;
int TU, VTUi, VTUf, VTUa;
u64 link_data_rate, link_ratio, unk;
u32 best_diff = 64 * symbol;
u32 link_nr, link_bw, r;
/* calculate packed data rate for each lane */
nv50_sor_dp_link_get(dev, or, link, &link_nr, &link_bw);
link_data_rate = (clk * bpp / 8) / link_nr;
/* calculate ratio of packed data rate to link symbol rate */
link_ratio = link_data_rate * symbol;
r = do_div(link_ratio, link_bw);
for (TU = 64; TU >= 32; TU--) {
/* calculate average number of valid symbols in each TU */
u32 tu_valid = link_ratio * TU;
u32 calc, diff;
/* find a hw representation for the fraction.. */
VTUi = tu_valid / symbol;
calc = VTUi * symbol;
diff = tu_valid - calc;
if (diff) {
if (diff >= (symbol / 2)) {
VTUf = symbol / (symbol - diff);
if (symbol - (VTUf * diff))
VTUf++;
if (VTUf <= 15) {
VTUa = 1;
calc += symbol - (symbol / VTUf);
} else {
VTUa = 0;
VTUf = 1;
calc += symbol;
}
} else {
VTUa = 0;
VTUf = min((int)(symbol / diff), 15);
calc += symbol / VTUf;
}
diff = calc - tu_valid;
} else {
/* no remainder, but the hw doesn't like the fractional
* part to be zero. decrement the integer part and
* have the fraction add a whole symbol back
*/
VTUa = 0;
VTUf = 1;
VTUi--;
}
if (diff < best_diff) {
best_diff = diff;
bestTU = TU;
bestVTUa = VTUa;
bestVTUf = VTUf;
bestVTUi = VTUi;
if (diff == 0)
break;
}
}
if (!bestTU) {
NV_ERROR(dev, "DP: unable to find suitable config\n");
return;
}
/* XXX close to vbios numbers, but not right */
unk = (symbol - link_ratio) * bestTU;
unk *= link_ratio;
r = do_div(unk, symbol);
r = do_div(unk, symbol);
unk += 6;
nv_mask(dev, NV50_SOR_DP_CTRL(or, link), 0x000001fc, bestTU << 2);
nv_mask(dev, NV50_SOR_DP_SCFG(or, link), 0x010f7f3f, bestVTUa << 24 |
bestVTUf << 16 |
bestVTUi << 8 |
unk);
}
static void static void
nv50_sor_disconnect(struct drm_encoder *encoder) nv50_sor_disconnect(struct drm_encoder *encoder)
{ {
...@@ -117,20 +304,13 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) ...@@ -117,20 +304,13 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
} }
if (nv_encoder->dcb->type == OUTPUT_DP) { if (nv_encoder->dcb->type == OUTPUT_DP) {
struct nouveau_i2c_chan *auxch; struct dp_train_func func = {
.link_set = nv50_sor_dp_link_set,
.train_set = nv50_sor_dp_train_set,
.train_adj = nv50_sor_dp_train_adj
};
auxch = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index); nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, &func);
if (!auxch)
return;
if (mode == DRM_MODE_DPMS_ON) {
u8 status = DP_SET_POWER_D0;
nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
nouveau_dp_link_train(encoder, nv_encoder->dp.datarate);
} else {
u8 status = DP_SET_POWER_D3;
nouveau_dp_auxch(auxch, 8, DP_SET_POWER, &status, 1);
}
} }
} }
......
...@@ -57,27 +57,15 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, ...@@ -57,27 +57,15 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
} }
static inline u64 static inline u64
nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target) vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
{ {
struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private;
phys |= 1; /* present */ phys |= 1; /* present */
phys |= (u64)memtype << 40; phys |= (u64)memtype << 40;
/* IGPs don't have real VRAM, re-target to stolen system memory */
if (target == 0 && dev_priv->vram_sys_base) {
phys += dev_priv->vram_sys_base;
target = 3;
}
phys |= target << 4; phys |= target << 4;
if (vma->access & NV_MEM_ACCESS_SYS) if (vma->access & NV_MEM_ACCESS_SYS)
phys |= (1 << 6); phys |= (1 << 6);
if (!(vma->access & NV_MEM_ACCESS_WO)) if (!(vma->access & NV_MEM_ACCESS_WO))
phys |= (1 << 3); phys |= (1 << 3);
return phys; return phys;
} }
...@@ -85,11 +73,19 @@ void ...@@ -85,11 +73,19 @@ void
nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
{ {
struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private;
u32 comp = (mem->memtype & 0x180) >> 7; u32 comp = (mem->memtype & 0x180) >> 7;
u32 block; u32 block, target;
int i; int i;
phys = nv50_vm_addr(vma, phys, mem->memtype, 0); /* IGPs don't have real VRAM, re-target to stolen system memory */
target = 0;
if (dev_priv->vram_sys_base) {
phys += dev_priv->vram_sys_base;
target = 3;
}
phys = vm_addr(vma, phys, mem->memtype, target);
pte <<= 3; pte <<= 3;
cnt <<= 3; cnt <<= 3;
...@@ -125,9 +121,10 @@ void ...@@ -125,9 +121,10 @@ void
nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{ {
u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2;
pte <<= 3; pte <<= 3;
while (cnt--) { while (cnt--) {
u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2); u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target);
nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 0, lower_32_bits(phys));
nv_wo32(pgt, pte + 4, upper_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys));
pte += 8; pte += 8;
......
...@@ -189,8 +189,25 @@ nv50_vram_init(struct drm_device *dev) ...@@ -189,8 +189,25 @@ nv50_vram_init(struct drm_device *dev)
struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
u32 pfb714 = nv_rd32(dev, 0x100714);
u32 rblock, length; u32 rblock, length;
switch (pfb714 & 0x00000007) {
case 0: dev_priv->vram_type = NV_MEM_TYPE_DDR1; break;
case 1:
if (nouveau_mem_vbios_type(dev) == NV_MEM_TYPE_DDR3)
dev_priv->vram_type = NV_MEM_TYPE_DDR3;
else
dev_priv->vram_type = NV_MEM_TYPE_DDR2;
break;
case 2: dev_priv->vram_type = NV_MEM_TYPE_GDDR3; break;
case 3: dev_priv->vram_type = NV_MEM_TYPE_GDDR4; break;
case 4: dev_priv->vram_type = NV_MEM_TYPE_GDDR5; break;
default:
break;
}
dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x100200) & 0x4);
dev_priv->vram_size = nv_rd32(dev, 0x10020c); dev_priv->vram_size = nv_rd32(dev, 0x10020c);
dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32;
dev_priv->vram_size &= 0xffffffff00ULL; dev_priv->vram_size &= 0xffffffff00ULL;
......
...@@ -269,7 +269,7 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) ...@@ -269,7 +269,7 @@ calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq)
clk0 = calc_div(dev, clk, clk0, freq, &div1D); clk0 = calc_div(dev, clk, clk0, freq, &div1D);
/* see if we can get any closer using PLLs */ /* see if we can get any closer using PLLs */
if (clk0 != freq) { if (clk0 != freq && (0x00004387 & (1 << clk))) {
if (clk < 7) if (clk < 7)
clk1 = calc_pll(dev, clk, freq, &info->coef); clk1 = calc_pll(dev, clk, freq, &info->coef);
else else
......
...@@ -77,9 +77,11 @@ void ...@@ -77,9 +77,11 @@ void
nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt, nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
{ {
u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5;
pte <<= 3; pte <<= 3;
while (cnt--) { while (cnt--) {
u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5); u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, target);
nv_wo32(pgt, pte + 0, lower_32_bits(phys)); nv_wo32(pgt, pte + 0, lower_32_bits(phys));
nv_wo32(pgt, pte + 4, upper_32_bits(phys)); nv_wo32(pgt, pte + 4, upper_32_bits(phys));
pte += 8; pte += 8;
......
...@@ -106,23 +106,23 @@ nvc0_vram_init(struct drm_device *dev) ...@@ -106,23 +106,23 @@ nvc0_vram_init(struct drm_device *dev)
struct nouveau_vram_engine *vram = &dev_priv->engine.vram; struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */
const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */
u32 parts = nv_rd32(dev, 0x121c74); u32 parts = nv_rd32(dev, 0x022438);
u32 pmask = nv_rd32(dev, 0x022554);
u32 bsize = nv_rd32(dev, 0x10f20c); u32 bsize = nv_rd32(dev, 0x10f20c);
u32 offset, length; u32 offset, length;
bool uniform = true; bool uniform = true;
int ret, part; int ret, part;
NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800)); NV_DEBUG(dev, "0x100800: 0x%08x\n", nv_rd32(dev, 0x100800));
NV_DEBUG(dev, "parts 0x%08x bcast_mem_amount 0x%08x\n", parts, bsize); NV_DEBUG(dev, "parts 0x%08x mask 0x%08x\n", parts, pmask);
/* read amount of vram attached to each memory controller */ dev_priv->vram_type = nouveau_mem_vbios_type(dev);
part = 0; dev_priv->vram_rank_B = !!(nv_rd32(dev, 0x10f200) & 0x00000004);
while (parts) {
u32 psize = nv_rd32(dev, 0x11020c + (part++ * 0x1000));
if (psize == 0)
continue;
parts--;
/* read amount of vram attached to each memory controller */
for (part = 0; part < parts; part++) {
if (!(pmask & (1 << part))) {
u32 psize = nv_rd32(dev, 0x11020c + (part * 0x1000));
if (psize != bsize) { if (psize != bsize) {
if (psize < bsize) if (psize < bsize)
bsize = psize; bsize = psize;
...@@ -132,6 +132,7 @@ nvc0_vram_init(struct drm_device *dev) ...@@ -132,6 +132,7 @@ nvc0_vram_init(struct drm_device *dev)
NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize); NV_DEBUG(dev, "%d: mem_amount 0x%08x\n", part, psize);
dev_priv->vram_size += (u64)psize << 20; dev_priv->vram_size += (u64)psize << 20;
} }
}
/* if all controllers have the same amount attached, there's no holes */ /* if all controllers have the same amount attached, there's no holes */
if (uniform) { if (uniform) {
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment