Skip to content

Commit

Permalink
Merge remote branch 'nouveau/for-airlied' of /ssd/git/drm-nouveau-nex…
Browse files Browse the repository at this point in the history
…t into drm-core-next

* 'nouveau/for-airlied' of /ssd/git/drm-nouveau-next: (27 commits)
  drm/nvc0: fix typo in PRAMIN flush
  drm/nouveau: Fix DCB TMDS config parsing.
  drm/nv30: Fix PFB init for nv31.
  drm/nv04: Fix up SGRAM density detection.
  drm/i2c/ch7006: Don't use POWER_LEVEL_FULL_POWER_OFF on early chip versions.
  drm/nouveau: Init dcb->or on cards that have no usable DCB table.
  drm/nouveau: reduce severity of some "error" messages
  drm/nvc0: backup bar3 channel on suspend
  drm/nouveau: implement init table opcodex 0x5e and 0x9a
  drm/nouveau: implement init table op 0x57, INIT_LTIME
  drm/nvc0: implement crtc pll setting
  drm/nvc0: fix evo dma object so we display something
  drm/nvc0: rudimentary instmem support
  drm/nvc0: implement memory detection
  drm/nvc0: allow INIT_GPIO
  drm/nvc0: starting point for GF100 support, everything stubbed
  drm/nv30: Workaround dual TMDS brain damage.
  drm/nouveau: No need to set slave TV encoder configs explicitly.
  drm/nv17-nv4x: Attempt to init some external TMDS transmitters.
  drm/nv10: Fix up switching of NV10TCL_DMA_VTXBUF.
  ...
  • Loading branch information
Dave Airlie committed Aug 9, 2010
2 parents d8ab355 + 2dc5d2e commit c3b6ef8
Show file tree
Hide file tree
Showing 30 changed files with 1,118 additions and 201 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i2c/ch7006_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ static int ch7006_encoder_init(struct i2c_client *client,
priv->hmargin = 50;
priv->vmargin = 50;
priv->last_dpms = -1;
priv->chip_version = ch7006_read(client, CH7006_VERSION_ID);

if (ch7006_tv_norm) {
for (i = 0; i < NUM_TV_NORMS; i++) {
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/i2c/ch7006_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,10 @@ void ch7006_setup_power_state(struct drm_encoder *encoder)
}

} else {
*power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF);
if (priv->chip_version >= 0x20)
*power |= bitfs(CH7006_POWER_LEVEL, FULL_POWER_OFF);
else
*power |= bitfs(CH7006_POWER_LEVEL, POWER_OFF);
}
}

Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i2c/ch7006_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ struct ch7006_priv {
int flicker;
int scale;

int chip_version;
int last_dpms;
};

Expand Down
8 changes: 4 additions & 4 deletions drivers/gpu/drm/nouveau/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \
nouveau_dp.o \
nv04_timer.o \
nv04_mc.o nv40_mc.o nv50_mc.o \
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \
nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \
nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \
nv04_graph.o nv10_graph.o nv20_graph.o \
nv40_graph.o nv50_graph.o \
nv40_graph.o nv50_graph.o nvc0_graph.o \
nv40_grctx.o nv50_grctx.o \
nv04_instmem.o nv50_instmem.o \
nv04_instmem.o nv50_instmem.o nvc0_instmem.o \
nv50_crtc.o nv50_dac.o nv50_sor.o \
nv50_cursor.o nv50_display.o nv50_fbcon.o \
nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \
Expand Down
194 changes: 182 additions & 12 deletions drivers/gpu/drm/nouveau/nouveau_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -1927,6 +1927,31 @@ init_condition_time(struct nvbios *bios, uint16_t offset,
return 3;
}

static int
init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
/*
* INIT_LTIME opcode: 0x57 ('V')
*
* offset (8 bit): opcode
* offset + 1 (16 bit): time
*
* Sleep for "time" miliseconds.
*/

unsigned time = ROM16(bios->data[offset + 1]);

if (!iexec->execute)
return 3;

BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n",
offset, time);

msleep(time);

return 3;
}

static int
init_zm_reg_sequence(struct nvbios *bios, uint16_t offset,
struct init_exec *iexec)
Expand Down Expand Up @@ -1994,6 +2019,64 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
return 3;
}

static int
init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
/*
* INIT_I2C_IF opcode: 0x5E ('^')
*
* offset (8 bit): opcode
* offset + 1 (8 bit): DCB I2C table entry index
* offset + 2 (8 bit): I2C slave address
* offset + 3 (8 bit): I2C register
* offset + 4 (8 bit): mask
* offset + 5 (8 bit): data
*
* Read the register given by "I2C register" on the device addressed
* by "I2C slave address" on the I2C bus given by "DCB I2C table
* entry index". Compare the result AND "mask" to "data".
* If they're not equal, skip subsequent opcodes until condition is
* inverted (INIT_NOT), or we hit INIT_RESUME
*/

uint8_t i2c_index = bios->data[offset + 1];
uint8_t i2c_address = bios->data[offset + 2] >> 1;
uint8_t reg = bios->data[offset + 3];
uint8_t mask = bios->data[offset + 4];
uint8_t data = bios->data[offset + 5];
struct nouveau_i2c_chan *chan;
union i2c_smbus_data val;
int ret;

/* no execute check by design */

BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n",
offset, i2c_index, i2c_address);

chan = init_i2c_device_find(bios->dev, i2c_index);
if (!chan)
return -ENODEV;

ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0,
I2C_SMBUS_READ, reg,
I2C_SMBUS_BYTE_DATA, &val);
if (ret < 0) {
BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: [no device], "
"Mask: 0x%02X, Data: 0x%02X\n",
offset, reg, mask, data);
iexec->execute = 0;
return 6;
}

BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, "
"Mask: 0x%02X, Data: 0x%02X\n",
offset, reg, val.byte, mask, data);

iexec->execute = ((val.byte & mask) == data);

return 6;
}

static int
init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
Expand Down Expand Up @@ -2083,9 +2166,10 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb,
uint32_t val = 0;

if (off < pci_resource_len(dev->pdev, 1)) {
uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0);
uint32_t __iomem *p =
io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);

val = ioread32(p);
val = ioread32(p + (off & ~PAGE_MASK));

io_mapping_unmap_atomic(p, KM_USER0);
}
Expand All @@ -2098,9 +2182,10 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb,
uint32_t off, uint32_t val)
{
if (off < pci_resource_len(dev->pdev, 1)) {
uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0);
uint32_t __iomem *p =
io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0);

iowrite32(val, p);
iowrite32(val, p + (off & ~PAGE_MASK));
wmb();

io_mapping_unmap_atomic(p, KM_USER0);
Expand Down Expand Up @@ -2165,7 +2250,7 @@ nv04_init_compute_mem(struct nvbios *bios)
NV04_PFB_BOOT_0_RAM_AMOUNT,
NV04_PFB_BOOT_0_RAM_AMOUNT_4MB);

} else if (peek_fb(dev, fb, 0) == patt) {
} else if (peek_fb(dev, fb, 0) != patt) {
if (read_back_fb(dev, fb, 0x800000, patt))
bios_md32(bios, NV04_PFB_BOOT_0,
NV04_PFB_BOOT_0_RAM_AMOUNT,
Expand Down Expand Up @@ -2593,7 +2678,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset,
/* no iexec->execute check by design */

uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0);
uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6));
uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & 0x40) >> 6;

if (bios->major_version > 2)
return 0;
Expand Down Expand Up @@ -3140,7 +3225,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c };
int i;

if (dev_priv->card_type != NV_50) {
if (dev_priv->card_type < NV_50) {
NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n");
return 1;
}
Expand Down Expand Up @@ -3490,6 +3575,69 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
return len;
}

static int
init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
{
/*
* INIT_I2C_LONG_IF opcode: 0x9A ('')
*
* offset (8 bit): opcode
* offset + 1 (8 bit): DCB I2C table entry index
* offset + 2 (8 bit): I2C slave address
* offset + 3 (16 bit): I2C register
* offset + 5 (8 bit): mask
* offset + 6 (8 bit): data
*
* Read the register given by "I2C register" on the device addressed
* by "I2C slave address" on the I2C bus given by "DCB I2C table
* entry index". Compare the result AND "mask" to "data".
* If they're not equal, skip subsequent opcodes until condition is
* inverted (INIT_NOT), or we hit INIT_RESUME
*/

uint8_t i2c_index = bios->data[offset + 1];
uint8_t i2c_address = bios->data[offset + 2] >> 1;
uint8_t reglo = bios->data[offset + 3];
uint8_t reghi = bios->data[offset + 4];
uint8_t mask = bios->data[offset + 5];
uint8_t data = bios->data[offset + 6];
struct nouveau_i2c_chan *chan;
uint8_t buf0[2] = { reghi, reglo };
uint8_t buf1[1];
struct i2c_msg msg[2] = {
{ i2c_address, 0, 1, buf0 },
{ i2c_address, I2C_M_RD, 1, buf1 },
};
int ret;

/* no execute check by design */

BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n",
offset, i2c_index, i2c_address);

chan = init_i2c_device_find(bios->dev, i2c_index);
if (!chan)
return -ENODEV;


ret = i2c_transfer(&chan->adapter, msg, 2);
if (ret < 0) {
BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], "
"Mask: 0x%02X, Data: 0x%02X\n",
offset, reghi, reglo, mask, data);
iexec->execute = 0;
return 7;
}

BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, "
"Mask: 0x%02X, Data: 0x%02X\n",
offset, reghi, reglo, buf1[0], mask, data);

iexec->execute = ((buf1[0] & mask) == data);

return 7;
}

static struct init_tbl_entry itbl_entry[] = {
/* command name , id , length , offset , mult , command handler */
/* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */
Expand All @@ -3516,9 +3664,11 @@ static struct init_tbl_entry itbl_entry[] = {
{ "INIT_ZM_CR" , 0x53, init_zm_cr },
{ "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group },
{ "INIT_CONDITION_TIME" , 0x56, init_condition_time },
{ "INIT_LTIME" , 0x57, init_ltime },
{ "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence },
/* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
{ "INIT_SUB_DIRECT" , 0x5B, init_sub_direct },
{ "INIT_I2C_IF" , 0x5E, init_i2c_if },
{ "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg },
{ "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io },
{ "INIT_COMPUTE_MEM" , 0x63, init_compute_mem },
Expand Down Expand Up @@ -3552,6 +3702,7 @@ static struct init_tbl_entry itbl_entry[] = {
{ "INIT_97" , 0x97, init_97 },
{ "INIT_AUXCH" , 0x98, init_auxch },
{ "INIT_ZM_AUXCH" , 0x99, init_zm_auxch },
{ "INIT_I2C_LONG_IF" , 0x9A, init_i2c_long_if },
{ NULL , 0 , NULL }
};

Expand Down Expand Up @@ -4410,7 +4561,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
bios->display.script_table_ptr,
table[2], table[3], table[0] >= 0x21);
if (!otable) {
NV_ERROR(dev, "Couldn't find matching output script table\n");
NV_DEBUG_KMS(dev, "failed to match any output table\n");
return 1;
}

Expand Down Expand Up @@ -4467,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
if (script)
script = clkcmptable(bios, script, pxclk);
if (!script) {
NV_ERROR(dev, "clock script 0 not found\n");
NV_DEBUG_KMS(dev, "clock script 0 not found\n");
return 1;
}

Expand Down Expand Up @@ -4826,7 +4977,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims
pll_lim->min_p = record[12];
pll_lim->max_p = record[13];
/* where did this go to?? */
if (limit_match == 0x00614100 || limit_match == 0x00614900)
if ((entry[0] & 0xf0) == 0x80)
pll_lim->refclk = 27000;
else
pll_lim->refclk = 100000;
Expand Down Expand Up @@ -5852,7 +6003,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads)
entry->i2c_index = i2c;
entry->heads = heads;
entry->location = DCB_LOC_ON_CHIP;
/* "or" mostly unused in early gen crt modesetting, 0 is fine */
entry->or = 1;
}

static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads)
Expand Down Expand Up @@ -5980,7 +6131,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb,
}
break;
case OUTPUT_TMDS:
entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
if (dcb->version >= 0x40)
entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4;
else if (dcb->version >= 0x30)
entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8;
else if (dcb->version >= 0x22)
entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4;

break;
case 0xe:
/* weird g80 mobile type that "nv" treats as a terminator */
Expand Down Expand Up @@ -6270,6 +6427,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
dcb->i2c_table = &bios->data[i2ctabptr];
if (dcb->version >= 0x30)
dcb->i2c_default_indices = dcb->i2c_table[4];

/*
* Parse the "management" I2C bus, used for hardware
* monitoring and some external TMDS transmitters.
*/
if (dcb->version >= 0x22) {
int idx = (dcb->version >= 0x40 ?
dcb->i2c_default_indices & 0xf :
2);

read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
idx, &dcb->i2c[idx]);
}
}

if (entries > DCB_MAX_NUM_ENTRIES)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/nouveau/nouveau_bios.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ struct dcb_entry {
} dpconf;
struct {
struct sor_conf sor;
int slave_addr;
} tmdsconf;
};
bool i2c_upper_default;
Expand Down
6 changes: 0 additions & 6 deletions drivers/gpu/drm/nouveau/nouveau_bo.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo)
if (nvbo->tile)
nv10_mem_expire_tiling(dev, nvbo->tile, NULL);

spin_lock(&dev_priv->ttm.bo_list_lock);
list_del(&nvbo->head);
spin_unlock(&dev_priv->ttm.bo_list_lock);
kfree(nvbo);
}

Expand Down Expand Up @@ -166,9 +163,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
}
nvbo->channel = NULL;

spin_lock(&dev_priv->ttm.bo_list_lock);
list_add_tail(&nvbo->head, &dev_priv->ttm.bo_list);
spin_unlock(&dev_priv->ttm.bo_list_lock);
*pnvbo = nvbo;
return 0;
}
Expand Down
Loading

0 comments on commit c3b6ef8

Please sign in to comment.