Merge remote branch 'nouveau/for-airlied' into drm-next-stage
* nouveau/for-airlied: (25 commits) drm/nouveau: use ALIGN instead of open coding it drm/nouveau: report unknown connector state if lid closed drm/nouveau: support version 0x20 displayport tables drm/nouveau: Fix noaccel/nofbaccel option descriptions. drm/nv50: Implement ctxprog/state generation. drm/nouveau: use dcb connector types throughout the driver drm/nv50: enable hpd on any connector we know the gpio line for drm/nouveau: use dcb connector table for creating drm connectors drm/nouveau: construct a connector table for cards that lack a real one drm/nouveau: check for known dcb connector types drm/nouveau: parse dcb gpio/connector tables after encoders drm/nouveau: reorganise bios header, add dcb connector type enums drm/nouveau: merge nvbios and nouveau_bios_info drm/nouveau: merge parsed_dcb and bios_parsed_dcb into dcb_table drm/nouveau: rename parsed_dcb_gpio to dcb_gpio_table drm/nouveau: allow retrieval of vbios image from debugfs drm/nouveau: fix missing spin_unlock in failure path drm/nouveau: fix i2ctable bounds checking drm/nouveau: fix nouveau_i2c_find bounds checking drm/nouveau: fix pramdac_table range checking ... Conflicts: drivers/gpu/drm/nouveau/nouveau_gem.c
This commit is contained in:
commit
aa71fa3cd5
|
@ -16,7 +16,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
|
|||
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
|
||||
nv04_graph.o nv10_graph.o nv20_graph.o \
|
||||
nv40_graph.o nv50_graph.o \
|
||||
nv40_grctx.o \
|
||||
nv40_grctx.o nv50_grctx.o \
|
||||
nv04_instmem.o nv50_instmem.o \
|
||||
nv50_crtc.o nv50_dac.o nv50_sor.o \
|
||||
nv50_cursor.o nv50_display.o nv50_fbcon.o \
|
||||
|
|
|
@ -311,11 +311,11 @@ valid_reg(struct nvbios *bios, uint32_t reg)
|
|||
|
||||
/* C51 has misaligned regs on purpose. Marvellous */
|
||||
if (reg & 0x2 ||
|
||||
(reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
|
||||
(reg & 0x1 && dev_priv->vbios.chip_version != 0x51))
|
||||
NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
|
||||
|
||||
/* warn on C51 regs that haven't been verified accessible in tracing */
|
||||
if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
|
||||
if (reg & 0x1 && dev_priv->vbios.chip_version == 0x51 &&
|
||||
reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
|
||||
NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
|
||||
reg);
|
||||
|
@ -420,7 +420,7 @@ bios_wr32(struct nvbios *bios, uint32_t reg, uint32_t data)
|
|||
LOG_OLD_VALUE(bios_rd32(bios, reg));
|
||||
BIOSLOG(bios, " Write: Reg: 0x%08X, Data: 0x%08X\n", reg, data);
|
||||
|
||||
if (dev_priv->VBIOS.execute) {
|
||||
if (dev_priv->vbios.execute) {
|
||||
still_alive();
|
||||
nv_wr32(bios->dev, reg, data);
|
||||
}
|
||||
|
@ -647,7 +647,7 @@ nv50_pll_set(struct drm_device *dev, uint32_t reg, uint32_t clk)
|
|||
reg0 = (reg0 & 0xfff8ffff) | (pll.log2P << 16);
|
||||
reg1 = (reg1 & 0xffff0000) | (pll.N1 << 8) | pll.M1;
|
||||
|
||||
if (dev_priv->VBIOS.execute) {
|
||||
if (dev_priv->vbios.execute) {
|
||||
still_alive();
|
||||
nv_wr32(dev, reg + 4, reg1);
|
||||
nv_wr32(dev, reg + 0, reg0);
|
||||
|
@ -689,7 +689,7 @@ setPLL(struct nvbios *bios, uint32_t reg, uint32_t clk)
|
|||
static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
|
||||
/*
|
||||
* For the results of this function to be correct, CR44 must have been
|
||||
|
@ -700,7 +700,7 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
|
|||
|
||||
uint8_t dcb_entry = NVReadVgaCrtc5758(dev, bios->state.crtchead, 0);
|
||||
|
||||
if (dcb_entry > bios->bdcb.dcb.entries) {
|
||||
if (dcb_entry > bios->dcb.entries) {
|
||||
NV_ERROR(dev, "CR58 doesn't have a valid DCB entry currently "
|
||||
"(%02X)\n", dcb_entry);
|
||||
dcb_entry = 0x7f; /* unused / invalid marker */
|
||||
|
@ -713,25 +713,26 @@ static struct nouveau_i2c_chan *
|
|||
init_i2c_device_find(struct drm_device *dev, int i2c_index)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct bios_parsed_dcb *bdcb = &dev_priv->VBIOS.bdcb;
|
||||
struct dcb_table *dcb = &dev_priv->vbios.dcb;
|
||||
|
||||
if (i2c_index == 0xff) {
|
||||
/* note: dcb_entry_idx_from_crtchead needs pre-script set-up */
|
||||
int idx = dcb_entry_idx_from_crtchead(dev), shift = 0;
|
||||
int default_indices = bdcb->i2c_default_indices;
|
||||
int default_indices = dcb->i2c_default_indices;
|
||||
|
||||
if (idx != 0x7f && bdcb->dcb.entry[idx].i2c_upper_default)
|
||||
if (idx != 0x7f && dcb->entry[idx].i2c_upper_default)
|
||||
shift = 4;
|
||||
|
||||
i2c_index = (default_indices >> shift) & 0xf;
|
||||
}
|
||||
if (i2c_index == 0x80) /* g80+ */
|
||||
i2c_index = bdcb->i2c_default_indices & 0xf;
|
||||
i2c_index = dcb->i2c_default_indices & 0xf;
|
||||
|
||||
return nouveau_i2c_find(dev, i2c_index);
|
||||
}
|
||||
|
||||
static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
|
||||
static uint32_t
|
||||
get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
|
||||
{
|
||||
/*
|
||||
* For mlv < 0x80, it is an index into a table of TMDS base addresses.
|
||||
|
@ -744,6 +745,7 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
|
|||
*/
|
||||
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
const int pramdac_offset[13] = {
|
||||
0, 0, 0x8, 0, 0x2000, 0, 0, 0, 0x2008, 0, 0, 0, 0x2000 };
|
||||
const uint32_t pramdac_table[4] = {
|
||||
|
@ -756,13 +758,12 @@ static uint32_t get_tmds_index_reg(struct drm_device *dev, uint8_t mlv)
|
|||
dcb_entry = dcb_entry_idx_from_crtchead(dev);
|
||||
if (dcb_entry == 0x7f)
|
||||
return 0;
|
||||
dacoffset = pramdac_offset[
|
||||
dev_priv->VBIOS.bdcb.dcb.entry[dcb_entry].or];
|
||||
dacoffset = pramdac_offset[bios->dcb.entry[dcb_entry].or];
|
||||
if (mlv == 0x81)
|
||||
dacoffset ^= 8;
|
||||
return 0x6808b0 + dacoffset;
|
||||
} else {
|
||||
if (mlv > ARRAY_SIZE(pramdac_table)) {
|
||||
if (mlv >= ARRAY_SIZE(pramdac_table)) {
|
||||
NV_ERROR(dev, "Magic Lookup Value too big (%02X)\n",
|
||||
mlv);
|
||||
return 0;
|
||||
|
@ -2574,19 +2575,19 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
|
|||
|
||||
const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 };
|
||||
const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
|
||||
const uint8_t *gpio_table = &bios->data[bios->bdcb.gpio_table_ptr];
|
||||
const uint8_t *gpio_table = &bios->data[bios->dcb.gpio_table_ptr];
|
||||
const uint8_t *gpio_entry;
|
||||
int i;
|
||||
|
||||
if (!iexec->execute)
|
||||
return 1;
|
||||
|
||||
if (bios->bdcb.version != 0x40) {
|
||||
if (bios->dcb.version != 0x40) {
|
||||
NV_ERROR(bios->dev, "DCB table not version 4.0\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bios->bdcb.gpio_table_ptr) {
|
||||
if (!bios->dcb.gpio_table_ptr) {
|
||||
NV_WARN(bios->dev, "Invalid pointer to INIT_8E table\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -3123,7 +3124,7 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
|
|||
struct dcb_entry *dcbent, int head, bool dl)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
struct init_exec iexec = {true, false};
|
||||
|
||||
NV_TRACE(dev, "0x%04X: Parsing digital output script table\n",
|
||||
|
@ -3140,7 +3141,7 @@ run_digital_op_script(struct drm_device *dev, uint16_t scriptptr,
|
|||
static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entry *dcbent, int head, enum LVDS_script script)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint8_t sub = bios->data[bios->fp.xlated_entry + script] + (bios->fp.link_c_increment && dcbent->or & OUTPUT_C ? 1 : 0);
|
||||
uint16_t scriptofs = ROM16(bios->data[bios->init_script_tbls_ptr + sub * 2]);
|
||||
|
||||
|
@ -3194,7 +3195,7 @@ static int run_lvds_table(struct drm_device *dev, struct dcb_entry *dcbent, int
|
|||
* of a list of pxclks and script pointers.
|
||||
*/
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
unsigned int outputset = (dcbent->or == 4) ? 1 : 0;
|
||||
uint16_t scriptptr = 0, clktable;
|
||||
uint8_t clktableptr = 0;
|
||||
|
@ -3261,7 +3262,7 @@ int call_lvds_script(struct drm_device *dev, struct dcb_entry *dcbent, int head,
|
|||
*/
|
||||
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint8_t lvds_ver = bios->data[bios->fp.lvdsmanufacturerpointer];
|
||||
uint32_t sel_clk_binding, sel_clk;
|
||||
int ret;
|
||||
|
@ -3395,7 +3396,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
|
|||
#ifndef __powerpc__
|
||||
NV_ERROR(dev, "Pointer to flat panel table invalid\n");
|
||||
#endif
|
||||
bios->pub.digital_min_front_porch = 0x4b;
|
||||
bios->digital_min_front_porch = 0x4b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -3428,7 +3429,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
|
|||
* fptable[4] is the minimum
|
||||
* RAMDAC_FP_HCRTC -> RAMDAC_FP_HSYNC_START gap
|
||||
*/
|
||||
bios->pub.digital_min_front_porch = fptable[4];
|
||||
bios->digital_min_front_porch = fptable[4];
|
||||
ofs = -7;
|
||||
break;
|
||||
default:
|
||||
|
@ -3467,7 +3468,7 @@ static int parse_fp_mode_table(struct drm_device *dev, struct nvbios *bios)
|
|||
|
||||
/* nv4x cards need both a strap value and fpindex of 0xf to use DDC */
|
||||
if (lth.lvds_ver > 0x10)
|
||||
bios->pub.fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
|
||||
bios->fp_no_ddc = fpstrapping != 0xf || fpindex != 0xf;
|
||||
|
||||
/*
|
||||
* If either the strap or xlated fpindex value are 0xf there is no
|
||||
|
@ -3491,7 +3492,7 @@ 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)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint8_t *mode_entry = &bios->data[bios->fp.mode_ptr];
|
||||
|
||||
if (!mode) /* just checking whether we can produce a mode */
|
||||
|
@ -3562,11 +3563,11 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b
|
|||
* until later, when this function should be called with non-zero pxclk
|
||||
*/
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
int fpstrapping = get_fp_strap(dev, bios), lvdsmanufacturerindex = 0;
|
||||
struct lvdstableheader lth;
|
||||
uint16_t lvdsofs;
|
||||
int ret, chip_version = bios->pub.chip_version;
|
||||
int ret, chip_version = bios->chip_version;
|
||||
|
||||
ret = parse_lvds_manufacturer_table_header(dev, bios, <h);
|
||||
if (ret)
|
||||
|
@ -3682,7 +3683,7 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
uint16_t record, int record_len, int record_nr)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint32_t entry;
|
||||
uint16_t table;
|
||||
int i, v;
|
||||
|
@ -3716,7 +3717,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
int *length)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint8_t *table;
|
||||
|
||||
if (!bios->display.dp_table_ptr) {
|
||||
|
@ -3725,7 +3726,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
}
|
||||
table = &bios->data[bios->display.dp_table_ptr];
|
||||
|
||||
if (table[0] != 0x21) {
|
||||
if (table[0] != 0x20 && table[0] != 0x21) {
|
||||
NV_ERROR(dev, "DisplayPort table version 0x%02x unknown\n",
|
||||
table[0]);
|
||||
return NULL;
|
||||
|
@ -3765,7 +3766,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
*/
|
||||
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint8_t *table = &bios->data[bios->display.script_table_ptr];
|
||||
uint8_t *otable = NULL;
|
||||
uint16_t script;
|
||||
|
@ -3918,8 +3919,8 @@ int run_tmds_table(struct drm_device *dev, struct dcb_entry *dcbent, int head, i
|
|||
*/
|
||||
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
int cv = bios->pub.chip_version;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
int cv = bios->chip_version;
|
||||
uint16_t clktable = 0, scriptptr;
|
||||
uint32_t sel_clk_binding, sel_clk;
|
||||
|
||||
|
@ -3978,8 +3979,8 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
|
|||
*/
|
||||
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
int cv = bios->pub.chip_version, pllindex = 0;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
int cv = bios->chip_version, pllindex = 0;
|
||||
uint8_t pll_lim_ver = 0, headerlen = 0, recordlen = 0, entries = 0;
|
||||
uint32_t crystal_strap_mask, crystal_straps;
|
||||
|
||||
|
@ -4332,7 +4333,7 @@ static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint
|
|||
*/
|
||||
|
||||
bios->major_version = bios->data[offset + 3];
|
||||
bios->pub.chip_version = bios->data[offset + 2];
|
||||
bios->chip_version = bios->data[offset + 2];
|
||||
NV_TRACE(dev, "Bios version %02x.%02x.%02x.%02x\n",
|
||||
bios->data[offset + 3], bios->data[offset + 2],
|
||||
bios->data[offset + 1], bios->data[offset]);
|
||||
|
@ -4402,7 +4403,7 @@ static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
|
|||
}
|
||||
|
||||
/* First entry is normal dac, 2nd tv-out perhaps? */
|
||||
bios->pub.dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
|
||||
bios->dactestval = ROM32(bios->data[load_table_ptr + headerlen]) & 0x3ff;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4526,8 +4527,8 @@ static int parse_bit_i_tbl_entry(struct drm_device *dev, struct nvbios *bios, st
|
|||
return -ENOSYS;
|
||||
}
|
||||
|
||||
bios->pub.dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
|
||||
bios->pub.tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]);
|
||||
bios->dactestval = ROM32(bios->data[daccmpoffset + dacheaderlen]);
|
||||
bios->tvdactestval = ROM32(bios->data[daccmpoffset + dacheaderlen + 4]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -4796,11 +4797,11 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
|
|||
uint16_t legacy_scripts_offset, legacy_i2c_offset;
|
||||
|
||||
/* load needed defaults in case we can't parse this info */
|
||||
bios->bdcb.dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
|
||||
bios->bdcb.dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
|
||||
bios->bdcb.dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
|
||||
bios->bdcb.dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
|
||||
bios->pub.digital_min_front_porch = 0x4b;
|
||||
bios->dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX;
|
||||
bios->dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX;
|
||||
bios->dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX;
|
||||
bios->dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX;
|
||||
bios->digital_min_front_porch = 0x4b;
|
||||
bios->fmaxvco = 256000;
|
||||
bios->fminvco = 128000;
|
||||
bios->fp.duallink_transition_clk = 90000;
|
||||
|
@ -4907,10 +4908,10 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi
|
|||
bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset];
|
||||
bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1];
|
||||
bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2];
|
||||
bios->bdcb.dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
|
||||
bios->bdcb.dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
|
||||
bios->bdcb.dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
|
||||
bios->bdcb.dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
|
||||
bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4];
|
||||
bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5];
|
||||
bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6];
|
||||
bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7];
|
||||
|
||||
if (bmplength > 74) {
|
||||
bios->fmaxvco = ROM32(bmp[67]);
|
||||
|
@ -4984,7 +4985,8 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
|
|||
else
|
||||
NV_WARN(dev,
|
||||
"DCB I2C table has more entries than indexable "
|
||||
"(%d entries, max index 15)\n", i2ctable[2]);
|
||||
"(%d entries, max %d)\n", i2ctable[2],
|
||||
DCB_MAX_NUM_I2C_ENTRIES);
|
||||
entry_len = i2ctable[3];
|
||||
/* [4] is i2c_default_indices, read in parse_dcb_table() */
|
||||
}
|
||||
|
@ -5000,8 +5002,8 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
|
|||
|
||||
if (index == 0xf)
|
||||
return 0;
|
||||
if (index > i2c_entries) {
|
||||
NV_ERROR(dev, "DCB I2C index too big (%d > %d)\n",
|
||||
if (index >= i2c_entries) {
|
||||
NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n",
|
||||
index, i2ctable[2]);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -5036,7 +5038,7 @@ read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, i
|
|||
static struct dcb_gpio_entry *
|
||||
new_gpio_entry(struct nvbios *bios)
|
||||
{
|
||||
struct parsed_dcb_gpio *gpio = &bios->bdcb.gpio;
|
||||
struct dcb_gpio_table *gpio = &bios->dcb.gpio;
|
||||
|
||||
return &gpio->entry[gpio->entries++];
|
||||
}
|
||||
|
@ -5045,14 +5047,14 @@ struct dcb_gpio_entry *
|
|||
nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bios->bdcb.gpio.entries; i++) {
|
||||
if (bios->bdcb.gpio.entry[i].tag != tag)
|
||||
for (i = 0; i < bios->dcb.gpio.entries; i++) {
|
||||
if (bios->dcb.gpio.entry[i].tag != tag)
|
||||
continue;
|
||||
|
||||
return &bios->bdcb.gpio.entry[i];
|
||||
return &bios->dcb.gpio.entry[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -5100,7 +5102,7 @@ static void
|
|||
parse_dcb_gpio_table(struct nvbios *bios)
|
||||
{
|
||||
struct drm_device *dev = bios->dev;
|
||||
uint16_t gpio_table_ptr = bios->bdcb.gpio_table_ptr;
|
||||
uint16_t gpio_table_ptr = bios->dcb.gpio_table_ptr;
|
||||
uint8_t *gpio_table = &bios->data[gpio_table_ptr];
|
||||
int header_len = gpio_table[1],
|
||||
entries = gpio_table[2],
|
||||
|
@ -5108,7 +5110,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
|
|||
void (*parse_entry)(struct nvbios *, uint16_t) = NULL;
|
||||
int i;
|
||||
|
||||
if (bios->bdcb.version >= 0x40) {
|
||||
if (bios->dcb.version >= 0x40) {
|
||||
if (gpio_table_ptr && entry_len != 4) {
|
||||
NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
|
||||
return;
|
||||
|
@ -5116,7 +5118,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
|
|||
|
||||
parse_entry = parse_dcb40_gpio_entry;
|
||||
|
||||
} else if (bios->bdcb.version >= 0x30) {
|
||||
} else if (bios->dcb.version >= 0x30) {
|
||||
if (gpio_table_ptr && entry_len != 2) {
|
||||
NV_WARN(dev, "Invalid DCB GPIO table entry length.\n");
|
||||
return;
|
||||
|
@ -5124,7 +5126,7 @@ parse_dcb_gpio_table(struct nvbios *bios)
|
|||
|
||||
parse_entry = parse_dcb30_gpio_entry;
|
||||
|
||||
} else if (bios->bdcb.version >= 0x22) {
|
||||
} else if (bios->dcb.version >= 0x22) {
|
||||
/*
|
||||
* DCBs older than v3.0 don't really have a GPIO
|
||||
* table, instead they keep some GPIO info at fixed
|
||||
|
@ -5158,30 +5160,67 @@ struct dcb_connector_table_entry *
|
|||
nouveau_bios_connector_entry(struct drm_device *dev, int index)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
struct dcb_connector_table_entry *cte;
|
||||
|
||||
if (index >= bios->bdcb.connector.entries)
|
||||
if (index >= bios->dcb.connector.entries)
|
||||
return NULL;
|
||||
|
||||
cte = &bios->bdcb.connector.entry[index];
|
||||
cte = &bios->dcb.connector.entry[index];
|
||||
if (cte->type == 0xff)
|
||||
return NULL;
|
||||
|
||||
return cte;
|
||||
}
|
||||
|
||||
static enum dcb_connector_type
|
||||
divine_connector_type(struct nvbios *bios, int index)
|
||||
{
|
||||
struct dcb_table *dcb = &bios->dcb;
|
||||
unsigned encoders = 0, type = DCB_CONNECTOR_NONE;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
if (dcb->entry[i].connector == index)
|
||||
encoders |= (1 << dcb->entry[i].type);
|
||||
}
|
||||
|
||||
if (encoders & (1 << OUTPUT_DP)) {
|
||||
if (encoders & (1 << OUTPUT_TMDS))
|
||||
type = DCB_CONNECTOR_DP;
|
||||
else
|
||||
type = DCB_CONNECTOR_eDP;
|
||||
} else
|
||||
if (encoders & (1 << OUTPUT_TMDS)) {
|
||||
if (encoders & (1 << OUTPUT_ANALOG))
|
||||
type = DCB_CONNECTOR_DVI_I;
|
||||
else
|
||||
type = DCB_CONNECTOR_DVI_D;
|
||||
} else
|
||||
if (encoders & (1 << OUTPUT_ANALOG)) {
|
||||
type = DCB_CONNECTOR_VGA;
|
||||
} else
|
||||
if (encoders & (1 << OUTPUT_LVDS)) {
|
||||
type = DCB_CONNECTOR_LVDS;
|
||||
} else
|
||||
if (encoders & (1 << OUTPUT_TV)) {
|
||||
type = DCB_CONNECTOR_TV_0;
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_dcb_connector_table(struct nvbios *bios)
|
||||
{
|
||||
struct drm_device *dev = bios->dev;
|
||||
struct dcb_connector_table *ct = &bios->bdcb.connector;
|
||||
struct dcb_connector_table *ct = &bios->dcb.connector;
|
||||
struct dcb_connector_table_entry *cte;
|
||||
uint8_t *conntab = &bios->data[bios->bdcb.connector_table_ptr];
|
||||
uint8_t *conntab = &bios->data[bios->dcb.connector_table_ptr];
|
||||
uint8_t *entry;
|
||||
int i;
|
||||
|
||||
if (!bios->bdcb.connector_table_ptr) {
|
||||
if (!bios->dcb.connector_table_ptr) {
|
||||
NV_DEBUG_KMS(dev, "No DCB connector table present\n");
|
||||
return;
|
||||
}
|
||||
|
@ -5203,6 +5242,7 @@ parse_dcb_connector_table(struct nvbios *bios)
|
|||
cte->entry = ROM16(entry[0]);
|
||||
else
|
||||
cte->entry = ROM32(entry[0]);
|
||||
|
||||
cte->type = (cte->entry & 0x000000ff) >> 0;
|
||||
cte->index = (cte->entry & 0x00000f00) >> 8;
|
||||
switch (cte->entry & 0x00033000) {
|
||||
|
@ -5228,10 +5268,33 @@ parse_dcb_connector_table(struct nvbios *bios)
|
|||
|
||||
NV_INFO(dev, " %d: 0x%08x: type 0x%02x idx %d tag 0x%02x\n",
|
||||
i, cte->entry, cte->type, cte->index, cte->gpio_tag);
|
||||
|
||||
/* check for known types, fallback to guessing the type
|
||||
* from attached encoders if we hit an unknown.
|
||||
*/
|
||||
switch (cte->type) {
|
||||
case DCB_CONNECTOR_VGA:
|
||||
case DCB_CONNECTOR_TV_0:
|
||||
case DCB_CONNECTOR_TV_1:
|
||||
case DCB_CONNECTOR_TV_3:
|
||||
case DCB_CONNECTOR_DVI_I:
|
||||
case DCB_CONNECTOR_DVI_D:
|
||||
case DCB_CONNECTOR_LVDS:
|
||||
case DCB_CONNECTOR_DP:
|
||||
case DCB_CONNECTOR_eDP:
|
||||
case DCB_CONNECTOR_HDMI_0:
|
||||
case DCB_CONNECTOR_HDMI_1:
|
||||
break;
|
||||
default:
|
||||
cte->type = divine_connector_type(bios, cte->index);
|
||||
NV_WARN(dev, "unknown type, using 0x%02x", cte->type);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb)
|
||||
static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb)
|
||||
{
|
||||
struct dcb_entry *entry = &dcb->entry[dcb->entries];
|
||||
|
||||
|
@ -5241,7 +5304,7 @@ static struct dcb_entry *new_dcb_entry(struct parsed_dcb *dcb)
|
|||
return entry;
|
||||
}
|
||||
|
||||
static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
|
||||
static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
|
||||
{
|
||||
struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||
|
||||
|
@ -5252,7 +5315,7 @@ static void fabricate_vga_output(struct parsed_dcb *dcb, int i2c, int heads)
|
|||
/* "or" mostly unused in early gen crt modesetting, 0 is fine */
|
||||
}
|
||||
|
||||
static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
|
||||
static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
|
||||
{
|
||||
struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||
|
||||
|
@ -5279,7 +5342,7 @@ static void fabricate_dvi_i_output(struct parsed_dcb *dcb, bool twoHeads)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads)
|
||||
static void fabricate_tv_output(struct dcb_table *dcb, bool twoHeads)
|
||||
{
|
||||
struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||
|
||||
|
@ -5290,13 +5353,13 @@ static void fabricate_tv_output(struct parsed_dcb *dcb, bool twoHeads)
|
|||
}
|
||||
|
||||
static bool
|
||||
parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
||||
parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
|
||||
uint32_t conn, uint32_t conf, struct dcb_entry *entry)
|
||||
{
|
||||
entry->type = conn & 0xf;
|
||||
entry->i2c_index = (conn >> 4) & 0xf;
|
||||
entry->heads = (conn >> 8) & 0xf;
|
||||
if (bdcb->version >= 0x40)
|
||||
if (dcb->version >= 0x40)
|
||||
entry->connector = (conn >> 12) & 0xf;
|
||||
entry->bus = (conn >> 16) & 0xf;
|
||||
entry->location = (conn >> 20) & 0x3;
|
||||
|
@ -5314,7 +5377,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
|||
* Although the rest of a CRT conf dword is usually
|
||||
* zeros, mac biosen have stuff there so we must mask
|
||||
*/
|
||||
entry->crtconf.maxfreq = (bdcb->version < 0x30) ?
|
||||
entry->crtconf.maxfreq = (dcb->version < 0x30) ?
|
||||
(conf & 0xffff) * 10 :
|
||||
(conf & 0xff) * 10000;
|
||||
break;
|
||||
|
@ -5323,7 +5386,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
|||
uint32_t mask;
|
||||
if (conf & 0x1)
|
||||
entry->lvdsconf.use_straps_for_mode = true;
|
||||
if (bdcb->version < 0x22) {
|
||||
if (dcb->version < 0x22) {
|
||||
mask = ~0xd;
|
||||
/*
|
||||
* The laptop in bug 14567 lies and claims to not use
|
||||
|
@ -5347,7 +5410,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
|||
* Until we even try to use these on G8x, it's
|
||||
* useless reporting unknown bits. They all are.
|
||||
*/
|
||||
if (bdcb->version >= 0x40)
|
||||
if (dcb->version >= 0x40)
|
||||
break;
|
||||
|
||||
NV_ERROR(dev, "Unknown LVDS configuration bits, "
|
||||
|
@ -5357,7 +5420,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
|||
}
|
||||
case OUTPUT_TV:
|
||||
{
|
||||
if (bdcb->version >= 0x30)
|
||||
if (dcb->version >= 0x30)
|
||||
entry->tvconf.has_component_output = conf & (0x8 << 4);
|
||||
else
|
||||
entry->tvconf.has_component_output = false;
|
||||
|
@ -5384,8 +5447,10 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
|||
break;
|
||||
case 0xe:
|
||||
/* weird g80 mobile type that "nv" treats as a terminator */
|
||||
bdcb->dcb.entries--;
|
||||
dcb->entries--;
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* unsure what DCB version introduces this, 3.0? */
|
||||
|
@ -5396,7 +5461,7 @@ parse_dcb20_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
|||
}
|
||||
|
||||
static bool
|
||||
parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
|
||||
parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb,
|
||||
uint32_t conn, uint32_t conf, struct dcb_entry *entry)
|
||||
{
|
||||
switch (conn & 0x0000000f) {
|
||||
|
@ -5462,27 +5527,27 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool parse_dcb_entry(struct drm_device *dev, struct bios_parsed_dcb *bdcb,
|
||||
static bool parse_dcb_entry(struct drm_device *dev, struct dcb_table *dcb,
|
||||
uint32_t conn, uint32_t conf)
|
||||
{
|
||||
struct dcb_entry *entry = new_dcb_entry(&bdcb->dcb);
|
||||
struct dcb_entry *entry = new_dcb_entry(dcb);
|
||||
bool ret;
|
||||
|
||||
if (bdcb->version >= 0x20)
|
||||
ret = parse_dcb20_entry(dev, bdcb, conn, conf, entry);
|
||||
if (dcb->version >= 0x20)
|
||||
ret = parse_dcb20_entry(dev, dcb, conn, conf, entry);
|
||||
else
|
||||
ret = parse_dcb15_entry(dev, &bdcb->dcb, conn, conf, entry);
|
||||
ret = parse_dcb15_entry(dev, dcb, conn, conf, entry);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
read_dcb_i2c_entry(dev, bdcb->version, bdcb->i2c_table,
|
||||
entry->i2c_index, &bdcb->dcb.i2c[entry->i2c_index]);
|
||||
read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
|
||||
entry->i2c_index, &dcb->i2c[entry->i2c_index]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static
|
||||
void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
|
||||
void merge_like_dcb_entries(struct drm_device *dev, struct dcb_table *dcb)
|
||||
{
|
||||
/*
|
||||
* DCB v2.0 lists each output combination separately.
|
||||
|
@ -5534,8 +5599,7 @@ static int
|
|||
parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct bios_parsed_dcb *bdcb = &bios->bdcb;
|
||||
struct parsed_dcb *dcb;
|
||||
struct dcb_table *dcb = &bios->dcb;
|
||||
uint16_t dcbptr = 0, i2ctabptr = 0;
|
||||
uint8_t *dcbtable;
|
||||
uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
|
||||
|
@ -5543,9 +5607,6 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
|||
int recordlength = 8, confofs = 4;
|
||||
int i;
|
||||
|
||||
dcb = bios->pub.dcb = &bdcb->dcb;
|
||||
dcb->entries = 0;
|
||||
|
||||
/* get the offset from 0x36 */
|
||||
if (dev_priv->card_type > NV_04) {
|
||||
dcbptr = ROM16(bios->data[0x36]);
|
||||
|
@ -5567,21 +5628,21 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
|||
dcbtable = &bios->data[dcbptr];
|
||||
|
||||
/* get DCB version */
|
||||
bdcb->version = dcbtable[0];
|
||||
dcb->version = dcbtable[0];
|
||||
NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n",
|
||||
bdcb->version >> 4, bdcb->version & 0xf);
|
||||
dcb->version >> 4, dcb->version & 0xf);
|
||||
|
||||
if (bdcb->version >= 0x20) { /* NV17+ */
|
||||
if (dcb->version >= 0x20) { /* NV17+ */
|
||||
uint32_t sig;
|
||||
|
||||
if (bdcb->version >= 0x30) { /* NV40+ */
|
||||
if (dcb->version >= 0x30) { /* NV40+ */
|
||||
headerlen = dcbtable[1];
|
||||
entries = dcbtable[2];
|
||||
recordlength = dcbtable[3];
|
||||
i2ctabptr = ROM16(dcbtable[4]);
|
||||
sig = ROM32(dcbtable[6]);
|
||||
bdcb->gpio_table_ptr = ROM16(dcbtable[10]);
|
||||
bdcb->connector_table_ptr = ROM16(dcbtable[20]);
|
||||
dcb->gpio_table_ptr = ROM16(dcbtable[10]);
|
||||
dcb->connector_table_ptr = ROM16(dcbtable[20]);
|
||||
} else {
|
||||
i2ctabptr = ROM16(dcbtable[2]);
|
||||
sig = ROM32(dcbtable[4]);
|
||||
|
@ -5593,7 +5654,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
|||
"signature (%08X)\n", sig);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (bdcb->version >= 0x15) { /* some NV11 and NV20 */
|
||||
} else if (dcb->version >= 0x15) { /* some NV11 and NV20 */
|
||||
char sig[8] = { 0 };
|
||||
|
||||
strncpy(sig, (char *)&dcbtable[-7], 7);
|
||||
|
@ -5641,14 +5702,11 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
|||
if (!i2ctabptr)
|
||||
NV_WARN(dev, "No pointer to DCB I2C port table\n");
|
||||
else {
|
||||
bdcb->i2c_table = &bios->data[i2ctabptr];
|
||||
if (bdcb->version >= 0x30)
|
||||
bdcb->i2c_default_indices = bdcb->i2c_table[4];
|
||||
dcb->i2c_table = &bios->data[i2ctabptr];
|
||||
if (dcb->version >= 0x30)
|
||||
dcb->i2c_default_indices = dcb->i2c_table[4];
|
||||
}
|
||||
|
||||
parse_dcb_gpio_table(bios);
|
||||
parse_dcb_connector_table(bios);
|
||||
|
||||
if (entries > DCB_MAX_NUM_ENTRIES)
|
||||
entries = DCB_MAX_NUM_ENTRIES;
|
||||
|
||||
|
@ -5673,7 +5731,7 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
|||
NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n",
|
||||
dcb->entries, connection, config);
|
||||
|
||||
if (!parse_dcb_entry(dev, bdcb, connection, config))
|
||||
if (!parse_dcb_entry(dev, dcb, connection, config))
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5681,18 +5739,22 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
|||
* apart for v2.1+ not being known for requiring merging, this
|
||||
* guarantees dcbent->index is the index of the entry in the rom image
|
||||
*/
|
||||
if (bdcb->version < 0x21)
|
||||
if (dcb->version < 0x21)
|
||||
merge_like_dcb_entries(dev, dcb);
|
||||
|
||||
return dcb->entries ? 0 : -ENXIO;
|
||||
if (!dcb->entries)
|
||||
return -ENXIO;
|
||||
|
||||
parse_dcb_gpio_table(bios);
|
||||
parse_dcb_connector_table(bios);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
fixup_legacy_connector(struct nvbios *bios)
|
||||
{
|
||||
struct bios_parsed_dcb *bdcb = &bios->bdcb;
|
||||
struct parsed_dcb *dcb = &bdcb->dcb;
|
||||
int high = 0, i;
|
||||
struct dcb_table *dcb = &bios->dcb;
|
||||
int i, i2c, i2c_conn[DCB_MAX_NUM_I2C_ENTRIES] = { };
|
||||
|
||||
/*
|
||||
* DCB 3.0 also has the table in most cases, but there are some cards
|
||||
|
@ -5700,9 +5762,11 @@ fixup_legacy_connector(struct nvbios *bios)
|
|||
* indices are all 0. We don't need the connector indices on pre-G80
|
||||
* chips (yet?) so limit the use to DCB 4.0 and above.
|
||||
*/
|
||||
if (bdcb->version >= 0x40)
|
||||
if (dcb->version >= 0x40)
|
||||
return;
|
||||
|
||||
dcb->connector.entries = 0;
|
||||
|
||||
/*
|
||||
* No known connector info before v3.0, so make it up. the rule here
|
||||
* is: anything on the same i2c bus is considered to be on the same
|
||||
|
@ -5710,37 +5774,38 @@ fixup_legacy_connector(struct nvbios *bios)
|
|||
* its own unique connector index.
|
||||
*/
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
if (dcb->entry[i].i2c_index == 0xf)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Ignore the I2C index for on-chip TV-out, as there
|
||||
* are cards with bogus values (nv31m in bug 23212),
|
||||
* and it's otherwise useless.
|
||||
*/
|
||||
if (dcb->entry[i].type == OUTPUT_TV &&
|
||||
dcb->entry[i].location == DCB_LOC_ON_CHIP) {
|
||||
dcb->entry[i].location == DCB_LOC_ON_CHIP)
|
||||
dcb->entry[i].i2c_index = 0xf;
|
||||
i2c = dcb->entry[i].i2c_index;
|
||||
|
||||
if (i2c_conn[i2c]) {
|
||||
dcb->entry[i].connector = i2c_conn[i2c] - 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
dcb->entry[i].connector = dcb->entry[i].i2c_index;
|
||||
if (dcb->entry[i].connector > high)
|
||||
high = dcb->entry[i].connector;
|
||||
dcb->entry[i].connector = dcb->connector.entries++;
|
||||
if (i2c != 0xf)
|
||||
i2c_conn[i2c] = dcb->connector.entries;
|
||||
}
|
||||
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
if (dcb->entry[i].i2c_index != 0xf)
|
||||
continue;
|
||||
|
||||
dcb->entry[i].connector = ++high;
|
||||
/* Fake the connector table as well as just connector indices */
|
||||
for (i = 0; i < dcb->connector.entries; i++) {
|
||||
dcb->connector.entry[i].index = i;
|
||||
dcb->connector.entry[i].type = divine_connector_type(bios, i);
|
||||
dcb->connector.entry[i].gpio_tag = 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
fixup_legacy_i2c(struct nvbios *bios)
|
||||
{
|
||||
struct parsed_dcb *dcb = &bios->bdcb.dcb;
|
||||
struct dcb_table *dcb = &bios->dcb;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
|
@ -5826,7 +5891,7 @@ static int load_nv17_hw_sequencer_ucode(struct drm_device *dev,
|
|||
uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
const uint8_t edid_sig[] = {
|
||||
0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };
|
||||
uint16_t offset = 0;
|
||||
|
@ -5859,7 +5924,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
|
|||
struct dcb_entry *dcbent)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
struct init_exec iexec = { true, false };
|
||||
|
||||
mutex_lock(&bios->lock);
|
||||
|
@ -5872,7 +5937,7 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
|
|||
static bool NVInitVBIOS(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
|
||||
memset(bios, 0, sizeof(struct nvbios));
|
||||
mutex_init(&bios->lock);
|
||||
|
@ -5888,7 +5953,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
|
|||
static int nouveau_parse_vbios_struct(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' };
|
||||
const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 };
|
||||
int offset;
|
||||
|
@ -5915,7 +5980,7 @@ int
|
|||
nouveau_run_vbios_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
int i, ret = 0;
|
||||
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
@ -5946,9 +6011,9 @@ nouveau_run_vbios_init(struct drm_device *dev)
|
|||
}
|
||||
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
for (i = 0; i < bios->bdcb.dcb.entries; i++) {
|
||||
for (i = 0; i < bios->dcb.entries; i++) {
|
||||
nouveau_bios_run_display_table(dev,
|
||||
&bios->bdcb.dcb.entry[i],
|
||||
&bios->dcb.entry[i],
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
@ -5962,11 +6027,11 @@ static void
|
|||
nouveau_bios_i2c_devices_takedown(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
struct dcb_i2c_entry *entry;
|
||||
int i;
|
||||
|
||||
entry = &bios->bdcb.dcb.i2c[0];
|
||||
entry = &bios->dcb.i2c[0];
|
||||
for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++)
|
||||
nouveau_i2c_fini(dev, entry);
|
||||
}
|
||||
|
@ -5975,13 +6040,11 @@ int
|
|||
nouveau_bios_init(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint32_t saved_nv_pextdev_boot_0;
|
||||
bool was_locked;
|
||||
int ret;
|
||||
|
||||
dev_priv->vbios = &bios->pub;
|
||||
|
||||
if (!NVInitVBIOS(dev))
|
||||
return -ENODEV;
|
||||
|
||||
|
@ -6023,10 +6086,8 @@ nouveau_bios_init(struct drm_device *dev)
|
|||
bios_wr32(bios, NV_PEXTDEV_BOOT_0, saved_nv_pextdev_boot_0);
|
||||
|
||||
ret = nouveau_run_vbios_init(dev);
|
||||
if (ret) {
|
||||
dev_priv->vbios = NULL;
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* feature_byte on BMP is poor, but init always sets CR4B */
|
||||
was_locked = NVLockVgaCrtcs(dev, false);
|
||||
|
|
|
@ -34,9 +34,67 @@
|
|||
|
||||
#define DCB_LOC_ON_CHIP 0
|
||||
|
||||
struct dcb_i2c_entry {
|
||||
uint8_t port_type;
|
||||
uint8_t read, write;
|
||||
struct nouveau_i2c_chan *chan;
|
||||
};
|
||||
|
||||
enum dcb_gpio_tag {
|
||||
DCB_GPIO_TVDAC0 = 0xc,
|
||||
DCB_GPIO_TVDAC1 = 0x2d,
|
||||
};
|
||||
|
||||
struct dcb_gpio_entry {
|
||||
enum dcb_gpio_tag tag;
|
||||
int line;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
struct dcb_gpio_table {
|
||||
int entries;
|
||||
struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES];
|
||||
};
|
||||
|
||||
enum dcb_connector_type {
|
||||
DCB_CONNECTOR_VGA = 0x00,
|
||||
DCB_CONNECTOR_TV_0 = 0x10,
|
||||
DCB_CONNECTOR_TV_1 = 0x11,
|
||||
DCB_CONNECTOR_TV_3 = 0x13,
|
||||
DCB_CONNECTOR_DVI_I = 0x30,
|
||||
DCB_CONNECTOR_DVI_D = 0x31,
|
||||
DCB_CONNECTOR_LVDS = 0x40,
|
||||
DCB_CONNECTOR_DP = 0x46,
|
||||
DCB_CONNECTOR_eDP = 0x47,
|
||||
DCB_CONNECTOR_HDMI_0 = 0x60,
|
||||
DCB_CONNECTOR_HDMI_1 = 0x61,
|
||||
DCB_CONNECTOR_NONE = 0xff
|
||||
};
|
||||
|
||||
struct dcb_connector_table_entry {
|
||||
uint32_t entry;
|
||||
enum dcb_connector_type type;
|
||||
uint8_t index;
|
||||
uint8_t gpio_tag;
|
||||
};
|
||||
|
||||
struct dcb_connector_table {
|
||||
int entries;
|
||||
struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES];
|
||||
};
|
||||
|
||||
enum dcb_type {
|
||||
OUTPUT_ANALOG = 0,
|
||||
OUTPUT_TV = 1,
|
||||
OUTPUT_TMDS = 2,
|
||||
OUTPUT_LVDS = 3,
|
||||
OUTPUT_DP = 6,
|
||||
OUTPUT_ANY = -1
|
||||
};
|
||||
|
||||
struct dcb_entry {
|
||||
int index; /* may not be raw dcb index if merging has happened */
|
||||
uint8_t type;
|
||||
enum dcb_type type;
|
||||
uint8_t i2c_index;
|
||||
uint8_t heads;
|
||||
uint8_t connector;
|
||||
|
@ -71,69 +129,22 @@ struct dcb_entry {
|
|||
bool i2c_upper_default;
|
||||
};
|
||||
|
||||
struct dcb_i2c_entry {
|
||||
uint8_t port_type;
|
||||
uint8_t read, write;
|
||||
struct nouveau_i2c_chan *chan;
|
||||
};
|
||||
|
||||
struct parsed_dcb {
|
||||
int entries;
|
||||
struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
|
||||
struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
|
||||
};
|
||||
|
||||
enum dcb_gpio_tag {
|
||||
DCB_GPIO_TVDAC0 = 0xc,
|
||||
DCB_GPIO_TVDAC1 = 0x2d,
|
||||
};
|
||||
|
||||
struct dcb_gpio_entry {
|
||||
enum dcb_gpio_tag tag;
|
||||
int line;
|
||||
bool invert;
|
||||
};
|
||||
|
||||
struct parsed_dcb_gpio {
|
||||
int entries;
|
||||
struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES];
|
||||
};
|
||||
|
||||
struct dcb_connector_table_entry {
|
||||
uint32_t entry;
|
||||
uint8_t type;
|
||||
uint8_t index;
|
||||
uint8_t gpio_tag;
|
||||
};
|
||||
|
||||
struct dcb_connector_table {
|
||||
int entries;
|
||||
struct dcb_connector_table_entry entry[DCB_MAX_NUM_CONNECTOR_ENTRIES];
|
||||
};
|
||||
|
||||
struct bios_parsed_dcb {
|
||||
struct dcb_table {
|
||||
uint8_t version;
|
||||
|
||||
struct parsed_dcb dcb;
|
||||
int entries;
|
||||
struct dcb_entry entry[DCB_MAX_NUM_ENTRIES];
|
||||
|
||||
uint8_t *i2c_table;
|
||||
uint8_t i2c_default_indices;
|
||||
struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES];
|
||||
|
||||
uint16_t gpio_table_ptr;
|
||||
struct parsed_dcb_gpio gpio;
|
||||
struct dcb_gpio_table gpio;
|
||||
uint16_t connector_table_ptr;
|
||||
struct dcb_connector_table connector;
|
||||
};
|
||||
|
||||
enum nouveau_encoder_type {
|
||||
OUTPUT_ANALOG = 0,
|
||||
OUTPUT_TV = 1,
|
||||
OUTPUT_TMDS = 2,
|
||||
OUTPUT_LVDS = 3,
|
||||
OUTPUT_DP = 6,
|
||||
OUTPUT_ANY = -1
|
||||
};
|
||||
|
||||
enum nouveau_or {
|
||||
OUTPUT_A = (1 << 0),
|
||||
OUTPUT_B = (1 << 1),
|
||||
|
@ -190,8 +201,8 @@ struct pll_lims {
|
|||
int refclk;
|
||||
};
|
||||
|
||||
struct nouveau_bios_info {
|
||||
struct parsed_dcb *dcb;
|
||||
struct nvbios {
|
||||
struct drm_device *dev;
|
||||
|
||||
uint8_t chip_version;
|
||||
|
||||
|
@ -199,11 +210,6 @@ struct nouveau_bios_info {
|
|||
uint32_t tvdactestval;
|
||||
uint8_t digital_min_front_porch;
|
||||
bool fp_no_ddc;
|
||||
};
|
||||
|
||||
struct nvbios {
|
||||
struct drm_device *dev;
|
||||
struct nouveau_bios_info pub;
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
|
@ -234,7 +240,7 @@ struct nvbios {
|
|||
uint16_t some_script_ptr; /* BIT I + 14 */
|
||||
uint16_t init96_tbl_ptr; /* BIT I + 16 */
|
||||
|
||||
struct bios_parsed_dcb bdcb;
|
||||
struct dcb_table dcb;
|
||||
|
||||
struct {
|
||||
int crtchead;
|
||||
|
|
|
@ -274,7 +274,7 @@ getMNP_single(struct drm_device *dev, struct pll_lims *pll_lim, int clk,
|
|||
* returns calculated clock
|
||||
*/
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int cv = dev_priv->vbios->chip_version;
|
||||
int cv = dev_priv->vbios.chip_version;
|
||||
int minvco = pll_lim->vco1.minfreq, maxvco = pll_lim->vco1.maxfreq;
|
||||
int minM = pll_lim->vco1.min_m, maxM = pll_lim->vco1.max_m;
|
||||
int minN = pll_lim->vco1.min_n, maxN = pll_lim->vco1.max_n;
|
||||
|
@ -373,7 +373,7 @@ getMNP_double(struct drm_device *dev, struct pll_lims *pll_lim, int clk,
|
|||
* returns calculated clock
|
||||
*/
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int chip_version = dev_priv->vbios->chip_version;
|
||||
int chip_version = dev_priv->vbios.chip_version;
|
||||
int minvco1 = pll_lim->vco1.minfreq, maxvco1 = pll_lim->vco1.maxfreq;
|
||||
int minvco2 = pll_lim->vco2.minfreq, maxvco2 = pll_lim->vco2.maxfreq;
|
||||
int minU1 = pll_lim->vco1.min_inputfreq, minU2 = pll_lim->vco2.min_inputfreq;
|
||||
|
|
|
@ -35,22 +35,27 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_bo *pb = chan->pushbuf_bo;
|
||||
struct nouveau_gpuobj *pushbuf = NULL;
|
||||
uint32_t start = pb->bo.mem.mm_node->start << PAGE_SHIFT;
|
||||
int ret;
|
||||
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
|
||||
dev_priv->vm_end, NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_AGP, &pushbuf);
|
||||
chan->pushbuf_base = pb->bo.offset;
|
||||
} else
|
||||
if (pb->bo.mem.mem_type == TTM_PL_TT) {
|
||||
ret = nouveau_gpuobj_gart_dma_new(chan, 0,
|
||||
dev_priv->gart_info.aper_size,
|
||||
NV_DMA_ACCESS_RO, &pushbuf,
|
||||
NULL);
|
||||
chan->pushbuf_base = start;
|
||||
chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT;
|
||||
} else
|
||||
if (dev_priv->card_type != NV_04) {
|
||||
ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, 0,
|
||||
dev_priv->fb_available_size,
|
||||
NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_VIDMEM, &pushbuf);
|
||||
chan->pushbuf_base = start;
|
||||
chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT;
|
||||
} else {
|
||||
/* NV04 cmdbuf hack, from original ddx.. not sure of it's
|
||||
* exact reason for existing :) PCI access to cmdbuf in
|
||||
|
@ -61,7 +66,7 @@ nouveau_channel_pushbuf_ctxdma_init(struct nouveau_channel *chan)
|
|||
dev_priv->fb_available_size,
|
||||
NV_DMA_ACCESS_RO,
|
||||
NV_DMA_TARGET_PCI, &pushbuf);
|
||||
chan->pushbuf_base = start;
|
||||
chan->pushbuf_base = pb->bo.mem.mm_node->start << PAGE_SHIFT;
|
||||
}
|
||||
|
||||
ret = nouveau_gpuobj_ref_add(dev, chan, 0, pushbuf, &chan->pushbuf);
|
||||
|
@ -275,9 +280,18 @@ nouveau_channel_free(struct nouveau_channel *chan)
|
|||
*/
|
||||
nouveau_fence_fini(chan);
|
||||
|
||||
/* Ensure the channel is no longer active on the GPU */
|
||||
/* This will prevent pfifo from switching channels. */
|
||||
pfifo->reassign(dev, false);
|
||||
|
||||
/* We want to give pgraph a chance to idle and get rid of all potential
|
||||
* errors. We need to do this before the lock, otherwise the irq handler
|
||||
* is unable to process them.
|
||||
*/
|
||||
if (pgraph->channel(dev) == chan)
|
||||
nouveau_wait_for_idle(dev);
|
||||
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
pgraph->fifo_access(dev, false);
|
||||
if (pgraph->channel(dev) == chan)
|
||||
pgraph->unload_context(dev);
|
||||
|
@ -293,6 +307,8 @@ nouveau_channel_free(struct nouveau_channel *chan)
|
|||
|
||||
pfifo->reassign(dev, true);
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
/* Release the channel's resources */
|
||||
nouveau_gpuobj_ref_del(dev, &chan->pushbuf);
|
||||
if (chan->pushbuf_bo) {
|
||||
|
@ -369,6 +385,14 @@ nouveau_ioctl_fifo_alloc(struct drm_device *dev, void *data,
|
|||
return ret;
|
||||
init->channel = chan->id;
|
||||
|
||||
if (chan->dma.ib_max)
|
||||
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM |
|
||||
NOUVEAU_GEM_DOMAIN_GART;
|
||||
else if (chan->pushbuf_bo->bo.mem.mem_type == TTM_PL_VRAM)
|
||||
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM;
|
||||
else
|
||||
init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_GART;
|
||||
|
||||
init->subchan[0].handle = NvM2MF;
|
||||
if (dev_priv->card_type < NV_50)
|
||||
init->subchan[0].grclass = 0x0039;
|
||||
|
@ -408,7 +432,6 @@ nouveau_ioctl_fifo_free(struct drm_device *dev, void *data,
|
|||
***********************************/
|
||||
|
||||
struct drm_ioctl_desc nouveau_ioctls[] = {
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_CARD_INIT, nouveau_ioctl_card_init, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GETPARAM, nouveau_ioctl_getparam, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_SETPARAM, nouveau_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_CHANNEL_ALLOC, nouveau_ioctl_fifo_alloc, DRM_AUTH),
|
||||
|
@ -418,13 +441,9 @@ struct drm_ioctl_desc nouveau_ioctls[] = {
|
|||
DRM_IOCTL_DEF(DRM_NOUVEAU_GPUOBJ_FREE, nouveau_ioctl_gpuobj_free, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL, nouveau_gem_ioctl_pushbuf_call, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PIN, nouveau_gem_ioctl_pin, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_UNPIN, nouveau_gem_ioctl_unpin, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH),
|
||||
DRM_IOCTL_DEF(DRM_NOUVEAU_GEM_PUSHBUF_CALL2, nouveau_gem_ioctl_pushbuf_call2, DRM_AUTH),
|
||||
};
|
||||
|
||||
int nouveau_max_ioctl = DRM_ARRAY_SIZE(nouveau_ioctls);
|
||||
|
|
|
@ -218,7 +218,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
|
|||
connector->interlace_allowed = true;
|
||||
}
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
|
||||
drm_connector_property_set_value(connector,
|
||||
dev->mode_config.dvi_i_subconnector_property,
|
||||
nv_encoder->dcb->type == OUTPUT_TMDS ?
|
||||
|
@ -236,15 +236,17 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
struct nouveau_i2c_chan *i2c;
|
||||
int type, flags;
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS)
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
|
||||
if (nv_encoder && nv_connector->native_mode) {
|
||||
unsigned status = connector_status_connected;
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
if (!nouveau_ignorelid && !acpi_lid_open())
|
||||
return connector_status_disconnected;
|
||||
status = connector_status_unknown;
|
||||
#endif
|
||||
nouveau_connector_set_encoder(connector, nv_encoder);
|
||||
return connector_status_connected;
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Cleanup the previous EDID block. */
|
||||
|
@ -279,7 +281,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
* same i2c channel so the value returned from ddc_detect
|
||||
* isn't necessarily correct.
|
||||
*/
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
|
||||
if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
|
||||
type = OUTPUT_TMDS;
|
||||
else
|
||||
|
@ -321,11 +323,11 @@ detect_analog:
|
|||
static void
|
||||
nouveau_connector_force(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct nouveau_connector *nv_connector = nouveau_connector(connector);
|
||||
struct nouveau_encoder *nv_encoder;
|
||||
int type;
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_DVII) {
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) {
|
||||
if (connector->force == DRM_FORCE_ON_DIGITAL)
|
||||
type = OUTPUT_TMDS;
|
||||
else
|
||||
|
@ -335,7 +337,7 @@ nouveau_connector_force(struct drm_connector *connector)
|
|||
|
||||
nv_encoder = find_encoder_by_type(connector, type);
|
||||
if (!nv_encoder) {
|
||||
NV_ERROR(dev, "can't find encoder to force %s on!\n",
|
||||
NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
|
||||
drm_get_connector_name(connector));
|
||||
connector->status = connector_status_disconnected;
|
||||
return;
|
||||
|
@ -369,7 +371,7 @@ nouveau_connector_set_property(struct drm_connector *connector,
|
|||
}
|
||||
|
||||
/* LVDS always needs gpu scaling */
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS &&
|
||||
if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS &&
|
||||
value == DRM_MODE_SCALE_NONE)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -535,7 +537,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
|||
/* If we're not LVDS, destroy the previous native mode, the attached
|
||||
* monitor could have changed.
|
||||
*/
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
|
||||
if (nv_connector->dcb->type != DCB_CONNECTOR_LVDS &&
|
||||
nv_connector->native_mode) {
|
||||
drm_mode_destroy(dev, nv_connector->native_mode);
|
||||
nv_connector->native_mode = NULL;
|
||||
|
@ -563,7 +565,7 @@ nouveau_connector_get_modes(struct drm_connector *connector)
|
|||
ret = get_slave_funcs(nv_encoder)->
|
||||
get_modes(to_drm_encoder(nv_encoder), connector);
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
|
||||
if (nv_encoder->dcb->type == OUTPUT_LVDS)
|
||||
ret += nouveau_connector_scaler_modes_add(connector);
|
||||
|
||||
return ret;
|
||||
|
@ -613,6 +615,9 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
|
|||
|
||||
clock *= 3;
|
||||
break;
|
||||
default:
|
||||
BUG_ON(1);
|
||||
return MODE_BAD;
|
||||
}
|
||||
|
||||
if (clock < min_clock)
|
||||
|
@ -680,7 +685,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
|
|||
/* Firstly try getting EDID over DDC, if allowed and I2C channel
|
||||
* is available.
|
||||
*/
|
||||
if (!dev_priv->VBIOS.pub.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
|
||||
if (!dev_priv->vbios.fp_no_ddc && nv_encoder->dcb->i2c_index < 0xf)
|
||||
i2c = nouveau_i2c_find(dev, nv_encoder->dcb->i2c_index);
|
||||
|
||||
if (i2c) {
|
||||
|
@ -695,7 +700,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
|
|||
*/
|
||||
if (!nv_connector->edid && nouveau_bios_fp_mode(dev, &native) &&
|
||||
(nv_encoder->dcb->lvdsconf.use_straps_for_mode ||
|
||||
dev_priv->VBIOS.pub.fp_no_ddc)) {
|
||||
dev_priv->vbios.fp_no_ddc)) {
|
||||
nv_connector->native_mode = drm_mode_duplicate(dev, &native);
|
||||
goto out;
|
||||
}
|
||||
|
@ -704,7 +709,7 @@ nouveau_connector_create_lvds(struct drm_device *dev,
|
|||
* stored for the panel stored in them.
|
||||
*/
|
||||
if (!nv_connector->edid && !nv_connector->native_mode &&
|
||||
!dev_priv->VBIOS.pub.fp_no_ddc) {
|
||||
!dev_priv->vbios.fp_no_ddc) {
|
||||
struct edid *edid =
|
||||
(struct edid *)nouveau_bios_embedded_edid(dev);
|
||||
if (edid) {
|
||||
|
@ -739,46 +744,66 @@ out:
|
|||
}
|
||||
|
||||
int
|
||||
nouveau_connector_create(struct drm_device *dev, int index, int type)
|
||||
nouveau_connector_create(struct drm_device *dev,
|
||||
struct dcb_connector_table_entry *dcb)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_connector *nv_connector = NULL;
|
||||
struct drm_connector *connector;
|
||||
struct drm_encoder *encoder;
|
||||
int ret;
|
||||
int ret, type;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
switch (dcb->type) {
|
||||
case DCB_CONNECTOR_NONE:
|
||||
return 0;
|
||||
case DCB_CONNECTOR_VGA:
|
||||
NV_INFO(dev, "Detected a VGA connector\n");
|
||||
type = DRM_MODE_CONNECTOR_VGA;
|
||||
break;
|
||||
case DCB_CONNECTOR_TV_0:
|
||||
case DCB_CONNECTOR_TV_1:
|
||||
case DCB_CONNECTOR_TV_3:
|
||||
NV_INFO(dev, "Detected a TV connector\n");
|
||||
type = DRM_MODE_CONNECTOR_TV;
|
||||
break;
|
||||
case DCB_CONNECTOR_DVI_I:
|
||||
NV_INFO(dev, "Detected a DVI-I connector\n");
|
||||
type = DRM_MODE_CONNECTOR_DVII;
|
||||
break;
|
||||
case DCB_CONNECTOR_DVI_D:
|
||||
NV_INFO(dev, "Detected a DVI-D connector\n");
|
||||
type = DRM_MODE_CONNECTOR_DVID;
|
||||
break;
|
||||
case DCB_CONNECTOR_HDMI_0:
|
||||
case DCB_CONNECTOR_HDMI_1:
|
||||
NV_INFO(dev, "Detected a HDMI connector\n");
|
||||
type = DRM_MODE_CONNECTOR_HDMIA;
|
||||
break;
|
||||
case DCB_CONNECTOR_LVDS:
|
||||
NV_INFO(dev, "Detected a LVDS connector\n");
|
||||
type = DRM_MODE_CONNECTOR_LVDS;
|
||||
break;
|
||||
case DCB_CONNECTOR_DP:
|
||||
NV_INFO(dev, "Detected a DisplayPort connector\n");
|
||||
type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
break;
|
||||
case DCB_CONNECTOR_eDP:
|
||||
NV_INFO(dev, "Detected an eDP connector\n");
|
||||
type = DRM_MODE_CONNECTOR_eDP;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL);
|
||||
if (!nv_connector)
|
||||
return -ENOMEM;
|
||||
nv_connector->dcb = nouveau_bios_connector_entry(dev, index);
|
||||
nv_connector->dcb = dcb;
|
||||
connector = &nv_connector->base;
|
||||
|
||||
switch (type) {
|
||||
case DRM_MODE_CONNECTOR_VGA:
|
||||
NV_INFO(dev, "Detected a VGA connector\n");
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVID:
|
||||
NV_INFO(dev, "Detected a DVI-D connector\n");
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DVII:
|
||||
NV_INFO(dev, "Detected a DVI-I connector\n");
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
NV_INFO(dev, "Detected a LVDS connector\n");
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_TV:
|
||||
NV_INFO(dev, "Detected a TV connector\n");
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DisplayPort:
|
||||
NV_INFO(dev, "Detected a DisplayPort connector\n");
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "Unknown connector, this is not good.\n");
|
||||
break;
|
||||
}
|
||||
|
||||
/* defaults, will get overridden in detect() */
|
||||
connector->interlace_allowed = false;
|
||||
connector->doublescan_allowed = false;
|
||||
|
@ -786,44 +811,11 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
|
|||
drm_connector_init(dev, connector, &nouveau_connector_funcs, type);
|
||||
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
|
||||
|
||||
/* Init DVI-I specific properties */
|
||||
if (type == DRM_MODE_CONNECTOR_DVII) {
|
||||
drm_mode_create_dvi_i_properties(dev);
|
||||
drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0);
|
||||
drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
|
||||
}
|
||||
|
||||
if (type != DRM_MODE_CONNECTOR_LVDS)
|
||||
nv_connector->use_dithering = false;
|
||||
|
||||
if (type == DRM_MODE_CONNECTOR_DVID ||
|
||||
type == DRM_MODE_CONNECTOR_DVII ||
|
||||
type == DRM_MODE_CONNECTOR_LVDS ||
|
||||
type == DRM_MODE_CONNECTOR_DisplayPort) {
|
||||
nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
|
||||
|
||||
drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property,
|
||||
nv_connector->scaling_mode);
|
||||
drm_connector_attach_property(connector, dev->mode_config.dithering_mode_property,
|
||||
nv_connector->use_dithering ? DRM_MODE_DITHERING_ON
|
||||
: DRM_MODE_DITHERING_OFF);
|
||||
|
||||
} else {
|
||||
nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
|
||||
|
||||
if (type == DRM_MODE_CONNECTOR_VGA &&
|
||||
dev_priv->card_type >= NV_50) {
|
||||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
nv_connector->scaling_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/* attach encoders */
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
|
||||
|
||||
if (nv_encoder->dcb->connector != index)
|
||||
if (nv_encoder->dcb->connector != dcb->index)
|
||||
continue;
|
||||
|
||||
if (get_slave_funcs(nv_encoder))
|
||||
|
@ -832,9 +824,52 @@ nouveau_connector_create(struct drm_device *dev, int index, int type)
|
|||
drm_mode_connector_attach_encoder(connector, encoder);
|
||||
}
|
||||
|
||||
if (!connector->encoder_ids[0]) {
|
||||
NV_WARN(dev, " no encoders, ignoring\n");
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(connector);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Init DVI-I specific properties */
|
||||
if (dcb->type == DCB_CONNECTOR_DVI_I) {
|
||||
drm_mode_create_dvi_i_properties(dev);
|
||||
drm_connector_attach_property(connector, dev->mode_config.dvi_i_subconnector_property, 0);
|
||||
drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0);
|
||||
}
|
||||
|
||||
if (dcb->type != DCB_CONNECTOR_LVDS)
|
||||
nv_connector->use_dithering = false;
|
||||
|
||||
switch (dcb->type) {
|
||||
case DCB_CONNECTOR_VGA:
|
||||
if (dev_priv->card_type >= NV_50) {
|
||||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
nv_connector->scaling_mode);
|
||||
}
|
||||
/* fall-through */
|
||||
case DCB_CONNECTOR_TV_0:
|
||||
case DCB_CONNECTOR_TV_1:
|
||||
case DCB_CONNECTOR_TV_3:
|
||||
nv_connector->scaling_mode = DRM_MODE_SCALE_NONE;
|
||||
break;
|
||||
default:
|
||||
nv_connector->scaling_mode = DRM_MODE_SCALE_FULLSCREEN;
|
||||
|
||||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.scaling_mode_property,
|
||||
nv_connector->scaling_mode);
|
||||
drm_connector_attach_property(connector,
|
||||
dev->mode_config.dithering_mode_property,
|
||||
nv_connector->use_dithering ?
|
||||
DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF);
|
||||
break;
|
||||
}
|
||||
|
||||
drm_sysfs_connector_add(connector);
|
||||
|
||||
if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
|
||||
if (dcb->type == DCB_CONNECTOR_LVDS) {
|
||||
ret = nouveau_connector_create_lvds(dev, connector);
|
||||
if (ret) {
|
||||
connector->funcs->destroy(connector);
|
||||
|
|
|
@ -49,6 +49,7 @@ static inline struct nouveau_connector *nouveau_connector(
|
|||
return container_of(con, struct nouveau_connector, base);
|
||||
}
|
||||
|
||||
int nouveau_connector_create(struct drm_device *dev, int i2c_index, int type);
|
||||
int nouveau_connector_create(struct drm_device *,
|
||||
struct dcb_connector_table_entry *);
|
||||
|
||||
#endif /* __NOUVEAU_CONNECTOR_H__ */
|
||||
|
|
|
@ -47,12 +47,23 @@ nouveau_debugfs_channel_info(struct seq_file *m, void *data)
|
|||
seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2);
|
||||
seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2);
|
||||
seq_printf(m, " free: 0x%08x\n", chan->dma.free << 2);
|
||||
if (chan->dma.ib_max) {
|
||||
seq_printf(m, " ib max: 0x%08x\n", chan->dma.ib_max);
|
||||
seq_printf(m, " ib put: 0x%08x\n", chan->dma.ib_put);
|
||||
seq_printf(m, " ib free: 0x%08x\n", chan->dma.ib_free);
|
||||
}
|
||||
|
||||
seq_printf(m, "gpu fifo state:\n");
|
||||
seq_printf(m, " get: 0x%08x\n",
|
||||
nvchan_rd32(chan, chan->user_get));
|
||||
seq_printf(m, " put: 0x%08x\n",
|
||||
nvchan_rd32(chan, chan->user_put));
|
||||
if (chan->dma.ib_max) {
|
||||
seq_printf(m, " ib get: 0x%08x\n",
|
||||
nvchan_rd32(chan, 0x88));
|
||||
seq_printf(m, " ib put: 0x%08x\n",
|
||||
nvchan_rd32(chan, 0x8c));
|
||||
}
|
||||
|
||||
seq_printf(m, "last fence : %d\n", chan->fence.sequence);
|
||||
seq_printf(m, "last signalled: %d\n", chan->fence.sequence_ack);
|
||||
|
@ -133,9 +144,22 @@ nouveau_debugfs_memory_info(struct seq_file *m, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nouveau_debugfs_vbios_image(struct seq_file *m, void *data)
|
||||
{
|
||||
struct drm_info_node *node = (struct drm_info_node *) m->private;
|
||||
struct drm_nouveau_private *dev_priv = node->minor->dev->dev_private;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev_priv->vbios.length; i++)
|
||||
seq_printf(m, "%c", dev_priv->vbios.data[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_info_list nouveau_debugfs_list[] = {
|
||||
{ "chipset", nouveau_debugfs_chipset_info, 0, NULL },
|
||||
{ "memory", nouveau_debugfs_memory_info, 0, NULL },
|
||||
{ "vbios.rom", nouveau_debugfs_vbios_image, 0, NULL },
|
||||
};
|
||||
#define NOUVEAU_DEBUGFS_ENTRIES ARRAY_SIZE(nouveau_debugfs_list)
|
||||
|
||||
|
|
|
@ -32,7 +32,22 @@
|
|||
void
|
||||
nouveau_dma_pre_init(struct nouveau_channel *chan)
|
||||
{
|
||||
chan->dma.max = (chan->pushbuf_bo->bo.mem.size >> 2) - 2;
|
||||
struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
|
||||
struct nouveau_bo *pushbuf = chan->pushbuf_bo;
|
||||
|
||||
if (dev_priv->card_type == NV_50) {
|
||||
const int ib_size = pushbuf->bo.mem.size / 2;
|
||||
|
||||
chan->dma.ib_base = (pushbuf->bo.mem.size - ib_size) >> 2;
|
||||
chan->dma.ib_max = (ib_size / 8) - 1;
|
||||
chan->dma.ib_put = 0;
|
||||
chan->dma.ib_free = chan->dma.ib_max - chan->dma.ib_put;
|
||||
|
||||
chan->dma.max = (pushbuf->bo.mem.size - ib_size) >> 2;
|
||||
} else {
|
||||
chan->dma.max = (pushbuf->bo.mem.size >> 2) - 2;
|
||||
}
|
||||
|
||||
chan->dma.put = 0;
|
||||
chan->dma.cur = chan->dma.put;
|
||||
chan->dma.free = chan->dma.max - chan->dma.cur;
|
||||
|
@ -162,12 +177,101 @@ READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout)
|
|||
return (val - chan->pushbuf_base) >> 2;
|
||||
}
|
||||
|
||||
void
|
||||
nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo,
|
||||
int delta, int length)
|
||||
{
|
||||
struct nouveau_bo *pb = chan->pushbuf_bo;
|
||||
uint64_t offset = bo->bo.offset + delta;
|
||||
int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base;
|
||||
|
||||
BUG_ON(chan->dma.ib_free < 1);
|
||||
nouveau_bo_wr32(pb, ip++, lower_32_bits(offset));
|
||||
nouveau_bo_wr32(pb, ip++, upper_32_bits(offset) | length << 8);
|
||||
|
||||
chan->dma.ib_put = (chan->dma.ib_put + 1) & chan->dma.ib_max;
|
||||
nvchan_wr32(chan, 0x8c, chan->dma.ib_put);
|
||||
chan->dma.ib_free--;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_dma_push_wait(struct nouveau_channel *chan, int count)
|
||||
{
|
||||
uint32_t cnt = 0, prev_get = 0;
|
||||
|
||||
while (chan->dma.ib_free < count) {
|
||||
uint32_t get = nvchan_rd32(chan, 0x88);
|
||||
if (get != prev_get) {
|
||||
prev_get = get;
|
||||
cnt = 0;
|
||||
}
|
||||
|
||||
if ((++cnt & 0xff) == 0) {
|
||||
DRM_UDELAY(1);
|
||||
if (cnt > 100000)
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
chan->dma.ib_free = get - chan->dma.ib_put;
|
||||
if (chan->dma.ib_free <= 0)
|
||||
chan->dma.ib_free += chan->dma.ib_max + 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nv50_dma_wait(struct nouveau_channel *chan, int slots, int count)
|
||||
{
|
||||
uint32_t cnt = 0, prev_get = 0;
|
||||
int ret;
|
||||
|
||||
ret = nv50_dma_push_wait(chan, slots + 1);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
while (chan->dma.free < count) {
|
||||
int get = READ_GET(chan, &prev_get, &cnt);
|
||||
if (unlikely(get < 0)) {
|
||||
if (get == -EINVAL)
|
||||
continue;
|
||||
|
||||
return get;
|
||||
}
|
||||
|
||||
if (get <= chan->dma.cur) {
|
||||
chan->dma.free = chan->dma.max - chan->dma.cur;
|
||||
if (chan->dma.free >= count)
|
||||
break;
|
||||
|
||||
FIRE_RING(chan);
|
||||
do {
|
||||
get = READ_GET(chan, &prev_get, &cnt);
|
||||
if (unlikely(get < 0)) {
|
||||
if (get == -EINVAL)
|
||||
continue;
|
||||
return get;
|
||||
}
|
||||
} while (get == 0);
|
||||
chan->dma.cur = 0;
|
||||
chan->dma.put = 0;
|
||||
}
|
||||
|
||||
chan->dma.free = get - chan->dma.cur - 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_dma_wait(struct nouveau_channel *chan, int size)
|
||||
nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size)
|
||||
{
|
||||
uint32_t prev_get = 0, cnt = 0;
|
||||
int get;
|
||||
|
||||
if (chan->dma.ib_max)
|
||||
return nv50_dma_wait(chan, slots, size);
|
||||
|
||||
while (chan->dma.free < size) {
|
||||
get = READ_GET(chan, &prev_get, &cnt);
|
||||
if (unlikely(get == -EBUSY))
|
||||
|
|
|
@ -31,6 +31,9 @@
|
|||
#define NOUVEAU_DMA_DEBUG 0
|
||||
#endif
|
||||
|
||||
void nv50_dma_push(struct nouveau_channel *, struct nouveau_bo *,
|
||||
int delta, int length);
|
||||
|
||||
/*
|
||||
* There's a hw race condition where you can't jump to your PUT offset,
|
||||
* to avoid this we jump to offset + SKIPS and fill the difference with
|
||||
|
@ -96,13 +99,11 @@ enum {
|
|||
static __must_check inline int
|
||||
RING_SPACE(struct nouveau_channel *chan, int size)
|
||||
{
|
||||
if (chan->dma.free < size) {
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_dma_wait(chan, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
ret = nouveau_dma_wait(chan, 1, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
chan->dma.free -= size;
|
||||
return 0;
|
||||
|
@ -146,7 +147,13 @@ FIRE_RING(struct nouveau_channel *chan)
|
|||
return;
|
||||
chan->accel_done = true;
|
||||
|
||||
WRITE_PUT(chan->dma.cur);
|
||||
if (chan->dma.ib_max) {
|
||||
nv50_dma_push(chan, chan->pushbuf_bo, chan->dma.put << 2,
|
||||
(chan->dma.cur - chan->dma.put) << 2);
|
||||
} else {
|
||||
WRITE_PUT(chan->dma.cur);
|
||||
}
|
||||
|
||||
chan->dma.put = chan->dma.cur;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,11 +75,11 @@ MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
|
|||
int nouveau_ignorelid = 0;
|
||||
module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(noagp, "Disable all acceleration");
|
||||
MODULE_PARM_DESC(noaccel, "Disable all acceleration");
|
||||
int nouveau_noaccel = 0;
|
||||
module_param_named(noaccel, nouveau_noaccel, int, 0400);
|
||||
|
||||
MODULE_PARM_DESC(noagp, "Disable fbcon acceleration");
|
||||
MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration");
|
||||
int nouveau_nofbaccel = 0;
|
||||
module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
#define DRIVER_MAJOR 0
|
||||
#define DRIVER_MINOR 0
|
||||
#define DRIVER_PATCHLEVEL 15
|
||||
#define DRIVER_PATCHLEVEL 16
|
||||
|
||||
#define NOUVEAU_FAMILY 0x0000FFFF
|
||||
#define NOUVEAU_FLAGS 0xFFFF0000
|
||||
|
@ -83,6 +83,7 @@ struct nouveau_bo {
|
|||
struct drm_file *reserved_by;
|
||||
struct list_head entry;
|
||||
int pbbo_index;
|
||||
bool validate_mapped;
|
||||
|
||||
struct nouveau_channel *channel;
|
||||
|
||||
|
@ -239,6 +240,11 @@ struct nouveau_channel {
|
|||
int cur;
|
||||
int put;
|
||||
/* access via pushbuf_bo */
|
||||
|
||||
int ib_base;
|
||||
int ib_max;
|
||||
int ib_free;
|
||||
int ib_put;
|
||||
} dma;
|
||||
|
||||
uint32_t sw_subchannel[8];
|
||||
|
@ -533,6 +539,9 @@ struct drm_nouveau_private {
|
|||
struct nouveau_engine engine;
|
||||
struct nouveau_channel *channel;
|
||||
|
||||
/* For PFIFO and PGRAPH. */
|
||||
spinlock_t context_switch_lock;
|
||||
|
||||
/* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
|
||||
struct nouveau_gpuobj *ramht;
|
||||
uint32_t ramin_rsvd_vram;
|
||||
|
@ -596,8 +605,7 @@ struct drm_nouveau_private {
|
|||
|
||||
struct list_head gpuobj_list;
|
||||
|
||||
struct nvbios VBIOS;
|
||||
struct nouveau_bios_info *vbios;
|
||||
struct nvbios vbios;
|
||||
|
||||
struct nv04_mode_state mode_reg;
|
||||
struct nv04_mode_state saved_reg;
|
||||
|
@ -696,12 +704,6 @@ extern bool nouveau_wait_until(struct drm_device *, uint64_t timeout,
|
|||
uint32_t reg, uint32_t mask, uint32_t val);
|
||||
extern bool nouveau_wait_for_idle(struct drm_device *);
|
||||
extern int nouveau_card_init(struct drm_device *);
|
||||
extern int nouveau_ioctl_card_init(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern int nouveau_ioctl_suspend(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
extern int nouveau_ioctl_resume(struct drm_device *, void *data,
|
||||
struct drm_file *);
|
||||
|
||||
/* nouveau_mem.c */
|
||||
extern int nouveau_mem_init_heap(struct mem_block **, uint64_t start,
|
||||
|
@ -845,7 +847,7 @@ nouveau_debugfs_channel_fini(struct nouveau_channel *chan)
|
|||
/* nouveau_dma.c */
|
||||
extern void nouveau_dma_pre_init(struct nouveau_channel *);
|
||||
extern int nouveau_dma_init(struct nouveau_channel *);
|
||||
extern int nouveau_dma_wait(struct nouveau_channel *, int size);
|
||||
extern int nouveau_dma_wait(struct nouveau_channel *, int slots, int size);
|
||||
|
||||
/* nouveau_acpi.c */
|
||||
#ifdef CONFIG_ACPI
|
||||
|
@ -1027,6 +1029,7 @@ extern void nv50_graph_destroy_context(struct nouveau_channel *);
|
|||
extern int nv50_graph_load_context(struct nouveau_channel *);
|
||||
extern int nv50_graph_unload_context(struct drm_device *);
|
||||
extern void nv50_graph_context_switch(struct drm_device *);
|
||||
extern int nv50_grctx_init(struct nouveau_grctx *);
|
||||
|
||||
/* nouveau_grctx.c */
|
||||
extern int nouveau_grctx_prog_load(struct drm_device *);
|
||||
|
@ -1152,16 +1155,6 @@ extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
|
|||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_pushbuf(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_pushbuf_call(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_pushbuf_call2(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_pin(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_unpin(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_tile(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_cpu_prep(struct drm_device *, void *,
|
||||
struct drm_file *);
|
||||
extern int nouveau_gem_ioctl_cpu_fini(struct drm_device *, void *,
|
||||
|
|
|
@ -241,6 +241,11 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence)
|
|||
nouveau_fence_unref((void *)&prev_fence);
|
||||
}
|
||||
|
||||
if (unlikely(nvbo->validate_mapped)) {
|
||||
ttm_bo_kunmap(&nvbo->kmap);
|
||||
nvbo->validate_mapped = false;
|
||||
}
|
||||
|
||||
list_del(&nvbo->entry);
|
||||
nvbo->reserved_by = NULL;
|
||||
ttm_bo_unreserve(&nvbo->bo);
|
||||
|
@ -300,11 +305,14 @@ retry:
|
|||
if (ret == -EAGAIN)
|
||||
ret = ttm_bo_wait_unreserved(&nvbo->bo, false);
|
||||
drm_gem_object_unreference(gem);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "fail reserve\n");
|
||||
return ret;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
|
||||
b->user_priv = (uint64_t)(unsigned long)nvbo;
|
||||
nvbo->reserved_by = file_priv;
|
||||
nvbo->pbbo_index = i;
|
||||
if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
|
||||
|
@ -334,8 +342,10 @@ retry:
|
|||
}
|
||||
|
||||
ret = ttm_bo_wait_cpu(&nvbo->bo, false);
|
||||
if (ret)
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "fail wait_cpu\n");
|
||||
return ret;
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
@ -349,6 +359,7 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
{
|
||||
struct drm_nouveau_gem_pushbuf_bo __user *upbbo =
|
||||
(void __force __user *)(uintptr_t)user_pbbo_ptr;
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_bo *nvbo;
|
||||
int ret, relocs = 0;
|
||||
|
||||
|
@ -360,39 +371,46 @@ validate_list(struct nouveau_channel *chan, struct list_head *list,
|
|||
spin_lock(&nvbo->bo.lock);
|
||||
ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
||||
spin_unlock(&nvbo->bo.lock);
|
||||
if (unlikely(ret))
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail wait other chan\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = nouveau_gem_set_domain(nvbo->gem, b->read_domains,
|
||||
b->write_domains,
|
||||
b->valid_domains);
|
||||
if (unlikely(ret))
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail set_domain\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
nvbo->channel = chan;
|
||||
ret = ttm_bo_validate(&nvbo->bo, &nvbo->placement,
|
||||
false, false);
|
||||
nvbo->channel = NULL;
|
||||
if (unlikely(ret))
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "fail ttm_validate\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (nvbo->bo.offset == b->presumed_offset &&
|
||||
if (nvbo->bo.offset == b->presumed.offset &&
|
||||
((nvbo->bo.mem.mem_type == TTM_PL_VRAM &&
|
||||
b->presumed_domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
|
||||
b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) ||
|
||||
(nvbo->bo.mem.mem_type == TTM_PL_TT &&
|
||||
b->presumed_domain & NOUVEAU_GEM_DOMAIN_GART)))
|
||||
b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART)))
|
||||
continue;
|
||||
|
||||
if (nvbo->bo.mem.mem_type == TTM_PL_TT)
|
||||
b->presumed_domain = NOUVEAU_GEM_DOMAIN_GART;
|
||||
b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
|
||||
else
|
||||
b->presumed_domain = NOUVEAU_GEM_DOMAIN_VRAM;
|
||||
b->presumed_offset = nvbo->bo.offset;
|
||||
b->presumed_ok = 0;
|
||||
b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
|
||||
b->presumed.offset = nvbo->bo.offset;
|
||||
b->presumed.valid = 0;
|
||||
relocs++;
|
||||
|
||||
if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index], b, sizeof(*b)))
|
||||
if (DRM_COPY_TO_USER(&upbbo[nvbo->pbbo_index].presumed,
|
||||
&b->presumed, sizeof(b->presumed)))
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -406,6 +424,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
|
|||
uint64_t user_buffers, int nr_buffers,
|
||||
struct validate_op *op, int *apply_relocs)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
int ret, relocs = 0;
|
||||
|
||||
INIT_LIST_HEAD(&op->vram_list);
|
||||
|
@ -416,11 +435,14 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
|
|||
return 0;
|
||||
|
||||
ret = validate_init(chan, file_priv, pbbo, nr_buffers, op);
|
||||
if (unlikely(ret))
|
||||
if (unlikely(ret)) {
|
||||
NV_ERROR(dev, "validate_init\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = validate_list(chan, &op->vram_list, pbbo, user_buffers);
|
||||
if (unlikely(ret < 0)) {
|
||||
NV_ERROR(dev, "validate vram_list\n");
|
||||
validate_fini(op, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
@ -428,6 +450,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
|
|||
|
||||
ret = validate_list(chan, &op->gart_list, pbbo, user_buffers);
|
||||
if (unlikely(ret < 0)) {
|
||||
NV_ERROR(dev, "validate gart_list\n");
|
||||
validate_fini(op, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
@ -435,6 +458,7 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan,
|
|||
|
||||
ret = validate_list(chan, &op->both_list, pbbo, user_buffers);
|
||||
if (unlikely(ret < 0)) {
|
||||
NV_ERROR(dev, "validate both_list\n");
|
||||
validate_fini(op, NULL);
|
||||
return ret;
|
||||
}
|
||||
|
@ -463,59 +487,82 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
|
|||
}
|
||||
|
||||
static int
|
||||
nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo,
|
||||
unsigned nr_relocs, uint64_t ptr_relocs,
|
||||
unsigned nr_dwords, unsigned first_dword,
|
||||
uint32_t *pushbuf, bool is_iomem)
|
||||
nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev,
|
||||
struct drm_nouveau_gem_pushbuf *req,
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo)
|
||||
{
|
||||
struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
|
||||
struct drm_device *dev = chan->dev;
|
||||
int ret = 0;
|
||||
unsigned i;
|
||||
|
||||
reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
|
||||
reloc = u_memcpya(req->relocs, req->nr_relocs, sizeof(*reloc));
|
||||
if (IS_ERR(reloc))
|
||||
return PTR_ERR(reloc);
|
||||
|
||||
for (i = 0; i < nr_relocs; i++) {
|
||||
for (i = 0; i < req->nr_relocs; i++) {
|
||||
struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i];
|
||||
struct drm_nouveau_gem_pushbuf_bo *b;
|
||||
struct nouveau_bo *nvbo;
|
||||
uint32_t data;
|
||||
|
||||
if (r->bo_index >= nr_bo || r->reloc_index < first_dword ||
|
||||
r->reloc_index >= first_dword + nr_dwords) {
|
||||
NV_ERROR(dev, "Bad relocation %d\n", i);
|
||||
NV_ERROR(dev, " bo: %d max %d\n", r->bo_index, nr_bo);
|
||||
NV_ERROR(dev, " id: %d max %d\n", r->reloc_index, nr_dwords);
|
||||
if (unlikely(r->bo_index > req->nr_buffers)) {
|
||||
NV_ERROR(dev, "reloc bo index invalid\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
b = &bo[r->bo_index];
|
||||
if (b->presumed_ok)
|
||||
if (b->presumed.valid)
|
||||
continue;
|
||||
|
||||
if (unlikely(r->reloc_bo_index > req->nr_buffers)) {
|
||||
NV_ERROR(dev, "reloc container bo index invalid\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
nvbo = (void *)(unsigned long)bo[r->reloc_bo_index].user_priv;
|
||||
|
||||
if (unlikely(r->reloc_bo_offset + 4 >
|
||||
nvbo->bo.mem.num_pages << PAGE_SHIFT)) {
|
||||
NV_ERROR(dev, "reloc outside of bo\n");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!nvbo->kmap.virtual) {
|
||||
ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages,
|
||||
&nvbo->kmap);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "failed kmap for reloc\n");
|
||||
break;
|
||||
}
|
||||
nvbo->validate_mapped = true;
|
||||
}
|
||||
|
||||
if (r->flags & NOUVEAU_GEM_RELOC_LOW)
|
||||
data = b->presumed_offset + r->data;
|
||||
data = b->presumed.offset + r->data;
|
||||
else
|
||||
if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
|
||||
data = (b->presumed_offset + r->data) >> 32;
|
||||
data = (b->presumed.offset + r->data) >> 32;
|
||||
else
|
||||
data = r->data;
|
||||
|
||||
if (r->flags & NOUVEAU_GEM_RELOC_OR) {
|
||||
if (b->presumed_domain == NOUVEAU_GEM_DOMAIN_GART)
|
||||
if (b->presumed.domain == NOUVEAU_GEM_DOMAIN_GART)
|
||||
data |= r->tor;
|
||||
else
|
||||
data |= r->vor;
|
||||
}
|
||||
|
||||
if (is_iomem)
|
||||
iowrite32_native(data, (void __force __iomem *)
|
||||
&pushbuf[r->reloc_index]);
|
||||
else
|
||||
pushbuf[r->reloc_index] = data;
|
||||
spin_lock(&nvbo->bo.lock);
|
||||
ret = ttm_bo_wait(&nvbo->bo, false, false, false);
|
||||
spin_unlock(&nvbo->bo.lock);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "reloc wait_idle failed: %d\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data);
|
||||
}
|
||||
|
||||
kfree(reloc);
|
||||
|
@ -526,130 +573,53 @@ int
|
|||
nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_gem_pushbuf *req = data;
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
|
||||
struct drm_nouveau_gem_pushbuf_push *push;
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo;
|
||||
struct nouveau_channel *chan;
|
||||
struct validate_op op;
|
||||
struct nouveau_fence* fence = 0;
|
||||
uint32_t *pushbuf = NULL;
|
||||
int ret = 0, do_reloc = 0, i;
|
||||
struct nouveau_fence *fence = 0;
|
||||
int i, j, ret = 0, do_reloc = 0;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
|
||||
|
||||
if (req->nr_dwords >= chan->dma.max ||
|
||||
req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS ||
|
||||
req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) {
|
||||
NV_ERROR(dev, "Pushbuf config exceeds limits:\n");
|
||||
NV_ERROR(dev, " dwords : %d max %d\n", req->nr_dwords,
|
||||
chan->dma.max - 1);
|
||||
NV_ERROR(dev, " buffers: %d max %d\n", req->nr_buffers,
|
||||
NOUVEAU_GEM_MAX_BUFFERS);
|
||||
NV_ERROR(dev, " relocs : %d max %d\n", req->nr_relocs,
|
||||
NOUVEAU_GEM_MAX_RELOCS);
|
||||
req->vram_available = dev_priv->fb_aper_free;
|
||||
req->gart_available = dev_priv->gart_info.aper_free;
|
||||
if (unlikely(req->nr_push == 0))
|
||||
goto out_next;
|
||||
|
||||
if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) {
|
||||
NV_ERROR(dev, "pushbuf push count exceeds limit: %d max %d\n",
|
||||
req->nr_push, NOUVEAU_GEM_MAX_PUSH);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pushbuf = u_memcpya(req->dwords, req->nr_dwords, sizeof(uint32_t));
|
||||
if (IS_ERR(pushbuf))
|
||||
return PTR_ERR(pushbuf);
|
||||
if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) {
|
||||
NV_ERROR(dev, "pushbuf bo count exceeds limit: %d max %d\n",
|
||||
req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) {
|
||||
NV_ERROR(dev, "pushbuf reloc count exceeds limit: %d max %d\n",
|
||||
req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
push = u_memcpya(req->push, req->nr_push, sizeof(*push));
|
||||
if (IS_ERR(push))
|
||||
return PTR_ERR(push);
|
||||
|
||||
bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
|
||||
if (IS_ERR(bo)) {
|
||||
kfree(pushbuf);
|
||||
kfree(push);
|
||||
return PTR_ERR(bo);
|
||||
}
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/* Validate buffer list */
|
||||
ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
|
||||
req->nr_buffers, &op, &do_reloc);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
/* Apply any relocations that are required */
|
||||
if (do_reloc) {
|
||||
ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers,
|
||||
bo, req->nr_relocs,
|
||||
req->relocs,
|
||||
req->nr_dwords, 0,
|
||||
pushbuf, false);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Emit push buffer to the hw
|
||||
*/
|
||||
ret = RING_SPACE(chan, req->nr_dwords);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
OUT_RINGp(chan, pushbuf, req->nr_dwords);
|
||||
|
||||
ret = nouveau_fence_new(chan, &fence, true);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "error fencing pushbuf: %d\n", ret);
|
||||
WIND_RING(chan);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (nouveau_gem_pushbuf_sync(chan)) {
|
||||
ret = nouveau_fence_wait(fence, NULL, false, false);
|
||||
if (ret) {
|
||||
for (i = 0; i < req->nr_dwords; i++)
|
||||
NV_ERROR(dev, "0x%08x\n", pushbuf[i]);
|
||||
NV_ERROR(dev, "^^ above push buffer is fail :(\n");
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
validate_fini(&op, fence);
|
||||
nouveau_fence_unref((void**)&fence);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
kfree(pushbuf);
|
||||
kfree(bo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define PUSHBUF_CAL (dev_priv->card_type >= NV_20)
|
||||
|
||||
int
|
||||
nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_gem_pushbuf_call *req = data;
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo = NULL;
|
||||
struct nouveau_channel *chan;
|
||||
struct drm_gem_object *gem;
|
||||
struct nouveau_bo *pbbo;
|
||||
struct validate_op op;
|
||||
struct nouveau_fence* fence = 0;
|
||||
int i, ret = 0, do_reloc = 0;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
NOUVEAU_GET_USER_CHANNEL_WITH_RETURN(req->channel, file_priv, chan);
|
||||
|
||||
if (unlikely(req->handle == 0))
|
||||
goto out_next;
|
||||
|
||||
if (req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS ||
|
||||
req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS) {
|
||||
NV_ERROR(dev, "Pushbuf config exceeds limits:\n");
|
||||
NV_ERROR(dev, " buffers: %d max %d\n", req->nr_buffers,
|
||||
NOUVEAU_GEM_MAX_BUFFERS);
|
||||
NV_ERROR(dev, " relocs : %d max %d\n", req->nr_relocs,
|
||||
NOUVEAU_GEM_MAX_RELOCS);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo));
|
||||
if (IS_ERR(bo))
|
||||
return PTR_ERR(bo);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
/* Validate buffer list */
|
||||
ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, req->buffers,
|
||||
req->nr_buffers, &op, &do_reloc);
|
||||
|
@ -658,122 +628,84 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Validate DMA push buffer */
|
||||
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
|
||||
if (!gem) {
|
||||
NV_ERROR(dev, "Unknown pb handle 0x%08x\n", req->handle);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
pbbo = nouveau_gem_object(gem);
|
||||
|
||||
if ((req->offset & 3) || req->nr_dwords < 2 ||
|
||||
(unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
|
||||
(unsigned long)req->nr_dwords >
|
||||
((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
|
||||
NV_ERROR(dev, "pb call misaligned or out of bounds: "
|
||||
"%d + %d * 4 > %ld\n",
|
||||
req->offset, req->nr_dwords, pbbo->bo.mem.size);
|
||||
ret = -EINVAL;
|
||||
drm_gem_object_unreference(gem);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
|
||||
chan->fence.sequence);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "resv pb: %d\n", ret);
|
||||
drm_gem_object_unreference(gem);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nouveau_bo_placement_set(pbbo, 1 << chan->pushbuf_bo->bo.mem.mem_type);
|
||||
ret = ttm_bo_validate(&pbbo->bo, &pbbo->placement, false, false);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "validate pb: %d\n", ret);
|
||||
ttm_bo_unreserve(&pbbo->bo);
|
||||
drm_gem_object_unreference(gem);
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_add_tail(&pbbo->entry, &op.both_list);
|
||||
|
||||
/* If presumed return address doesn't match, we need to map the
|
||||
* push buffer and fix it..
|
||||
*/
|
||||
if (!PUSHBUF_CAL) {
|
||||
uint32_t retaddy;
|
||||
|
||||
if (chan->dma.free < 4 + NOUVEAU_DMA_SKIPS) {
|
||||
ret = nouveau_dma_wait(chan, 4 + NOUVEAU_DMA_SKIPS);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "jmp_space: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
retaddy = chan->pushbuf_base + ((chan->dma.cur + 2) << 2);
|
||||
retaddy |= 0x20000000;
|
||||
if (retaddy != req->suffix0) {
|
||||
req->suffix0 = retaddy;
|
||||
do_reloc = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Apply any relocations that are required */
|
||||
if (do_reloc) {
|
||||
void *pbvirt;
|
||||
bool is_iomem;
|
||||
ret = ttm_bo_kmap(&pbbo->bo, 0, pbbo->bo.mem.num_pages,
|
||||
&pbbo->kmap);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "kmap pb: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
pbvirt = ttm_kmap_obj_virtual(&pbbo->kmap, &is_iomem);
|
||||
ret = nouveau_gem_pushbuf_reloc_apply(chan, req->nr_buffers, bo,
|
||||
req->nr_relocs,
|
||||
req->relocs,
|
||||
req->nr_dwords,
|
||||
req->offset / 4,
|
||||
pbvirt, is_iomem);
|
||||
|
||||
if (!PUSHBUF_CAL) {
|
||||
nouveau_bo_wr32(pbbo,
|
||||
req->offset / 4 + req->nr_dwords - 2,
|
||||
req->suffix0);
|
||||
}
|
||||
|
||||
ttm_bo_kunmap(&pbbo->kmap);
|
||||
ret = nouveau_gem_pushbuf_reloc_apply(dev, req, bo);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "reloc apply: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (PUSHBUF_CAL) {
|
||||
ret = RING_SPACE(chan, 2);
|
||||
if (chan->dma.ib_max) {
|
||||
ret = nouveau_dma_wait(chan, req->nr_push + 1, 6);
|
||||
if (ret) {
|
||||
NV_INFO(dev, "nv50cal_space: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < req->nr_push; i++) {
|
||||
struct nouveau_bo *nvbo = (void *)(unsigned long)
|
||||
bo[push[i].bo_index].user_priv;
|
||||
|
||||
nv50_dma_push(chan, nvbo, push[i].offset,
|
||||
push[i].length);
|
||||
}
|
||||
} else
|
||||
if (dev_priv->card_type >= NV_20) {
|
||||
ret = RING_SPACE(chan, req->nr_push * 2);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "cal_space: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) +
|
||||
req->offset) | 2);
|
||||
OUT_RING(chan, 0);
|
||||
|
||||
for (i = 0; i < req->nr_push; i++) {
|
||||
struct nouveau_bo *nvbo = (void *)(unsigned long)
|
||||
bo[push[i].bo_index].user_priv;
|
||||
struct drm_mm_node *mem = nvbo->bo.mem.mm_node;
|
||||
|
||||
OUT_RING(chan, ((mem->start << PAGE_SHIFT) +
|
||||
push[i].offset) | 2);
|
||||
OUT_RING(chan, 0);
|
||||
}
|
||||
} else {
|
||||
ret = RING_SPACE(chan, 2 + NOUVEAU_DMA_SKIPS);
|
||||
ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS));
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "jmp_space: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
OUT_RING(chan, ((pbbo->bo.mem.mm_node->start << PAGE_SHIFT) +
|
||||
req->offset) | 0x20000000);
|
||||
OUT_RING(chan, 0);
|
||||
|
||||
/* Space the jumps apart with NOPs. */
|
||||
for (i = 0; i < NOUVEAU_DMA_SKIPS; i++)
|
||||
for (i = 0; i < req->nr_push; i++) {
|
||||
struct nouveau_bo *nvbo = (void *)(unsigned long)
|
||||
bo[push[i].bo_index].user_priv;
|
||||
struct drm_mm_node *mem = nvbo->bo.mem.mm_node;
|
||||
uint32_t cmd;
|
||||
|
||||
cmd = chan->pushbuf_base + ((chan->dma.cur + 2) << 2);
|
||||
cmd |= 0x20000000;
|
||||
if (unlikely(cmd != req->suffix0)) {
|
||||
if (!nvbo->kmap.virtual) {
|
||||
ret = ttm_bo_kmap(&nvbo->bo, 0,
|
||||
nvbo->bo.mem.
|
||||
num_pages,
|
||||
&nvbo->kmap);
|
||||
if (ret) {
|
||||
WIND_RING(chan);
|
||||
goto out;
|
||||
}
|
||||
nvbo->validate_mapped = true;
|
||||
}
|
||||
|
||||
nouveau_bo_wr32(nvbo, (push[i].offset +
|
||||
push[i].length - 8) / 4, cmd);
|
||||
}
|
||||
|
||||
OUT_RING(chan, ((mem->start << PAGE_SHIFT) +
|
||||
push[i].offset) | 0x20000000);
|
||||
OUT_RING(chan, 0);
|
||||
for (j = 0; j < NOUVEAU_DMA_SKIPS; j++)
|
||||
OUT_RING(chan, 0);
|
||||
}
|
||||
}
|
||||
|
||||
ret = nouveau_fence_new(chan, &fence, true);
|
||||
|
@ -788,9 +720,14 @@ out:
|
|||
nouveau_fence_unref((void**)&fence);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
kfree(bo);
|
||||
kfree(push);
|
||||
|
||||
out_next:
|
||||
if (PUSHBUF_CAL) {
|
||||
if (chan->dma.ib_max) {
|
||||
req->suffix0 = 0x00000000;
|
||||
req->suffix1 = 0x00000000;
|
||||
} else
|
||||
if (dev_priv->card_type >= NV_20) {
|
||||
req->suffix0 = 0x00020000;
|
||||
req->suffix1 = 0x00000000;
|
||||
} else {
|
||||
|
@ -802,19 +739,6 @@ out_next:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_gem_ioctl_pushbuf_call2(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct drm_nouveau_gem_pushbuf_call *req = data;
|
||||
|
||||
req->vram_available = dev_priv->fb_aper_free;
|
||||
req->gart_available = dev_priv->gart_info.aper_free;
|
||||
|
||||
return nouveau_gem_ioctl_pushbuf_call(dev, data, file_priv);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain)
|
||||
{
|
||||
|
@ -828,70 +752,6 @@ domain_to_ttm(struct nouveau_bo *nvbo, uint32_t domain)
|
|||
return flags;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_gem_ioctl_pin(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_gem_pin *req = data;
|
||||
struct drm_gem_object *gem;
|
||||
struct nouveau_bo *nvbo;
|
||||
int ret = 0;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
NV_ERROR(dev, "pin only allowed without kernel modesetting\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!DRM_SUSER(DRM_CURPROC))
|
||||
return -EPERM;
|
||||
|
||||
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
|
||||
if (!gem)
|
||||
return -EINVAL;
|
||||
nvbo = nouveau_gem_object(gem);
|
||||
|
||||
ret = nouveau_bo_pin(nvbo, domain_to_ttm(nvbo, req->domain));
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
req->offset = nvbo->bo.offset;
|
||||
if (nvbo->bo.mem.mem_type == TTM_PL_TT)
|
||||
req->domain = NOUVEAU_GEM_DOMAIN_GART;
|
||||
else
|
||||
req->domain = NOUVEAU_GEM_DOMAIN_VRAM;
|
||||
|
||||
out:
|
||||
drm_gem_object_unreference_unlocked(gem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_gem_ioctl_unpin(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_nouveau_gem_pin *req = data;
|
||||
struct drm_gem_object *gem;
|
||||
int ret;
|
||||
|
||||
NOUVEAU_CHECK_INITIALISED_WITH_RETURN;
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET))
|
||||
return -EINVAL;
|
||||
|
||||
gem = drm_gem_object_lookup(dev, file_priv, req->handle);
|
||||
if (!gem)
|
||||
return -EINVAL;
|
||||
|
||||
ret = nouveau_bo_unpin(nouveau_gem_object(gem));
|
||||
|
||||
drm_gem_object_unreference_unlocked(gem);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
|
|
|
@ -160,7 +160,7 @@ static void
|
|||
setPLL_single(struct drm_device *dev, uint32_t reg, struct nouveau_pll_vals *pv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int chip_version = dev_priv->vbios->chip_version;
|
||||
int chip_version = dev_priv->vbios.chip_version;
|
||||
uint32_t oldpll = NVReadRAMDAC(dev, 0, reg);
|
||||
int oldN = (oldpll >> 8) & 0xff, oldM = oldpll & 0xff;
|
||||
uint32_t pll = (oldpll & 0xfff80000) | pv->log2P << 16 | pv->NM1;
|
||||
|
@ -216,7 +216,7 @@ setPLL_double_highregs(struct drm_device *dev, uint32_t reg1,
|
|||
struct nouveau_pll_vals *pv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int chip_version = dev_priv->vbios->chip_version;
|
||||
int chip_version = dev_priv->vbios.chip_version;
|
||||
bool nv3035 = chip_version == 0x30 || chip_version == 0x35;
|
||||
uint32_t reg2 = reg1 + ((reg1 == NV_RAMDAC_VPLL2) ? 0x5c : 0x70);
|
||||
uint32_t oldpll1 = NVReadRAMDAC(dev, 0, reg1);
|
||||
|
@ -374,7 +374,7 @@ nouveau_hw_setpll(struct drm_device *dev, uint32_t reg1,
|
|||
struct nouveau_pll_vals *pv)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
int cv = dev_priv->vbios->chip_version;
|
||||
int cv = dev_priv->vbios.chip_version;
|
||||
|
||||
if (cv == 0x30 || cv == 0x31 || cv == 0x35 || cv == 0x36 ||
|
||||
cv >= 0x40) {
|
||||
|
|
|
@ -254,16 +254,16 @@ struct nouveau_i2c_chan *
|
|||
nouveau_i2c_find(struct drm_device *dev, int index)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
|
||||
if (index > DCB_MAX_NUM_I2C_ENTRIES)
|
||||
if (index >= DCB_MAX_NUM_I2C_ENTRIES)
|
||||
return NULL;
|
||||
|
||||
if (!bios->bdcb.dcb.i2c[index].chan) {
|
||||
if (nouveau_i2c_init(dev, &bios->bdcb.dcb.i2c[index], index))
|
||||
if (!bios->dcb.i2c[index].chan) {
|
||||
if (nouveau_i2c_init(dev, &bios->dcb.i2c[index], index))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bios->bdcb.dcb.i2c[index].chan;
|
||||
return bios->dcb.i2c[index].chan;
|
||||
}
|
||||
|
||||
|
|
|
@ -691,11 +691,14 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
|
|||
struct drm_device *dev = (struct drm_device *)arg;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t status, fbdev_flags = 0;
|
||||
unsigned long flags;
|
||||
|
||||
status = nv_rd32(dev, NV03_PMC_INTR_0);
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
if (dev_priv->fbdev_info) {
|
||||
fbdev_flags = dev_priv->fbdev_info->flags;
|
||||
dev_priv->fbdev_info->flags |= FBINFO_HWACCEL_DISABLED;
|
||||
|
@ -733,5 +736,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
|
|||
if (dev_priv->fbdev_info)
|
||||
dev_priv->fbdev_info->flags = fbdev_flags;
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
|
|
@ -391,6 +391,7 @@ nouveau_card_init(struct drm_device *dev)
|
|||
goto out;
|
||||
engine = &dev_priv->engine;
|
||||
dev_priv->init_state = NOUVEAU_CARD_INIT_FAILED;
|
||||
spin_lock_init(&dev_priv->context_switch_lock);
|
||||
|
||||
/* Parse BIOS tables / Run init tables if card not POSTed */
|
||||
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
|
||||
|
@ -776,13 +777,6 @@ int nouveau_unload(struct drm_device *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_ioctl_card_init(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
return nouveau_card_init(dev);
|
||||
}
|
||||
|
||||
int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
|
|
|
@ -230,13 +230,13 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder)
|
|||
if (dcb->type == OUTPUT_TV) {
|
||||
testval = RGB_TEST_DATA(0xa0, 0xa0, 0xa0);
|
||||
|
||||
if (dev_priv->vbios->tvdactestval)
|
||||
testval = dev_priv->vbios->tvdactestval;
|
||||
if (dev_priv->vbios.tvdactestval)
|
||||
testval = dev_priv->vbios.tvdactestval;
|
||||
} else {
|
||||
testval = RGB_TEST_DATA(0x140, 0x140, 0x140); /* 0x94050140 */
|
||||
|
||||
if (dev_priv->vbios->dactestval)
|
||||
testval = dev_priv->vbios->dactestval;
|
||||
if (dev_priv->vbios.dactestval)
|
||||
testval = dev_priv->vbios.dactestval;
|
||||
}
|
||||
|
||||
saved_rtest_ctrl = NVReadRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + regoffset);
|
||||
|
|
|
@ -269,10 +269,10 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder,
|
|||
regp->fp_horiz_regs[FP_TOTAL] = output_mode->htotal - 1;
|
||||
if (!nv_gf4_disp_arch(dev) ||
|
||||
(output_mode->hsync_start - output_mode->hdisplay) >=
|
||||
dev_priv->vbios->digital_min_front_porch)
|
||||
dev_priv->vbios.digital_min_front_porch)
|
||||
regp->fp_horiz_regs[FP_CRTC] = output_mode->hdisplay;
|
||||
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 - dev_priv->vbios.digital_min_front_porch - 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_VALID_START] = output_mode->hskew;
|
||||
|
|
|
@ -93,10 +93,9 @@ int
|
|||
nv04_display_create(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct parsed_dcb *dcb = dev_priv->vbios->dcb;
|
||||
struct dcb_table *dcb = &dev_priv->vbios.dcb;
|
||||
struct drm_encoder *encoder;
|
||||
struct drm_crtc *crtc;
|
||||
uint16_t connector[16] = { 0 };
|
||||
int i, ret;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
@ -154,52 +153,10 @@ nv04_display_create(struct drm_device *dev)
|
|||
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
connector[dcbent->connector] |= (1 << dcbent->type);
|
||||
}
|
||||
|
||||
for (i = 0; i < dcb->entries; i++) {
|
||||
struct dcb_entry *dcbent = &dcb->entry[i];
|
||||
uint16_t encoders;
|
||||
int type;
|
||||
|
||||
encoders = connector[dcbent->connector];
|
||||
if (!(encoders & (1 << dcbent->type)))
|
||||
continue;
|
||||
connector[dcbent->connector] = 0;
|
||||
|
||||
switch (dcbent->type) {
|
||||
case OUTPUT_ANALOG:
|
||||
if (!MULTIPLE_ENCODERS(encoders))
|
||||
type = DRM_MODE_CONNECTOR_VGA;
|
||||
else
|
||||
type = DRM_MODE_CONNECTOR_DVII;
|
||||
break;
|
||||
case OUTPUT_TMDS:
|
||||
if (!MULTIPLE_ENCODERS(encoders))
|
||||
type = DRM_MODE_CONNECTOR_DVID;
|
||||
else
|
||||
type = DRM_MODE_CONNECTOR_DVII;
|
||||
break;
|
||||
case OUTPUT_LVDS:
|
||||
type = DRM_MODE_CONNECTOR_LVDS;
|
||||
#if 0
|
||||
/* don't create i2c adapter when lvds ddc not allowed */
|
||||
if (dcbent->lvdsconf.use_straps_for_mode ||
|
||||
dev_priv->vbios->fp_no_ddc)
|
||||
i2c_index = 0xf;
|
||||
#endif
|
||||
break;
|
||||
case OUTPUT_TV:
|
||||
type = DRM_MODE_CONNECTOR_TV;
|
||||
break;
|
||||
default:
|
||||
type = DRM_MODE_CONNECTOR_Unknown;
|
||||
continue;
|
||||
}
|
||||
|
||||
nouveau_connector_create(dev, dcbent->connector, type);
|
||||
}
|
||||
for (i = 0; i < dcb->connector.entries; i++)
|
||||
nouveau_connector_create(dev, &dcb->connector.entry[i]);
|
||||
|
||||
/* Save previous state */
|
||||
NVLockVgaCrtcs(dev, false);
|
||||
|
|
|
@ -118,7 +118,7 @@ nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
|||
return;
|
||||
}
|
||||
|
||||
width = (image->width + 31) & ~31;
|
||||
width = ALIGN(image->width, 32);
|
||||
dsize = (width * image->height) >> 5;
|
||||
|
||||
if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
|
||||
|
|
|
@ -117,6 +117,7 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
|
|||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_gpuobj_new_fake(dev, NV04_RAMFC(chan->id), ~0,
|
||||
|
@ -127,6 +128,8 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
/* Setup initial state */
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
RAMFC_WR(DMA_PUT, chan->pushbuf_base);
|
||||
|
@ -144,6 +147,8 @@ nv04_fifo_create_context(struct nouveau_channel *chan)
|
|||
/* enable the fifo dma operation */
|
||||
nv_wr32(dev, NV04_PFIFO_MODE,
|
||||
nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ int nv04_tv_create(struct drm_device *dev, struct dcb_entry *entry)
|
|||
nv_encoder->or = ffs(entry->or) - 1;
|
||||
|
||||
/* Run the slave-specific initialization */
|
||||
adap = &dev_priv->vbios->dcb->i2c[i2c_index].chan->adapter;
|
||||
adap = &dev_priv->vbios.dcb.i2c[i2c_index].chan->adapter;
|
||||
|
||||
was_locked = NVLockVgaCrtcs(dev, false);
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder)
|
|||
|
||||
#define RGB_TEST_DATA(r, g, b) (r << 0 | g << 10 | b << 20)
|
||||
testval = RGB_TEST_DATA(0x82, 0xeb, 0x82);
|
||||
if (dev_priv->vbios->tvdactestval)
|
||||
testval = dev_priv->vbios->tvdactestval;
|
||||
if (dev_priv->vbios.tvdactestval)
|
||||
testval = dev_priv->vbios.tvdactestval;
|
||||
|
||||
dacclk = NVReadRAMDAC(dev, 0, NV_PRAMDAC_DACCLK + regoffset);
|
||||
head = (dacclk & 0x100) >> 8;
|
||||
|
@ -367,7 +367,7 @@ static void nv17_tv_prepare(struct drm_encoder *encoder)
|
|||
!enc->crtc &&
|
||||
nv04_dfp_get_bound_head(dev, dcb) == head) {
|
||||
nv04_dfp_bind_head(dev, dcb, head ^ 1,
|
||||
dev_priv->VBIOS.fp.dual_link);
|
||||
dev_priv->vbios.fp.dual_link);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ nv40_fifo_create_context(struct nouveau_channel *chan)
|
|||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
uint32_t fc = NV40_RAMFC(chan->id);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_gpuobj_new_fake(dev, NV40_RAMFC(chan->id), ~0,
|
||||
|
@ -45,6 +46,8 @@ nv40_fifo_create_context(struct nouveau_channel *chan)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
nv_wi32(dev, fc + 0, chan->pushbuf_base);
|
||||
nv_wi32(dev, fc + 4, chan->pushbuf_base);
|
||||
|
@ -63,6 +66,8 @@ nv40_fifo_create_context(struct nouveau_channel *chan)
|
|||
/* enable the fifo dma operation */
|
||||
nv_wr32(dev, NV04_PFIFO_MODE,
|
||||
nv_rd32(dev, NV04_PFIFO_MODE) | (1 << chan->id));
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,8 +79,8 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)
|
|||
}
|
||||
|
||||
/* Use bios provided value if possible. */
|
||||
if (dev_priv->vbios->dactestval) {
|
||||
load_pattern = dev_priv->vbios->dactestval;
|
||||
if (dev_priv->vbios.dactestval) {
|
||||
load_pattern = dev_priv->vbios.dactestval;
|
||||
NV_DEBUG_KMS(dev, "Using bios provided load_pattern of %d\n",
|
||||
load_pattern);
|
||||
} else {
|
||||
|
|
|
@ -370,9 +370,7 @@ nv50_display_init(struct drm_device *dev)
|
|||
struct nouveau_connector *conn = nouveau_connector(connector);
|
||||
struct dcb_gpio_entry *gpio;
|
||||
|
||||
if (connector->connector_type != DRM_MODE_CONNECTOR_DVII &&
|
||||
connector->connector_type != DRM_MODE_CONNECTOR_DVID &&
|
||||
connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
|
||||
if (conn->dcb->gpio_tag == 0xff)
|
||||
continue;
|
||||
|
||||
gpio = nouveau_bios_gpio_entry(dev, conn->dcb->gpio_tag);
|
||||
|
@ -465,8 +463,7 @@ static int nv50_display_disable(struct drm_device *dev)
|
|||
int nv50_display_create(struct drm_device *dev)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct parsed_dcb *dcb = dev_priv->vbios->dcb;
|
||||
uint32_t connector[16] = {};
|
||||
struct dcb_table *dcb = &dev_priv->vbios.dcb;
|
||||
int ret, i;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
@ -522,44 +519,13 @@ int nv50_display_create(struct drm_device *dev)
|
|||
NV_WARN(dev, "DCB encoder %d unknown\n", entry->type);
|
||||
continue;
|
||||
}
|
||||
|
||||
connector[entry->connector] |= (1 << entry->type);
|
||||
}
|
||||
|
||||
/* It appears that DCB 3.0+ VBIOS has a connector table, however,
|
||||
* I'm not 100% certain how to decode it correctly yet so just
|
||||
* look at what encoders are present on each connector index and
|
||||
* attempt to derive the connector type from that.
|
||||
*/
|
||||
for (i = 0 ; i < dcb->entries; i++) {
|
||||
struct dcb_entry *entry = &dcb->entry[i];
|
||||
uint16_t encoders;
|
||||
int type;
|
||||
|
||||
encoders = connector[entry->connector];
|
||||
if (!(encoders & (1 << entry->type)))
|
||||
for (i = 0 ; i < dcb->connector.entries; i++) {
|
||||
if (i != 0 && dcb->connector.entry[i].index ==
|
||||
dcb->connector.entry[i - 1].index)
|
||||
continue;
|
||||
connector[entry->connector] = 0;
|
||||
|
||||
if (encoders & (1 << OUTPUT_DP)) {
|
||||
type = DRM_MODE_CONNECTOR_DisplayPort;
|
||||
} else if (encoders & (1 << OUTPUT_TMDS)) {
|
||||
if (encoders & (1 << OUTPUT_ANALOG))
|
||||
type = DRM_MODE_CONNECTOR_DVII;
|
||||
else
|
||||
type = DRM_MODE_CONNECTOR_DVID;
|
||||
} else if (encoders & (1 << OUTPUT_ANALOG)) {
|
||||
type = DRM_MODE_CONNECTOR_VGA;
|
||||
} else if (encoders & (1 << OUTPUT_LVDS)) {
|
||||
type = DRM_MODE_CONNECTOR_LVDS;
|
||||
} else {
|
||||
type = DRM_MODE_CONNECTOR_Unknown;
|
||||
}
|
||||
|
||||
if (type == DRM_MODE_CONNECTOR_Unknown)
|
||||
continue;
|
||||
|
||||
nouveau_connector_create(dev, entry->connector, type);
|
||||
nouveau_connector_create(dev, &dcb->connector.entry[i]);
|
||||
}
|
||||
|
||||
ret = nv50_display_init(dev);
|
||||
|
@ -667,8 +633,8 @@ nv50_display_irq_head(struct drm_device *dev, int *phead,
|
|||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < dev_priv->vbios->dcb->entries; i++) {
|
||||
struct dcb_entry *dcbent = &dev_priv->vbios->dcb->entry[i];
|
||||
for (i = 0; i < dev_priv->vbios.dcb.entries; i++) {
|
||||
struct dcb_entry *dcbent = &dev_priv->vbios.dcb.entry[i];
|
||||
|
||||
if (dcbent->type != type)
|
||||
continue;
|
||||
|
@ -692,7 +658,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_connector *nv_connector = NULL;
|
||||
struct drm_encoder *encoder;
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
struct nvbios *bios = &dev_priv->vbios;
|
||||
uint32_t mc, script = 0, or;
|
||||
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
|
@ -710,7 +676,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcbent,
|
|||
switch (dcbent->type) {
|
||||
case OUTPUT_LVDS:
|
||||
script = (mc >> 8) & 0xf;
|
||||
if (bios->pub.fp_no_ddc) {
|
||||
if (bios->fp_no_ddc) {
|
||||
if (bios->fp.dual_link)
|
||||
script |= 0x0100;
|
||||
if (bios->fp.if_is_24bit)
|
||||
|
|
|
@ -109,7 +109,7 @@ nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
|||
return;
|
||||
}
|
||||
|
||||
width = (image->width + 31) & ~31;
|
||||
width = ALIGN(image->width, 32);
|
||||
dwords = (width * image->height) >> 5;
|
||||
|
||||
BEGIN_RING(chan, NvSub2D, 0x0814, 2);
|
||||
|
|
|
@ -243,6 +243,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
|
|||
struct drm_device *dev = chan->dev;
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *ramfc = NULL;
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
NV_DEBUG(dev, "ch%d\n", chan->id);
|
||||
|
@ -278,19 +279,21 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
|
|||
return ret;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
|
||||
nv_wo32(dev, ramfc, 0x08/4, chan->pushbuf_base);
|
||||
nv_wo32(dev, ramfc, 0x10/4, chan->pushbuf_base);
|
||||
nv_wo32(dev, ramfc, 0x48/4, chan->pushbuf->instance >> 4);
|
||||
nv_wo32(dev, ramfc, 0x80/4, (0xc << 24) | (chan->ramht->instance >> 4));
|
||||
nv_wo32(dev, ramfc, 0x3c/4, 0x00086078);
|
||||
nv_wo32(dev, ramfc, 0x44/4, 0x2101ffff);
|
||||
nv_wo32(dev, ramfc, 0x60/4, 0x7fffffff);
|
||||
nv_wo32(dev, ramfc, 0x40/4, 0x00000000);
|
||||
nv_wo32(dev, ramfc, 0x7c/4, 0x30000001);
|
||||
nv_wo32(dev, ramfc, 0x78/4, 0x00000000);
|
||||
nv_wo32(dev, ramfc, 0x4c/4, 0xffffffff);
|
||||
nv_wo32(dev, ramfc, 0x3c/4, 0x403f6078);
|
||||
nv_wo32(dev, ramfc, 0x50/4, chan->pushbuf_base +
|
||||
chan->dma.ib_base * 4);
|
||||
nv_wo32(dev, ramfc, 0x54/4, drm_order(chan->dma.ib_max + 1) << 16);
|
||||
|
||||
if (!IS_G80) {
|
||||
nv_wo32(dev, chan->ramin->gpuobj, 0, chan->id);
|
||||
|
@ -306,10 +309,12 @@ nv50_fifo_create_context(struct nouveau_channel *chan)
|
|||
ret = nv50_fifo_channel_enable(dev, chan->id, false);
|
||||
if (ret) {
|
||||
NV_ERROR(dev, "error enabling ch%d: %d\n", chan->id, ret);
|
||||
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,30 +28,7 @@
|
|||
#include "drm.h"
|
||||
#include "nouveau_drv.h"
|
||||
|
||||
MODULE_FIRMWARE("nouveau/nv50.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv50.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nv84.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv84.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nv86.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv86.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nv92.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv92.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nv94.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv94.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nv96.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv96.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nv98.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nv98.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nva0.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nva0.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nva5.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nva5.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nva8.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nva8.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nvaa.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nvaa.ctxvals");
|
||||
MODULE_FIRMWARE("nouveau/nvac.ctxprog");
|
||||
MODULE_FIRMWARE("nouveau/nvac.ctxvals");
|
||||
#include "nouveau_grctx.h"
|
||||
|
||||
#define IS_G80 ((dev_priv->chipset & 0xf0) == 0x50)
|
||||
|
||||
|
@ -111,9 +88,34 @@ nv50_graph_init_ctxctl(struct drm_device *dev)
|
|||
|
||||
NV_DEBUG(dev, "\n");
|
||||
|
||||
nouveau_grctx_prog_load(dev);
|
||||
if (!dev_priv->engine.graph.ctxprog)
|
||||
dev_priv->engine.graph.accel_blocked = true;
|
||||
if (nouveau_ctxfw) {
|
||||
nouveau_grctx_prog_load(dev);
|
||||
dev_priv->engine.graph.grctx_size = 0x70000;
|
||||
}
|
||||
if (!dev_priv->engine.graph.ctxprog) {
|
||||
struct nouveau_grctx ctx = {};
|
||||
uint32_t *cp = kmalloc(512 * 4, GFP_KERNEL);
|
||||
int i;
|
||||
if (!cp) {
|
||||
NV_ERROR(dev, "Couldn't alloc ctxprog! Disabling acceleration.\n");
|
||||
dev_priv->engine.graph.accel_blocked = true;
|
||||
return 0;
|
||||
}
|
||||
ctx.dev = dev;
|
||||
ctx.mode = NOUVEAU_GRCTX_PROG;
|
||||
ctx.data = cp;
|
||||
ctx.ctxprog_max = 512;
|
||||
if (!nv50_grctx_init(&ctx)) {
|
||||
dev_priv->engine.graph.grctx_size = ctx.ctxvals_pos * 4;
|
||||
|
||||
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0);
|
||||
for (i = 0; i < ctx.ctxprog_len; i++)
|
||||
nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]);
|
||||
} else {
|
||||
dev_priv->engine.graph.accel_blocked = true;
|
||||
}
|
||||
kfree(cp);
|
||||
}
|
||||
|
||||
nv_wr32(dev, 0x400320, 4);
|
||||
nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
|
||||
|
@ -193,13 +195,13 @@ nv50_graph_create_context(struct nouveau_channel *chan)
|
|||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct nouveau_gpuobj *ramin = chan->ramin->gpuobj;
|
||||
struct nouveau_gpuobj *ctx;
|
||||
uint32_t grctx_size = 0x70000;
|
||||
struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
|
||||
int hdr, ret;
|
||||
|
||||
NV_DEBUG(dev, "ch%d\n", chan->id);
|
||||
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, grctx_size, 0x1000,
|
||||
NVOBJ_FLAG_ZERO_ALLOC |
|
||||
ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, pgraph->grctx_size,
|
||||
0x1000, NVOBJ_FLAG_ZERO_ALLOC |
|
||||
NVOBJ_FLAG_ZERO_FREE, &chan->ramin_grctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -209,7 +211,7 @@ nv50_graph_create_context(struct nouveau_channel *chan)
|
|||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
nv_wo32(dev, ramin, (hdr + 0x00)/4, 0x00190002);
|
||||
nv_wo32(dev, ramin, (hdr + 0x04)/4, chan->ramin_grctx->instance +
|
||||
grctx_size - 1);
|
||||
pgraph->grctx_size - 1);
|
||||
nv_wo32(dev, ramin, (hdr + 0x08)/4, chan->ramin_grctx->instance);
|
||||
nv_wo32(dev, ramin, (hdr + 0x0c)/4, 0);
|
||||
nv_wo32(dev, ramin, (hdr + 0x10)/4, 0);
|
||||
|
@ -217,7 +219,15 @@ nv50_graph_create_context(struct nouveau_channel *chan)
|
|||
dev_priv->engine.instmem.finish_access(dev);
|
||||
|
||||
dev_priv->engine.instmem.prepare_access(dev, true);
|
||||
nouveau_grctx_vals_load(dev, ctx);
|
||||
if (!pgraph->ctxprog) {
|
||||
struct nouveau_grctx ctx = {};
|
||||
ctx.dev = chan->dev;
|
||||
ctx.mode = NOUVEAU_GRCTX_VALS;
|
||||
ctx.data = chan->ramin_grctx->gpuobj;
|
||||
nv50_grctx_init(&ctx);
|
||||
} else {
|
||||
nouveau_grctx_vals_load(dev, ctx);
|
||||
}
|
||||
nv_wo32(dev, ctx, 0x00000/4, chan->ramin->instance >> 12);
|
||||
if ((dev_priv->chipset & 0xf0) == 0xa0)
|
||||
nv_wo32(dev, ctx, 0x00004/4, 0x00000000);
|
||||
|
|
2367
drivers/gpu/drm/nouveau/nv50_grctx.c
Normal file
2367
drivers/gpu/drm/nouveau/nv50_grctx.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -390,7 +390,7 @@ nv50_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj,
|
|||
if (gpuobj->im_backing)
|
||||
return -EINVAL;
|
||||
|
||||
*sz = (*sz + (NV50_INSTMEM_PAGE_SIZE-1)) & ~(NV50_INSTMEM_PAGE_SIZE-1);
|
||||
*sz = ALIGN(*sz, NV50_INSTMEM_PAGE_SIZE);
|
||||
if (*sz == 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
|
|
@ -25,13 +25,14 @@
|
|||
#ifndef __NOUVEAU_DRM_H__
|
||||
#define __NOUVEAU_DRM_H__
|
||||
|
||||
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 15
|
||||
#define NOUVEAU_DRM_HEADER_PATCHLEVEL 16
|
||||
|
||||
struct drm_nouveau_channel_alloc {
|
||||
uint32_t fb_ctxdma_handle;
|
||||
uint32_t tt_ctxdma_handle;
|
||||
|
||||
int channel;
|
||||
uint32_t pushbuf_domains;
|
||||
|
||||
/* Notifier memory */
|
||||
uint32_t notifier_handle;
|
||||
|
@ -109,68 +110,58 @@ struct drm_nouveau_gem_new {
|
|||
uint32_t align;
|
||||
};
|
||||
|
||||
#define NOUVEAU_GEM_MAX_BUFFERS 1024
|
||||
struct drm_nouveau_gem_pushbuf_bo_presumed {
|
||||
uint32_t valid;
|
||||
uint32_t domain;
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gem_pushbuf_bo {
|
||||
uint64_t user_priv;
|
||||
uint32_t handle;
|
||||
uint32_t read_domains;
|
||||
uint32_t write_domains;
|
||||
uint32_t valid_domains;
|
||||
uint32_t presumed_ok;
|
||||
uint32_t presumed_domain;
|
||||
uint64_t presumed_offset;
|
||||
struct drm_nouveau_gem_pushbuf_bo_presumed presumed;
|
||||
};
|
||||
|
||||
#define NOUVEAU_GEM_RELOC_LOW (1 << 0)
|
||||
#define NOUVEAU_GEM_RELOC_HIGH (1 << 1)
|
||||
#define NOUVEAU_GEM_RELOC_OR (1 << 2)
|
||||
#define NOUVEAU_GEM_MAX_RELOCS 1024
|
||||
struct drm_nouveau_gem_pushbuf_reloc {
|
||||
uint32_t reloc_bo_index;
|
||||
uint32_t reloc_bo_offset;
|
||||
uint32_t bo_index;
|
||||
uint32_t reloc_index;
|
||||
uint32_t flags;
|
||||
uint32_t data;
|
||||
uint32_t vor;
|
||||
uint32_t tor;
|
||||
};
|
||||
|
||||
#define NOUVEAU_GEM_MAX_BUFFERS 1024
|
||||
#define NOUVEAU_GEM_MAX_RELOCS 1024
|
||||
#define NOUVEAU_GEM_MAX_PUSH 512
|
||||
struct drm_nouveau_gem_pushbuf_push {
|
||||
uint32_t bo_index;
|
||||
uint32_t pad;
|
||||
uint64_t offset;
|
||||
uint64_t length;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gem_pushbuf {
|
||||
uint32_t channel;
|
||||
uint32_t nr_dwords;
|
||||
uint32_t nr_buffers;
|
||||
uint32_t nr_relocs;
|
||||
uint64_t dwords;
|
||||
uint64_t buffers;
|
||||
uint64_t relocs;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gem_pushbuf_call {
|
||||
uint32_t channel;
|
||||
uint32_t handle;
|
||||
uint32_t offset;
|
||||
uint32_t nr_buffers;
|
||||
uint32_t nr_relocs;
|
||||
uint32_t nr_dwords;
|
||||
uint64_t buffers;
|
||||
uint32_t nr_push;
|
||||
uint64_t relocs;
|
||||
uint64_t push;
|
||||
uint32_t suffix0;
|
||||
uint32_t suffix1;
|
||||
/* below only accessed for CALL2 */
|
||||
uint64_t vram_available;
|
||||
uint64_t gart_available;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gem_pin {
|
||||
uint32_t handle;
|
||||
uint32_t domain;
|
||||
uint64_t offset;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gem_unpin {
|
||||
uint32_t handle;
|
||||
};
|
||||
|
||||
#define NOUVEAU_GEM_CPU_PREP_NOWAIT 0x00000001
|
||||
#define NOUVEAU_GEM_CPU_PREP_NOBLOCK 0x00000002
|
||||
#define NOUVEAU_GEM_CPU_PREP_WRITE 0x00000004
|
||||
|
@ -183,14 +174,6 @@ struct drm_nouveau_gem_cpu_fini {
|
|||
uint32_t handle;
|
||||
};
|
||||
|
||||
struct drm_nouveau_gem_tile {
|
||||
uint32_t handle;
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
uint32_t tile_mode;
|
||||
uint32_t tile_flags;
|
||||
};
|
||||
|
||||
enum nouveau_bus_type {
|
||||
NV_AGP = 0,
|
||||
NV_PCI = 1,
|
||||
|
@ -200,22 +183,17 @@ enum nouveau_bus_type {
|
|||
struct drm_nouveau_sarea {
|
||||
};
|
||||
|
||||
#define DRM_NOUVEAU_CARD_INIT 0x00
|
||||
#define DRM_NOUVEAU_GETPARAM 0x01
|
||||
#define DRM_NOUVEAU_SETPARAM 0x02
|
||||
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x03
|
||||
#define DRM_NOUVEAU_CHANNEL_FREE 0x04
|
||||
#define DRM_NOUVEAU_GROBJ_ALLOC 0x05
|
||||
#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x06
|
||||
#define DRM_NOUVEAU_GPUOBJ_FREE 0x07
|
||||
#define DRM_NOUVEAU_GETPARAM 0x00
|
||||
#define DRM_NOUVEAU_SETPARAM 0x01
|
||||
#define DRM_NOUVEAU_CHANNEL_ALLOC 0x02
|
||||
#define DRM_NOUVEAU_CHANNEL_FREE 0x03
|
||||
#define DRM_NOUVEAU_GROBJ_ALLOC 0x04
|
||||
#define DRM_NOUVEAU_NOTIFIEROBJ_ALLOC 0x05
|
||||
#define DRM_NOUVEAU_GPUOBJ_FREE 0x06
|
||||
#define DRM_NOUVEAU_GEM_NEW 0x40
|
||||
#define DRM_NOUVEAU_GEM_PUSHBUF 0x41
|
||||
#define DRM_NOUVEAU_GEM_PUSHBUF_CALL 0x42
|
||||
#define DRM_NOUVEAU_GEM_PIN 0x43 /* !KMS only */
|
||||
#define DRM_NOUVEAU_GEM_UNPIN 0x44 /* !KMS only */
|
||||
#define DRM_NOUVEAU_GEM_CPU_PREP 0x45
|
||||
#define DRM_NOUVEAU_GEM_CPU_FINI 0x46
|
||||
#define DRM_NOUVEAU_GEM_INFO 0x47
|
||||
#define DRM_NOUVEAU_GEM_PUSHBUF_CALL2 0x48
|
||||
#define DRM_NOUVEAU_GEM_CPU_PREP 0x42
|
||||
#define DRM_NOUVEAU_GEM_CPU_FINI 0x43
|
||||
#define DRM_NOUVEAU_GEM_INFO 0x44
|
||||
|
||||
#endif /* __NOUVEAU_DRM_H__ */
|
||||
|
|
Loading…
Reference in a new issue