diff --git a/[refs] b/[refs] index 70e7c153ce2b..f983547acce1 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5d56fe5fd794a98c4f446f8665fd06b82e93ff64 +refs/heads/master: fdc0b8a63c1124bb025a2846d41531a123845740 diff --git a/trunk/drivers/gpu/drm/drm_sman.c b/trunk/drivers/gpu/drm/drm_sman.c index cebce45f4429..462cdc87cdb8 100644 --- a/trunk/drivers/gpu/drm/drm_sman.c +++ b/trunk/drivers/gpu/drm/drm_sman.c @@ -244,7 +244,7 @@ struct drm_memblock_item *drm_sman_alloc(struct drm_sman *sman, unsigned int man EXPORT_SYMBOL(drm_sman_alloc); -static void drm_sman_free(struct drm_memblock_item *item) +void drm_sman_free(struct drm_memblock_item *item) { struct drm_sman *sman = item->sman; @@ -253,6 +253,7 @@ static void drm_sman_free(struct drm_memblock_item *item) item->mm->free(item->mm->private, item->mm_info); kfree(item); } +EXPORT_SYMBOL(drm_sman_free); int drm_sman_free_key(struct drm_sman *sman, unsigned int key) { diff --git a/trunk/drivers/gpu/drm/nouveau/Makefile b/trunk/drivers/gpu/drm/nouveau/Makefile index 9f27e3d9e69a..35ef5b1e3566 100644 --- a/trunk/drivers/gpu/drm/nouveau/Makefile +++ b/trunk/drivers/gpu/drm/nouveau/Makefile @@ -9,9 +9,9 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nouveau_bo.o nouveau_fence.o nouveau_gem.o nouveau_ttm.o \ nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ - nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \ + nouveau_dp.o nouveau_ramht.o \ nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ - nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ + nouveau_mm.o nouveau_vm.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 nvc0_fb.o \ @@ -19,12 +19,9 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ nv04_graph.o nv10_graph.o nv20_graph.o \ nv40_graph.o nv50_graph.o nvc0_graph.o \ nv40_grctx.o nv50_grctx.o nvc0_grctx.o \ - nv84_crypt.o nv98_crypt.o \ + nv84_crypt.o \ nva3_copy.o nvc0_copy.o \ nv31_mpeg.o nv50_mpeg.o \ - nv84_bsp.o \ - nv84_vp.o \ - nv98_ppp.o \ nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ nv04_crtc.o nv04_display.o nv04_cursor.o \ diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c index e5cbead85e50..5fc201b49d30 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -27,7 +27,6 @@ #include "nouveau_drv.h" #include "nouveau_hw.h" #include "nouveau_encoder.h" -#include "nouveau_gpio.h" #include @@ -35,6 +34,9 @@ #define NV_CIO_CRE_44_HEADA 0x0 #define NV_CIO_CRE_44_HEADB 0x3 #define FEATURE_MOBILE 0x10 /* also FEATURE_QUADRO for BMP */ +#define LEGACY_I2C_CRT 0x80 +#define LEGACY_I2C_PANEL 0x81 +#define LEGACY_I2C_TV 0x82 #define EDID1_LEN 128 @@ -721,19 +723,115 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev) return dcb_entry; } +static int +read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c) +{ + uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4; + int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES; + int recordoffset = 0, rdofs = 1, wrofs = 0; + uint8_t port_type = 0; + + if (!i2ctable) + return -EINVAL; + + if (dcb_version >= 0x30) { + if (i2ctable[0] != dcb_version) /* necessary? */ + NV_WARN(dev, + "DCB I2C table version mismatch (%02X vs %02X)\n", + i2ctable[0], dcb_version); + dcb_i2c_ver = i2ctable[0]; + headerlen = i2ctable[1]; + if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES) + i2c_entries = i2ctable[2]; + else + NV_WARN(dev, + "DCB I2C table has more entries than indexable " + "(%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() */ + } + /* + * It's your own fault if you call this function on a DCB 1.1 BIOS -- + * the test below is for DCB 1.2 + */ + if (dcb_version < 0x14) { + recordoffset = 2; + rdofs = 0; + wrofs = 1; + } + + if (index == 0xf) + return 0; + if (index >= i2c_entries) { + NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n", + index, i2ctable[2]); + return -ENOENT; + } + if (i2ctable[headerlen + entry_len * index + 3] == 0xff) { + NV_ERROR(dev, "DCB I2C entry invalid\n"); + return -EINVAL; + } + + if (dcb_i2c_ver >= 0x30) { + port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index]; + + /* + * Fixup for chips using same address offset for read and + * write. + */ + if (port_type == 4) /* seen on C51 */ + rdofs = wrofs = 1; + if (port_type >= 5) /* G80+ */ + rdofs = wrofs = 0; + } + + if (dcb_i2c_ver >= 0x40) { + if (port_type != 5 && port_type != 6) + NV_WARN(dev, "DCB I2C table has port type %d\n", port_type); + + i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]); + } + + i2c->port_type = port_type; + i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index]; + i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index]; + + return 0; +} + 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 dcb_table *dcb = &dev_priv->vbios.dcb; + if (i2c_index == 0xff) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ - int idx = dcb_entry_idx_from_crtchead(dev); + int idx = dcb_entry_idx_from_crtchead(dev), shift = 0; + int default_indices = dcb->i2c_default_indices; - i2c_index = NV_I2C_DEFAULT(0); if (idx != 0x7f && dcb->entry[idx].i2c_upper_default) - i2c_index = NV_I2C_DEFAULT(1); + shift = 4; + + i2c_index = (default_indices >> shift) & 0xf; } + if (i2c_index == 0x80) /* g80+ */ + i2c_index = dcb->i2c_default_indices & 0xf; + else + if (i2c_index == 0x81) + i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; + + if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) { + NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); + return NULL; + } + + /* Make sure i2c table entry has been parsed, it may not + * have been if this is a bus not referenced by a DCB encoder + */ + read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, + i2c_index, &dcb->i2c[i2c_index]); return nouveau_i2c_find(dev, i2c_index); } @@ -1101,9 +1199,13 @@ init_dp_condition(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) switch (cond) { case 0: - entry = dcb_conn(dev, dcb->connector); - if (!entry || entry[0] != DCB_CONNECTOR_eDP) + { + struct dcb_connector_table_entry *ent = + &bios->dcb.connector.entry[dcb->connector]; + + if (ent->type != DCB_CONNECTOR_eDP) iexec->execute = false; + } break; case 1: case 2: @@ -3125,6 +3227,49 @@ init_8d(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) return 1; } +static void +init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) +{ + const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; + u32 r, s, v; + + /* Not a clue, needs de-magicing */ + r = nv50_gpio_ctl[gpio->line >> 4]; + s = (gpio->line & 0x0f); + v = bios_rd32(bios, r) & ~(0x00010001 << s); + switch ((gpio->entry & 0x06000000) >> 25) { + case 1: + v |= (0x00000001 << s); + break; + case 2: + v |= (0x00010000 << s); + break; + default: + break; + } + + bios_wr32(bios, r, v); +} + +static void +init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) +{ + u32 v, i; + + v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); + v &= 0xffffff00; + v |= (gpio->entry & 0x00ff0000) >> 16; + bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); + + i = (gpio->entry & 0x1f000000) >> 24; + if (i) { + v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); + v &= 0xffffff00; + v |= gpio->line; + bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); + } +} + static int init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) { @@ -3137,8 +3282,35 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) * each GPIO according to various values listed in each entry */ - if (iexec->execute && bios->execute) - nouveau_gpio_reset(bios->dev); + struct drm_nouveau_private *dev_priv = bios->dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + int i; + + if (dev_priv->card_type < NV_50) { + NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); + return 1; + } + + if (!iexec->execute) + return 1; + + for (i = 0; i < bios->dcb.gpio.entries; i++) { + struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; + + BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); + + BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", + offset, gpio->tag, gpio->state_default); + + if (!bios->execute) + continue; + + pgpio->set(bios->dev, gpio->tag, gpio->state_default); + if (dev_priv->card_type < NV_D0) + init_gpio_unknv50(bios, gpio); + else + init_gpio_unknvd0(bios, gpio); + } return 1; } @@ -4235,6 +4407,18 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b break; } + /* Dell Latitude D620 reports a too-high value for the dual-link + * transition freq, causing us to program the panel incorrectly. + * + * It doesn't appear the VBIOS actually uses its transition freq + * (90000kHz), instead it uses the "Number of LVDS channels" field + * out of the panel ID structure (http://www.spwg.org/). + * + * For the moment, a quirk will do :) + */ + if (nv_match_device(dev, 0x01d7, 0x1028, 0x01c2)) + bios->fp.duallink_transition_clk = 80000; + /* set dual_link flag for EDID case */ if (pxclk && (chip_version < 0x25 || chip_version > 0x28)) bios->fp.dual_link = (pxclk >= bios->fp.duallink_transition_clk); @@ -4357,7 +4541,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, u16 type, int pclk, NV_DEBUG_KMS(dev, "Searching for output entry for %d %d %d\n", dcbent->type, dcbent->location, dcbent->or); for (i = 0; i < table[3]; i++) { - otable = ROMPTR(dev, table[table[1] + (i * table[2])]); + otable = ROMPTR(bios, table[table[1] + (i * table[2])]); if (otable && bios_encoder_match(dcbent, ROM32(otable[0]))) break; } @@ -4535,7 +4719,7 @@ static struct pll_mapping nv84_pll_mapping[] = { { PLL_CORE , 0x004028 }, { PLL_SHADER, 0x004020 }, { PLL_MEMORY, 0x004008 }, - { PLL_VDEC , 0x004030 }, + { PLL_UNK05 , 0x004030 }, { PLL_UNK41 , 0x00e818 }, { PLL_VPLL0 , 0x614100 }, { PLL_VPLL1 , 0x614900 }, @@ -5301,9 +5485,6 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) struct nvbios *bios = &dev_priv->vbios; u8 entries, *entry; - if (bios->type != NVBIOS_BIT) - return -ENODEV; - entries = bios->data[bios->offset + 10]; entry = &bios->data[bios->offset + 12]; while (entries--) { @@ -5312,7 +5493,7 @@ bit_table(struct drm_device *dev, u8 id, struct bit_entry *bit) bit->version = entry[1]; bit->length = ROM16(entry[2]); bit->offset = ROM16(entry[4]); - bit->data = ROMPTR(dev, entry[4]); + bit->data = ROMPTR(bios, entry[4]); return 0; } @@ -5417,6 +5598,10 @@ 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->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; @@ -5524,6 +5709,14 @@ 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]; + if (bios->data[legacy_i2c_offset + 4]) + bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; + if (bios->data[legacy_i2c_offset + 5]) + bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; + if (bios->data[legacy_i2c_offset + 6]) + bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; + if (bios->data[legacy_i2c_offset + 7]) + bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; if (bmplength > 74) { bios->fmaxvco = ROM32(bmp[67]); @@ -5574,128 +5767,286 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) return 0; } -void * -dcb_table(struct drm_device *dev) +static struct dcb_gpio_entry * +new_gpio_entry(struct nvbios *bios) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - u8 *dcb = NULL; + struct drm_device *dev = bios->dev; + struct dcb_gpio_table *gpio = &bios->dcb.gpio; - if (dev_priv->card_type > NV_04) - dcb = ROMPTR(dev, dev_priv->vbios.data[0x36]); - if (!dcb) { - NV_WARNONCE(dev, "No DCB data found in VBIOS\n"); + if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) { + NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n"); return NULL; } - if (dcb[0] >= 0x41) { - NV_WARNONCE(dev, "DCB version 0x%02x unknown\n", dcb[0]); - return NULL; - } else + return &gpio->entry[gpio->entries++]; +} + +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; + int i; + + for (i = 0; i < bios->dcb.gpio.entries; i++) { + if (bios->dcb.gpio.entry[i].tag != tag) + continue; + + return &bios->dcb.gpio.entry[i]; + } + + return NULL; +} + +static void +parse_dcb_gpio_table(struct nvbios *bios) +{ + struct drm_device *dev = bios->dev; + struct dcb_gpio_entry *e; + u8 headerlen, entries, recordlen; + u8 *dcb, *gpio = NULL, *entry; + int i; + + dcb = ROMPTR(bios, bios->data[0x36]); if (dcb[0] >= 0x30) { - if (ROM32(dcb[6]) == 0x4edcbdcb) - return dcb; + gpio = ROMPTR(bios, dcb[10]); + if (!gpio) + goto no_table; + + headerlen = gpio[1]; + entries = gpio[2]; + recordlen = gpio[3]; } else - if (dcb[0] >= 0x20) { - if (ROM32(dcb[4]) == 0x4edcbdcb) - return dcb; + if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) { + gpio = ROMPTR(bios, dcb[-15]); + if (!gpio) + goto no_table; + + headerlen = 3; + entries = gpio[2]; + recordlen = gpio[1]; } else - if (dcb[0] >= 0x15) { - if (!memcmp(&dcb[-7], "DEV_REC", 7)) - return dcb; + if (dcb[0] >= 0x22) { + /* No GPIO table present, parse the TVDAC GPIO data. */ + uint8_t *tvdac_gpio = &dcb[-5]; + + if (tvdac_gpio[0] & 1) { + e = new_gpio_entry(bios); + e->tag = DCB_GPIO_TVDAC0; + e->line = tvdac_gpio[1] >> 4; + e->invert = tvdac_gpio[0] & 2; + } + + goto no_table; } else { - /* - * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but - * always has the same single (crt) entry, even when tv-out - * present, so the conclusion is this version cannot really - * be used. - * - * v1.2 tables (some NV6/10, and NV15+) normally have the - * same 5 entries, which are not specific to the card and so - * no use. - * - * v1.2 does have an I2C table that read_dcb_i2c_table can - * handle, but cards exist (nv11 in #14821) with a bad i2c - * table pointer, so use the indices parsed in - * parse_bmp_structure. - * - * v1.1 (NV5+, maybe some NV4) is entirely unhelpful - */ - NV_WARNONCE(dev, "No useful DCB data in VBIOS\n"); - return NULL; + NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]); + goto no_table; } - NV_WARNONCE(dev, "DCB header validation failed\n"); - return NULL; + entry = gpio + headerlen; + for (i = 0; i < entries; i++, entry += recordlen) { + e = new_gpio_entry(bios); + if (!e) + break; + + if (gpio[0] < 0x40) { + e->entry = ROM16(entry[0]); + e->tag = (e->entry & 0x07e0) >> 5; + if (e->tag == 0x3f) { + bios->dcb.gpio.entries--; + continue; + } + + e->line = (e->entry & 0x001f); + e->invert = ((e->entry & 0xf800) >> 11) != 4; + } else { + e->entry = ROM32(entry[0]); + e->tag = (e->entry & 0x0000ff00) >> 8; + if (e->tag == 0xff) { + bios->dcb.gpio.entries--; + continue; + } + + e->line = (e->entry & 0x0000001f) >> 0; + if (gpio[0] == 0x40) { + e->state_default = (e->entry & 0x01000000) >> 24; + e->state[0] = (e->entry & 0x18000000) >> 27; + e->state[1] = (e->entry & 0x60000000) >> 29; + } else { + e->state_default = (e->entry & 0x00000080) >> 7; + e->state[0] = (entry[4] >> 4) & 3; + e->state[1] = (entry[4] >> 6) & 3; + } + } + } + +no_table: + /* Apple iMac G4 NV18 */ + if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { + e = new_gpio_entry(bios); + if (e) { + e->tag = DCB_GPIO_TVDAC0; + e->line = 4; + } + } } -void * -dcb_outp(struct drm_device *dev, u8 idx) +struct dcb_connector_table_entry * +nouveau_bios_connector_entry(struct drm_device *dev, int index) { - u8 *dcb = dcb_table(dev); - if (dcb && dcb[0] >= 0x30) { - if (idx < dcb[2]) - return dcb + dcb[1] + (idx * dcb[3]); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; + struct dcb_connector_table_entry *cte; + + if (index >= bios->dcb.connector.entries) + return NULL; + + 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 (dcb && dcb[0] >= 0x20) { - u8 *i2c = ROMPTR(dev, dcb[2]); - u8 *ent = dcb + 8 + (idx * 8); - if (i2c && ent < i2c) - return ent; + if (encoders & (1 << OUTPUT_LVDS)) { + type = DCB_CONNECTOR_LVDS; } else - if (dcb && dcb[0] >= 0x15) { - u8 *i2c = ROMPTR(dev, dcb[2]); - u8 *ent = dcb + 4 + (idx * 10); - if (i2c && ent < i2c) - return ent; + if (encoders & (1 << OUTPUT_TV)) { + type = DCB_CONNECTOR_TV_0; } - return NULL; + return type; } -int -dcb_outp_foreach(struct drm_device *dev, void *data, - int (*exec)(struct drm_device *, void *, int idx, u8 *outp)) -{ - int ret, idx = -1; - u8 *outp = NULL; - while ((outp = dcb_outp(dev, ++idx))) { - if (ROM32(outp[0]) == 0x00000000) - break; /* seen on an NV11 with DCB v1.5 */ - if (ROM32(outp[0]) == 0xffffffff) - break; /* seen on an NV17 with DCB v2.0 */ - - if ((outp[0] & 0x0f) == OUTPUT_UNUSED) - continue; - if ((outp[0] & 0x0f) == OUTPUT_EOL) - break; +static void +apply_dcb_connector_quirks(struct nvbios *bios, int idx) +{ + struct dcb_connector_table_entry *cte = &bios->dcb.connector.entry[idx]; + struct drm_device *dev = bios->dev; - ret = exec(dev, data, idx, outp); - if (ret) - return ret; + /* Gigabyte NX85T */ + if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) { + if (cte->type == DCB_CONNECTOR_HDMI_1) + cte->type = DCB_CONNECTOR_DVI_I; } - return 0; + /* Gigabyte GV-NX86T512H */ + if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) { + if (cte->type == DCB_CONNECTOR_HDMI_1) + cte->type = DCB_CONNECTOR_DVI_I; + } } -u8 * -dcb_conntab(struct drm_device *dev) +static const u8 hpd_gpio[16] = { + 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, +}; + +static void +parse_dcb_connector_table(struct nvbios *bios) { - u8 *dcb = dcb_table(dev); - if (dcb && dcb[0] >= 0x30 && dcb[1] >= 0x16) { - u8 *conntab = ROMPTR(dev, dcb[0x14]); - if (conntab && conntab[0] >= 0x30 && conntab[0] <= 0x40) - return conntab; + struct drm_device *dev = bios->dev; + struct dcb_connector_table *ct = &bios->dcb.connector; + struct dcb_connector_table_entry *cte; + uint8_t *conntab = &bios->data[bios->dcb.connector_table_ptr]; + uint8_t *entry; + int i; + + if (!bios->dcb.connector_table_ptr) { + NV_DEBUG_KMS(dev, "No DCB connector table present\n"); + return; } - return NULL; -} -u8 * -dcb_conn(struct drm_device *dev, u8 idx) -{ - u8 *conntab = dcb_conntab(dev); - if (conntab && idx < conntab[2]) - return conntab + conntab[1] + (idx * conntab[3]); - return NULL; + NV_INFO(dev, "DCB connector table: VHER 0x%02x %d %d %d\n", + conntab[0], conntab[1], conntab[2], conntab[3]); + if ((conntab[0] != 0x30 && conntab[0] != 0x40) || + (conntab[3] != 2 && conntab[3] != 4)) { + NV_ERROR(dev, " Unknown! Please report.\n"); + return; + } + + ct->entries = conntab[2]; + + entry = conntab + conntab[1]; + cte = &ct->entry[0]; + for (i = 0; i < conntab[2]; i++, entry += conntab[3], cte++) { + cte->index = i; + if (conntab[3] == 2) + cte->entry = ROM16(entry[0]); + else + cte->entry = ROM32(entry[0]); + + cte->type = (cte->entry & 0x000000ff) >> 0; + cte->index2 = (cte->entry & 0x00000f00) >> 8; + + cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12); + cte->gpio_tag = hpd_gpio[cte->gpio_tag]; + + if (cte->type == 0xff) + continue; + + apply_dcb_connector_quirks(bios, i); + + 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_LVDS_SPWG: + 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\n", cte->type); + break; + } + + if (nouveau_override_conntype) { + int type = divine_connector_type(bios, cte->index); + if (type != cte->type) + NV_WARN(dev, " -> type 0x%02x\n", cte->type); + } + + } } static struct dcb_entry *new_dcb_entry(struct dcb_table *dcb) @@ -5728,7 +6079,8 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, entry->type = conn & 0xf; entry->i2c_index = (conn >> 4) & 0xf; entry->heads = (conn >> 8) & 0xf; - entry->connector = (conn >> 12) & 0xf; + if (dcb->version >= 0x40) + entry->connector = (conn >> 12) & 0xf; entry->bus = (conn >> 16) & 0xf; entry->location = (conn >> 20) & 0x3; entry->or = (conn >> 24) & 0xf; @@ -5900,6 +6252,25 @@ parse_dcb15_entry(struct drm_device *dev, struct dcb_table *dcb, return true; } +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(dcb); + bool ret; + + if (dcb->version >= 0x20) + ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); + else + ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); + if (!ret) + return ret; + + 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 dcb_table *dcb) { @@ -6060,118 +6431,154 @@ fabricate_dcb_encoder_table(struct drm_device *dev, struct nvbios *bios) #endif /* Make up some sane defaults */ - fabricate_dcb_output(dcb, OUTPUT_ANALOG, - bios->legacy.i2c_indices.crt, 1, 1); + fabricate_dcb_output(dcb, OUTPUT_ANALOG, LEGACY_I2C_CRT, 1, 1); if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) - fabricate_dcb_output(dcb, OUTPUT_TV, - bios->legacy.i2c_indices.tv, + fabricate_dcb_output(dcb, OUTPUT_TV, LEGACY_I2C_TV, all_heads, 0); else if (bios->tmds.output0_script_ptr || bios->tmds.output1_script_ptr) - fabricate_dcb_output(dcb, OUTPUT_TMDS, - bios->legacy.i2c_indices.panel, + fabricate_dcb_output(dcb, OUTPUT_TMDS, LEGACY_I2C_PANEL, all_heads, 1); } static int -parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) +parse_dcb_table(struct drm_device *dev, struct nvbios *bios) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcb = &dev_priv->vbios.dcb; - u32 conf = (dcb->version >= 0x20) ? ROM32(outp[4]) : ROM32(outp[6]); - u32 conn = ROM32(outp[0]); - bool ret; - - if (apply_dcb_encoder_quirks(dev, idx, &conn, &conf)) { - struct dcb_entry *entry = new_dcb_entry(dcb); - - NV_TRACEWARN(dev, "DCB outp %02d: %08x %08x\n", idx, conn, conf); + struct dcb_table *dcb = &bios->dcb; + uint16_t dcbptr = 0, i2ctabptr = 0; + uint8_t *dcbtable; + uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; + bool configblock = true; + int recordlength = 8, confofs = 4; + int i; - if (dcb->version >= 0x20) - ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); - else - ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); - if (!ret) - return 1; /* stop parsing */ + /* get the offset from 0x36 */ + if (dev_priv->card_type > NV_04) { + dcbptr = ROM16(bios->data[0x36]); + if (dcbptr == 0x0000) + NV_WARN(dev, "No output data (DCB) found in BIOS\n"); + } - /* 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 (entry->type == OUTPUT_TV && - entry->location == DCB_LOC_ON_CHIP) - entry->i2c_index = 0x0f; + /* this situation likely means a really old card, pre DCB */ + if (dcbptr == 0x0) { + fabricate_dcb_encoder_table(dev, bios); + return 0; } - return 0; -} + dcbtable = &bios->data[dcbptr]; -static void -dcb_fake_connectors(struct nvbios *bios) -{ - struct dcb_table *dcbt = &bios->dcb; - u8 map[16] = { }; - int i, idx = 0; + /* get DCB version */ + dcb->version = dcbtable[0]; + NV_TRACE(dev, "Found Display Configuration Block version %d.%d\n", + dcb->version >> 4, dcb->version & 0xf); - /* heuristic: if we ever get a non-zero connector field, assume - * that all the indices are valid and we don't need fake them. - */ - for (i = 0; i < dcbt->entries; i++) { - if (dcbt->entry[i].connector) - return; - } + if (dcb->version >= 0x20) { /* NV17+ */ + uint32_t sig; - /* no useful connector info available, we need to make it up - * ourselves. the rule here is: anything on the same i2c bus - * is considered to be on the same connector. any output - * without an associated i2c bus is assigned its own unique - * connector index. - */ - for (i = 0; i < dcbt->entries; i++) { - u8 i2c = dcbt->entry[i].i2c_index; - if (i2c == 0x0f) { - dcbt->entry[i].connector = idx++; + if (dcb->version >= 0x30) { /* NV40+ */ + headerlen = dcbtable[1]; + entries = dcbtable[2]; + recordlength = dcbtable[3]; + i2ctabptr = ROM16(dcbtable[4]); + sig = ROM32(dcbtable[6]); + dcb->gpio_table_ptr = ROM16(dcbtable[10]); + dcb->connector_table_ptr = ROM16(dcbtable[20]); } else { - if (!map[i2c]) - map[i2c] = ++idx; - dcbt->entry[i].connector = map[i2c] - 1; + i2ctabptr = ROM16(dcbtable[2]); + sig = ROM32(dcbtable[4]); + headerlen = 8; } - } - /* if we created more than one connector, destroy the connector - * table - just in case it has random, rather than stub, entries. - */ - if (i > 1) { - u8 *conntab = dcb_conntab(bios->dev); - if (conntab) - conntab[0] = 0x00; - } -} + if (sig != 0x4edcbdcb) { + NV_ERROR(dev, "Bad Display Configuration Block " + "signature (%08X)\n", sig); + return -EINVAL; + } + } else if (dcb->version >= 0x15) { /* some NV11 and NV20 */ + char sig[8] = { 0 }; -static int -parse_dcb_table(struct drm_device *dev, struct nvbios *bios) -{ - struct dcb_table *dcb = &bios->dcb; - u8 *dcbt, *conn; - int idx; - - dcbt = dcb_table(dev); - if (!dcbt) { - /* handle pre-DCB boards */ - if (bios->type == NVBIOS_BMP) { - fabricate_dcb_encoder_table(dev, bios); - return 0; + strncpy(sig, (char *)&dcbtable[-7], 7); + i2ctabptr = ROM16(dcbtable[2]); + recordlength = 10; + confofs = 6; + + if (strcmp(sig, "DEV_REC")) { + NV_ERROR(dev, "Bad Display Configuration Block " + "signature (%s)\n", sig); + return -EINVAL; } + } else { + /* + * v1.4 (some NV15/16, NV11+) seems the same as v1.5, but always + * has the same single (crt) entry, even when tv-out present, so + * the conclusion is this version cannot really be used. + * v1.2 tables (some NV6/10, and NV15+) normally have the same + * 5 entries, which are not specific to the card and so no use. + * v1.2 does have an I2C table that read_dcb_i2c_table can + * handle, but cards exist (nv11 in #14821) with a bad i2c table + * pointer, so use the indices parsed in parse_bmp_structure. + * v1.1 (NV5+, maybe some NV4) is entirely unhelpful + */ + NV_TRACEWARN(dev, "No useful information in BIOS output table; " + "adding all possible outputs\n"); + fabricate_dcb_encoder_table(dev, bios); + return 0; + } - return -EINVAL; + if (!i2ctabptr) + NV_WARN(dev, "No pointer to DCB I2C port table\n"); + else { + 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]); + } } - NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); + if (entries > DCB_MAX_NUM_ENTRIES) + entries = DCB_MAX_NUM_ENTRIES; + + for (i = 0; i < entries; i++) { + uint32_t connection, config = 0; + + connection = ROM32(dcbtable[headerlen + recordlength * i]); + if (configblock) + config = ROM32(dcbtable[headerlen + confofs + recordlength * i]); + + /* seen on an NV11 with DCB v1.5 */ + if (connection == 0x00000000) + break; + + /* seen on an NV17 with DCB v2.0 */ + if (connection == 0xffffffff) + break; + + if ((connection & 0x0000000f) == 0x0000000f) + continue; - dcb->version = dcbt[0]; - dcb_outp_foreach(dev, NULL, parse_dcb_entry); + if (!apply_dcb_encoder_quirks(dev, i, &connection, &config)) + continue; + + NV_TRACEWARN(dev, "Raw DCB entry %d: %08x %08x\n", + dcb->entries, connection, config); + + if (!parse_dcb_entry(dev, dcb, connection, config)) + break; + } /* * apart for v2.1+ not being known for requiring merging, this @@ -6183,19 +6590,77 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) if (!dcb->entries) return -ENXIO; - /* dump connector table entries to log, if any exist */ - idx = -1; - while ((conn = dcb_conn(dev, ++idx))) { - if (conn[0] != 0xff) { - NV_TRACE(dev, "DCB conn %02d: ", idx); - if (dcb_conntab(dev)[3] < 4) - printk("%04x\n", ROM16(conn[0])); - else - printk("%08x\n", ROM32(conn[0])); + parse_dcb_gpio_table(bios); + parse_dcb_connector_table(bios); + return 0; +} + +static void +fixup_legacy_connector(struct nvbios *bios) +{ + 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 + * where the table is filled with stub entries, and the DCB entriy + * 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 (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 + * connector. any output without an associated i2c bus is assigned + * its own unique connector index. + */ + for (i = 0; i < dcb->entries; i++) { + /* + * 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].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->connector.entries++; + if (i2c != 0xf) + i2c_conn[i2c] = dcb->connector.entries; + } + + /* 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 dcb_table *dcb = &bios->dcb; + int i; + + for (i = 0; i < dcb->entries; i++) { + if (dcb->entry[i].i2c_index == LEGACY_I2C_CRT) + dcb->entry[i].i2c_index = bios->legacy.i2c_indices.crt; + if (dcb->entry[i].i2c_index == LEGACY_I2C_PANEL) + dcb->entry[i].i2c_index = bios->legacy.i2c_indices.panel; + if (dcb->entry[i].i2c_index == LEGACY_I2C_TV) + dcb->entry[i].i2c_index = bios->legacy.i2c_indices.tv; } - dcb_fake_connectors(bios); - return 0; } static int load_nv17_hwsq_ucode_entry(struct drm_device *dev, struct nvbios *bios, uint16_t hwsq_offset, int entry) @@ -6414,6 +6879,19 @@ nouveau_run_vbios_init(struct drm_device *dev) return ret; } +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 dcb_i2c_entry *entry; + int i; + + entry = &bios->dcb.i2c[0]; + for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++) + nouveau_i2c_fini(dev, entry); +} + static bool nouveau_bios_posted(struct drm_device *dev) { @@ -6450,18 +6928,13 @@ nouveau_bios_init(struct drm_device *dev) if (ret) return ret; - ret = nouveau_i2c_init(dev); - if (ret) - return ret; - - ret = nouveau_mxm_init(dev); - if (ret) - return ret; - ret = parse_dcb_table(dev, bios); if (ret) return ret; + fixup_legacy_i2c(bios); + fixup_legacy_connector(bios); + if (!bios->major_version) /* we don't run version 0 bios */ return 0; @@ -6498,6 +6971,5 @@ nouveau_bios_init(struct drm_device *dev) void nouveau_bios_takedown(struct drm_device *dev) { - nouveau_mxm_fini(dev); - nouveau_i2c_fini(dev); + nouveau_bios_i2c_devices_takedown(dev); } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h index 1e382ad5a2b8..8adb69e4a6b1 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bios.h @@ -34,14 +34,9 @@ #define DCB_LOC_ON_CHIP 0 -#define ROM16(x) le16_to_cpu(*(u16 *)&(x)) -#define ROM32(x) le32_to_cpu(*(u32 *)&(x)) -#define ROM48(x) ({ u8 *p = &(x); (u64)ROM16(p[4]) << 32 | ROM32(p[0]); }) -#define ROM64(x) le64_to_cpu(*(u64 *)&(x)) -#define ROMPTR(d,x) ({ \ - struct drm_nouveau_private *dev_priv = (d)->dev_private; \ - ROM16(x) ? &dev_priv->vbios.data[ROM16(x)] : NULL; \ -}) +#define ROM16(x) le16_to_cpu(*(uint16_t *)&(x)) +#define ROM32(x) le32_to_cpu(*(uint32_t *)&(x)) +#define ROMPTR(bios, x) (ROM16(x) ? &(bios)->data[ROM16(x)] : NULL) struct bit_entry { uint8_t id; @@ -53,12 +48,30 @@ struct bit_entry { int bit_table(struct drm_device *, u8 id, struct bit_entry *); +struct dcb_i2c_entry { + uint32_t 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, - DCB_GPIO_PWM_FAN = 0x9, - DCB_GPIO_FAN_SENSE = 0x3d, - DCB_GPIO_UNUSED = 0xff +}; + +struct dcb_gpio_entry { + enum dcb_gpio_tag tag; + int line; + bool invert; + uint32_t entry; + uint8_t state_default; + uint8_t state[2]; +}; + +struct dcb_gpio_table { + int entries; + struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES]; }; enum dcb_connector_type { @@ -77,6 +90,20 @@ enum dcb_connector_type { DCB_CONNECTOR_NONE = 0xff }; +struct dcb_connector_table_entry { + uint8_t index; + uint32_t entry; + enum dcb_connector_type type; + uint8_t index2; + uint8_t gpio_tag; + void *drm; +}; + +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, @@ -84,7 +111,6 @@ enum dcb_type { OUTPUT_LVDS = 3, OUTPUT_DP = 6, OUTPUT_EOL = 14, /* DCB 4.0+, appears to be end-of-list */ - OUTPUT_UNUSED = 15, OUTPUT_ANY = -1 }; @@ -129,8 +155,18 @@ struct dcb_entry { struct dcb_table { uint8_t version; + 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 dcb_gpio_table gpio; + uint16_t connector_table_ptr; + struct dcb_connector_table connector; }; enum nouveau_or { @@ -159,7 +195,7 @@ enum pll_types { PLL_SHADER = 0x02, PLL_UNK03 = 0x03, PLL_MEMORY = 0x04, - PLL_VDEC = 0x05, + PLL_UNK05 = 0x05, PLL_UNK40 = 0x40, PLL_UNK41 = 0x41, PLL_UNK42 = 0x42, @@ -297,11 +333,4 @@ struct nvbios { } legacy; }; -void *dcb_table(struct drm_device *); -void *dcb_outp(struct drm_device *, u8 idx); -int dcb_outp_foreach(struct drm_device *, void *data, - int (*)(struct drm_device *, void *, int idx, u8 *outp)); -u8 *dcb_conntab(struct drm_device *); -u8 *dcb_conn(struct drm_device *, u8 idx); - #endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c b/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c index 8cf4a48f872e..f12dd0f39211 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -682,7 +682,8 @@ nouveau_vma_getmap(struct nouveau_channel *chan, struct nouveau_bo *nvbo, if (mem->mem_type == TTM_PL_VRAM) nouveau_vm_map(vma, node); else - nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, node); + nouveau_vm_map_sg(vma, 0, mem->num_pages << PAGE_SHIFT, + node, node->pages); return 0; } @@ -809,6 +810,7 @@ nouveau_bo_move_flips(struct ttm_buffer_object *bo, bool evict, bool intr, static void nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { + struct nouveau_mem *node = new_mem->mm_node; struct nouveau_bo *nvbo = nouveau_bo(bo); struct nouveau_vma *vma; @@ -820,7 +822,7 @@ nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) nvbo->page_shift == vma->vm->spg_shift) { nouveau_vm_map_sg(vma, 0, new_mem-> num_pages << PAGE_SHIFT, - new_mem->mm_node); + node, node->pages); } else { nouveau_vm_unmap(vma); } @@ -1171,7 +1173,7 @@ nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nouveau_vm *vm, nouveau_vm_map(vma, nvbo->bo.mem.mm_node); else if (nvbo->bo.mem.mem_type == TTM_PL_TT) - nouveau_vm_map_sg(vma, 0, size, node); + nouveau_vm_map_sg(vma, 0, size, node, node->pages); list_add_tail(&vma->head, &nvbo->vma_list); vma->refcount = 1; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_channel.c b/trunk/drivers/gpu/drm/nouveau/nouveau_channel.c index a018defb7621..bb6ec9ef8676 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_channel.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_channel.c @@ -187,8 +187,6 @@ nouveau_channel_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, nouveau_dma_pre_init(chan); chan->user_put = 0x40; chan->user_get = 0x44; - if (dev_priv->card_type >= NV_50) - chan->user_get_hi = 0x60; /* disable the fifo caches */ pfifo->reassign(dev, false); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c index f3ce34be082a..cea6696b1906 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -35,7 +35,6 @@ #include "nouveau_encoder.h" #include "nouveau_crtc.h" #include "nouveau_connector.h" -#include "nouveau_gpio.h" #include "nouveau_hw.h" static void nouveau_connector_hotplug(void *, int); @@ -79,11 +78,29 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) return NULL; } +/*TODO: This could use improvement, and learn to handle the fixed + * BIOS tables etc. It's fine currently, for its only user. + */ +int +nouveau_connector_bpp(struct drm_connector *connector) +{ + struct nouveau_connector *nv_connector = nouveau_connector(connector); + + if (nv_connector->edid && nv_connector->edid->revision >= 4) { + u8 bpc = ((nv_connector->edid->input & 0x70) >> 3) + 4; + if (bpc > 4) + return bpc; + } + + return 18; +} + static void nouveau_connector_destroy(struct drm_connector *connector) { struct nouveau_connector *nv_connector = nouveau_connector(connector); struct drm_nouveau_private *dev_priv; + struct nouveau_gpio_engine *pgpio; struct drm_device *dev; if (!nv_connector) @@ -93,9 +110,10 @@ nouveau_connector_destroy(struct drm_connector *connector) dev_priv = dev->dev_private; NV_DEBUG_KMS(dev, "\n"); - if (nv_connector->hpd != DCB_GPIO_UNUSED) { - nouveau_gpio_isr_del(dev, 0, nv_connector->hpd, 0xff, - nouveau_connector_hotplug, connector); + pgpio = &dev_priv->engine.gpio; + if (pgpio->irq_unregister) { + pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); } kfree(nv_connector->edid); @@ -180,10 +198,6 @@ nouveau_connector_set_encoder(struct drm_connector *connector, return; nv_connector->detected_encoder = nv_encoder; - if (dev_priv->card_type >= NV_50) { - connector->interlace_allowed = true; - connector->doublescan_allowed = true; - } else if (nv_encoder->dcb->type == OUTPUT_LVDS || nv_encoder->dcb->type == OUTPUT_TMDS) { connector->doublescan_allowed = false; @@ -200,7 +214,7 @@ nouveau_connector_set_encoder(struct drm_connector *connector, connector->interlace_allowed = true; } - if (nv_connector->type == DCB_CONNECTOR_DVI_I) { + 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 ? @@ -383,7 +397,7 @@ nouveau_connector_force(struct drm_connector *connector) struct nouveau_encoder *nv_encoder; int type; - if (nv_connector->type == DCB_CONNECTOR_DVI_I) { + if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { if (connector->force == DRM_FORCE_ON_DIGITAL) type = OUTPUT_TMDS; else @@ -406,21 +420,15 @@ static int nouveau_connector_set_property(struct drm_connector *connector, struct drm_property *property, uint64_t value) { - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; struct drm_encoder *encoder = to_drm_encoder(nv_encoder); struct drm_device *dev = connector->dev; - struct nouveau_crtc *nv_crtc; int ret; - nv_crtc = NULL; - if (connector->encoder && connector->encoder->crtc) - nv_crtc = nouveau_crtc(connector->encoder->crtc); - /* Scaling mode */ if (property == dev->mode_config.scaling_mode_property) { + struct nouveau_crtc *nv_crtc = NULL; bool modeset = false; switch (value) { @@ -446,6 +454,8 @@ nouveau_connector_set_property(struct drm_connector *connector, modeset = true; nv_connector->scaling_mode = value; + if (connector->encoder && connector->encoder->crtc) + nv_crtc = nouveau_crtc(connector->encoder->crtc); if (!nv_crtc) return 0; @@ -457,7 +467,7 @@ nouveau_connector_set_property(struct drm_connector *connector, if (!ret) return -EINVAL; } else { - ret = nv_crtc->set_scale(nv_crtc, true); + ret = nv_crtc->set_scale(nv_crtc, value, true); if (ret) return ret; } @@ -465,58 +475,23 @@ nouveau_connector_set_property(struct drm_connector *connector, return 0; } - /* Underscan */ - if (property == disp->underscan_property) { - if (nv_connector->underscan != value) { - nv_connector->underscan = value; - if (!nv_crtc || !nv_crtc->set_scale) - return 0; - - return nv_crtc->set_scale(nv_crtc, true); - } - - return 0; - } - - if (property == disp->underscan_hborder_property) { - if (nv_connector->underscan_hborder != value) { - nv_connector->underscan_hborder = value; - if (!nv_crtc || !nv_crtc->set_scale) - return 0; - - return nv_crtc->set_scale(nv_crtc, true); - } - - return 0; - } - - if (property == disp->underscan_vborder_property) { - if (nv_connector->underscan_vborder != value) { - nv_connector->underscan_vborder = value; - if (!nv_crtc || !nv_crtc->set_scale) - return 0; - - return nv_crtc->set_scale(nv_crtc, true); - } - - return 0; - } - /* Dithering */ - if (property == disp->dithering_mode) { - nv_connector->dithering_mode = value; - if (!nv_crtc || !nv_crtc->set_dither) - return 0; + if (property == dev->mode_config.dithering_mode_property) { + struct nouveau_crtc *nv_crtc = NULL; - return nv_crtc->set_dither(nv_crtc, true); - } + if (value == DRM_MODE_DITHERING_ON) + nv_connector->use_dithering = true; + else + nv_connector->use_dithering = false; + + if (connector->encoder && connector->encoder->crtc) + nv_crtc = nouveau_crtc(connector->encoder->crtc); - if (property == disp->dithering_depth) { - nv_connector->dithering_depth = value; if (!nv_crtc || !nv_crtc->set_dither) return 0; - return nv_crtc->set_dither(nv_crtc, true); + return nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, + true); } if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) @@ -627,46 +602,6 @@ nouveau_connector_scaler_modes_add(struct drm_connector *connector) return modes; } -static void -nouveau_connector_detect_depth(struct drm_connector *connector) -{ - struct drm_nouveau_private *dev_priv = connector->dev->dev_private; - struct nouveau_connector *nv_connector = nouveau_connector(connector); - struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; - struct nvbios *bios = &dev_priv->vbios; - struct drm_display_mode *mode = nv_connector->native_mode; - bool duallink; - - /* if the edid is feeling nice enough to provide this info, use it */ - if (nv_connector->edid && connector->display_info.bpc) - return; - - /* if not, we're out of options unless we're LVDS, default to 6bpc */ - connector->display_info.bpc = 6; - if (nv_encoder->dcb->type != OUTPUT_LVDS) - return; - - /* LVDS: panel straps */ - if (bios->fp_no_ddc) { - if (bios->fp.if_is_24bit) - connector->display_info.bpc = 8; - return; - } - - /* LVDS: DDC panel, need to first determine the number of links to - * know which if_is_24bit flag to check... - */ - if (nv_connector->edid && - nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) - duallink = ((u8 *)nv_connector->edid)[121] == 2; - else - duallink = mode->clock >= bios->fp.duallink_transition_clk; - - if ((!duallink && (bios->fp.strapless_is_24bit & 1)) || - ( duallink && (bios->fp.strapless_is_24bit & 2))) - connector->display_info.bpc = 8; -} - static int nouveau_connector_get_modes(struct drm_connector *connector) { @@ -696,12 +631,6 @@ nouveau_connector_get_modes(struct drm_connector *connector) nv_connector->native_mode = drm_mode_duplicate(dev, &mode); } - /* Determine display colour depth for everything except LVDS now, - * DP requires this before mode_valid() is called. - */ - if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS) - nouveau_connector_detect_depth(connector); - /* Find the native mode if this is a digital panel, if we didn't * find any modes through DDC previously add the native mode to * the list of modes. @@ -717,19 +646,12 @@ nouveau_connector_get_modes(struct drm_connector *connector) ret = 1; } - /* Determine LVDS colour depth, must happen after determining - * "native" mode as some VBIOS tables require us to use the - * pixel clock as part of the lookup... - */ - if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) - nouveau_connector_detect_depth(connector); - if (nv_encoder->dcb->type == OUTPUT_TV) ret = get_slave_funcs(encoder)->get_modes(encoder, connector); - if (nv_connector->type == DCB_CONNECTOR_LVDS || - nv_connector->type == DCB_CONNECTOR_LVDS_SPWG || - nv_connector->type == DCB_CONNECTOR_eDP) + if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || + nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG || + nv_connector->dcb->type == DCB_CONNECTOR_eDP) ret += nouveau_connector_scaler_modes_add(connector); return ret; @@ -788,7 +710,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, case OUTPUT_DP: max_clock = nv_encoder->dp.link_nr; max_clock *= nv_encoder->dp.link_bw; - clock = clock * (connector->display_info.bpc * 3) / 10; + clock = clock * nouveau_connector_bpp(connector) / 10; break; default: BUG_ON(1); @@ -846,175 +768,96 @@ nouveau_connector_funcs_lvds = { .force = nouveau_connector_force }; -static int -drm_conntype_from_dcb(enum dcb_connector_type dcb) -{ - switch (dcb) { - case DCB_CONNECTOR_VGA : return DRM_MODE_CONNECTOR_VGA; - case DCB_CONNECTOR_TV_0 : - case DCB_CONNECTOR_TV_1 : - case DCB_CONNECTOR_TV_3 : return DRM_MODE_CONNECTOR_TV; - case DCB_CONNECTOR_DVI_I : return DRM_MODE_CONNECTOR_DVII; - case DCB_CONNECTOR_DVI_D : return DRM_MODE_CONNECTOR_DVID; - case DCB_CONNECTOR_LVDS : - case DCB_CONNECTOR_LVDS_SPWG: return DRM_MODE_CONNECTOR_LVDS; - case DCB_CONNECTOR_DP : return DRM_MODE_CONNECTOR_DisplayPort; - case DCB_CONNECTOR_eDP : return DRM_MODE_CONNECTOR_eDP; - case DCB_CONNECTOR_HDMI_0 : - case DCB_CONNECTOR_HDMI_1 : return DRM_MODE_CONNECTOR_HDMIA; - default: - break; - } - - return DRM_MODE_CONNECTOR_Unknown; -} - struct drm_connector * nouveau_connector_create(struct drm_device *dev, int index) { const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct nouveau_connector *nv_connector = NULL; + struct dcb_connector_table_entry *dcb = NULL; struct drm_connector *connector; int type, ret = 0; - bool dummy; NV_DEBUG_KMS(dev, "\n"); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - nv_connector = nouveau_connector(connector); - if (nv_connector->index == index) - return connector; + if (index >= dev_priv->vbios.dcb.connector.entries) + return ERR_PTR(-EINVAL); + + dcb = &dev_priv->vbios.dcb.connector.entry[index]; + if (dcb->drm) + return dcb->drm; + + switch (dcb->type) { + case DCB_CONNECTOR_VGA: + type = DRM_MODE_CONNECTOR_VGA; + break; + case DCB_CONNECTOR_TV_0: + case DCB_CONNECTOR_TV_1: + case DCB_CONNECTOR_TV_3: + type = DRM_MODE_CONNECTOR_TV; + break; + case DCB_CONNECTOR_DVI_I: + type = DRM_MODE_CONNECTOR_DVII; + break; + case DCB_CONNECTOR_DVI_D: + type = DRM_MODE_CONNECTOR_DVID; + break; + case DCB_CONNECTOR_HDMI_0: + case DCB_CONNECTOR_HDMI_1: + type = DRM_MODE_CONNECTOR_HDMIA; + break; + case DCB_CONNECTOR_LVDS: + case DCB_CONNECTOR_LVDS_SPWG: + type = DRM_MODE_CONNECTOR_LVDS; + funcs = &nouveau_connector_funcs_lvds; + break; + case DCB_CONNECTOR_DP: + type = DRM_MODE_CONNECTOR_DisplayPort; + break; + case DCB_CONNECTOR_eDP: + type = DRM_MODE_CONNECTOR_eDP; + break; + default: + NV_ERROR(dev, "unknown connector type: 0x%02x!!\n", dcb->type); + return ERR_PTR(-EINVAL); } nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); if (!nv_connector) return ERR_PTR(-ENOMEM); - + nv_connector->dcb = dcb; connector = &nv_connector->base; - nv_connector->index = index; - - /* attempt to parse vbios connector type and hotplug gpio */ - nv_connector->dcb = dcb_conn(dev, index); - if (nv_connector->dcb) { - static const u8 hpd[16] = { - 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, - }; - - u32 entry = ROM16(nv_connector->dcb[0]); - if (dcb_conntab(dev)[3] >= 4) - entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; - - nv_connector->hpd = ffs((entry & 0x07033000) >> 12); - nv_connector->hpd = hpd[nv_connector->hpd]; - - nv_connector->type = nv_connector->dcb[0]; - if (drm_conntype_from_dcb(nv_connector->type) == - DRM_MODE_CONNECTOR_Unknown) { - NV_WARN(dev, "unknown connector type %02x\n", - nv_connector->type); - nv_connector->type = DCB_CONNECTOR_NONE; - } - - /* Gigabyte NX85T */ - if (nv_match_device(dev, 0x0421, 0x1458, 0x344c)) { - if (nv_connector->type == DCB_CONNECTOR_HDMI_1) - nv_connector->type = DCB_CONNECTOR_DVI_I; - } - /* Gigabyte GV-NX86T512H */ - if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) { - if (nv_connector->type == DCB_CONNECTOR_HDMI_1) - nv_connector->type = DCB_CONNECTOR_DVI_I; - } - } else { - nv_connector->type = DCB_CONNECTOR_NONE; - nv_connector->hpd = DCB_GPIO_UNUSED; - } + /* defaults, will get overridden in detect() */ + connector->interlace_allowed = false; + connector->doublescan_allowed = false; - /* no vbios data, or an unknown dcb connector type - attempt to - * figure out something suitable ourselves - */ - if (nv_connector->type == DCB_CONNECTOR_NONE) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct dcb_table *dcbt = &dev_priv->vbios.dcb; - u32 encoders = 0; - int i; - - for (i = 0; i < dcbt->entries; i++) { - if (dcbt->entry[i].connector == nv_connector->index) - encoders |= (1 << dcbt->entry[i].type); - } + drm_connector_init(dev, connector, funcs, type); + drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); - if (encoders & (1 << OUTPUT_DP)) { - if (encoders & (1 << OUTPUT_TMDS)) - nv_connector->type = DCB_CONNECTOR_DP; - else - nv_connector->type = DCB_CONNECTOR_eDP; - } else - if (encoders & (1 << OUTPUT_TMDS)) { - if (encoders & (1 << OUTPUT_ANALOG)) - nv_connector->type = DCB_CONNECTOR_DVI_I; - else - nv_connector->type = DCB_CONNECTOR_DVI_D; - } else - if (encoders & (1 << OUTPUT_ANALOG)) { - nv_connector->type = DCB_CONNECTOR_VGA; - } else - if (encoders & (1 << OUTPUT_LVDS)) { - nv_connector->type = DCB_CONNECTOR_LVDS; - } else - if (encoders & (1 << OUTPUT_TV)) { - nv_connector->type = DCB_CONNECTOR_TV_0; - } - } + /* Check if we need dithering enabled */ + if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { + bool dummy, is_24bit = false; - type = drm_conntype_from_dcb(nv_connector->type); - if (type == DRM_MODE_CONNECTOR_LVDS) { - ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy); + ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &is_24bit); if (ret) { - NV_ERROR(dev, "Error parsing LVDS table, disabling\n"); - kfree(nv_connector); - return ERR_PTR(ret); + NV_ERROR(dev, "Error parsing LVDS table, disabling " + "LVDS\n"); + goto fail; } - funcs = &nouveau_connector_funcs_lvds; - } else { - funcs = &nouveau_connector_funcs; + nv_connector->use_dithering = !is_24bit; } - /* defaults, will get overridden in detect() */ - connector->interlace_allowed = false; - connector->doublescan_allowed = false; - - drm_connector_init(dev, connector, funcs, type); - drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); - /* Init DVI-I specific properties */ - if (nv_connector->type == DCB_CONNECTOR_DVI_I) + 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); - - /* Add overscan compensation options to digital outputs */ - if (disp->underscan_property && - (nv_connector->type == DCB_CONNECTOR_DVI_D || - nv_connector->type == DCB_CONNECTOR_DVI_I || - nv_connector->type == DCB_CONNECTOR_HDMI_0 || - nv_connector->type == DCB_CONNECTOR_HDMI_1 || - nv_connector->type == DCB_CONNECTOR_DP)) { - drm_connector_attach_property(connector, - disp->underscan_property, - UNDERSCAN_OFF); - drm_connector_attach_property(connector, - disp->underscan_hborder_property, - 0); - drm_connector_attach_property(connector, - disp->underscan_vborder_property, - 0); + drm_connector_attach_property(connector, dev->mode_config.dvi_i_select_subconnector_property, 0); } - switch (nv_connector->type) { + switch (dcb->type) { case DCB_CONNECTOR_VGA: if (dev_priv->card_type >= NV_50) { drm_connector_attach_property(connector, @@ -1033,32 +876,32 @@ nouveau_connector_create(struct drm_device *dev, int index) drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, nv_connector->scaling_mode); - if (disp->dithering_mode) { - nv_connector->dithering_mode = DITHERING_MODE_AUTO; - drm_connector_attach_property(connector, - disp->dithering_mode, - nv_connector->dithering_mode); - } - if (disp->dithering_depth) { - nv_connector->dithering_depth = DITHERING_DEPTH_AUTO; - drm_connector_attach_property(connector, - disp->dithering_depth, - nv_connector->dithering_depth); - } + drm_connector_attach_property(connector, + dev->mode_config.dithering_mode_property, + nv_connector->use_dithering ? + DRM_MODE_DITHERING_ON : DRM_MODE_DITHERING_OFF); break; } - connector->polled = DRM_CONNECTOR_POLL_CONNECT; - if (nv_connector->hpd != DCB_GPIO_UNUSED) { - ret = nouveau_gpio_isr_add(dev, 0, nv_connector->hpd, 0xff, - nouveau_connector_hotplug, - connector); - if (ret == 0) - connector->polled = DRM_CONNECTOR_POLL_HPD; + if (nv_connector->dcb->gpio_tag != 0xff && pgpio->irq_register) { + pgpio->irq_register(dev, nv_connector->dcb->gpio_tag, + nouveau_connector_hotplug, connector); + + connector->polled = DRM_CONNECTOR_POLL_HPD; + } else { + connector->polled = DRM_CONNECTOR_POLL_CONNECT; } drm_sysfs_connector_add(connector); - return connector; + + dcb->drm = connector; + return dcb->drm; + +fail: + drm_connector_cleanup(connector); + kfree(connector); + return ERR_PTR(ret); + } static void diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h index e4857021304c..711b1e9203af 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -30,43 +30,13 @@ #include "drm_edid.h" #include "nouveau_i2c.h" -enum nouveau_underscan_type { - UNDERSCAN_OFF, - UNDERSCAN_ON, - UNDERSCAN_AUTO, -}; - -/* the enum values specifically defined here match nv50/nvd0 hw values, and - * the code relies on this - */ -enum nouveau_dithering_mode { - DITHERING_MODE_OFF = 0x00, - DITHERING_MODE_ON = 0x01, - DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON, - DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON, - DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON, - DITHERING_MODE_AUTO -}; - -enum nouveau_dithering_depth { - DITHERING_DEPTH_6BPC = 0x00, - DITHERING_DEPTH_8BPC = 0x02, - DITHERING_DEPTH_AUTO -}; - struct nouveau_connector { struct drm_connector base; - enum dcb_connector_type type; - u8 index; - u8 *dcb; - u8 hpd; - int dithering_mode; - int dithering_depth; + struct dcb_connector_table_entry *dcb; + int scaling_mode; - enum nouveau_underscan_type underscan; - u32 underscan_hborder; - u32 underscan_vborder; + bool use_dithering; struct nouveau_encoder *detected_encoder; struct edid *edid; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_crtc.h b/trunk/drivers/gpu/drm/nouveau/nouveau_crtc.h index 686f6b4a1da3..bf8e1289953d 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -32,6 +32,8 @@ struct nouveau_crtc { int index; + struct drm_display_mode *mode; + uint32_t dpms_saved_fp_control; uint32_t fp_users; int saturation; @@ -65,8 +67,8 @@ struct nouveau_crtc { int depth; } lut; - int (*set_dither)(struct nouveau_crtc *crtc, bool update); - int (*set_scale)(struct nouveau_crtc *crtc, bool update); + int (*set_dither)(struct nouveau_crtc *crtc, bool on, bool update); + int (*set_scale)(struct nouveau_crtc *crtc, int mode, bool update); }; static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc) diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c b/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c index fa2ec491f6a7..f52c2db3529e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_debugfs.c @@ -44,7 +44,7 @@ nouveau_debugfs_channel_info(struct seq_file *m, void *data) seq_printf(m, "channel id : %d\n", chan->id); seq_printf(m, "cpu fifo state:\n"); - seq_printf(m, " base: 0x%10llx\n", chan->pushbuf_base); + seq_printf(m, " base: 0x%08x\n", chan->pushbuf_base); seq_printf(m, " max: 0x%08x\n", chan->dma.max << 2); seq_printf(m, " cur: 0x%08x\n", chan->dma.cur << 2); seq_printf(m, " put: 0x%08x\n", chan->dma.put << 2); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c index 3cb52bc52b21..7e88cd7f2b99 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_display.c @@ -32,8 +32,6 @@ #include "nouveau_hw.h" #include "nouveau_crtc.h" #include "nouveau_dma.h" -#include "nouveau_connector.h" -#include "nouveau_gpio.h" #include "nv50_display.h" static void @@ -149,186 +147,11 @@ nouveau_user_framebuffer_create(struct drm_device *dev, return &nouveau_fb->base; } -static const struct drm_mode_config_funcs nouveau_mode_config_funcs = { +const struct drm_mode_config_funcs nouveau_mode_config_funcs = { .fb_create = nouveau_user_framebuffer_create, .output_poll_changed = nouveau_fbcon_output_poll_changed, }; - -struct drm_prop_enum_list { - u8 gen_mask; - int type; - char *name; -}; - -static struct drm_prop_enum_list underscan[] = { - { 6, UNDERSCAN_AUTO, "auto" }, - { 6, UNDERSCAN_OFF, "off" }, - { 6, UNDERSCAN_ON, "on" }, - {} -}; - -static struct drm_prop_enum_list dither_mode[] = { - { 7, DITHERING_MODE_AUTO, "auto" }, - { 7, DITHERING_MODE_OFF, "off" }, - { 1, DITHERING_MODE_ON, "on" }, - { 6, DITHERING_MODE_STATIC2X2, "static 2x2" }, - { 6, DITHERING_MODE_DYNAMIC2X2, "dynamic 2x2" }, - { 4, DITHERING_MODE_TEMPORAL, "temporal" }, - {} -}; - -static struct drm_prop_enum_list dither_depth[] = { - { 6, DITHERING_DEPTH_AUTO, "auto" }, - { 6, DITHERING_DEPTH_6BPC, "6 bpc" }, - { 6, DITHERING_DEPTH_8BPC, "8 bpc" }, - {} -}; - -#define PROP_ENUM(p,gen,n,list) do { \ - struct drm_prop_enum_list *l = (list); \ - int c = 0; \ - while (l->gen_mask) { \ - if (l->gen_mask & (1 << (gen))) \ - c++; \ - l++; \ - } \ - if (c) { \ - p = drm_property_create(dev, DRM_MODE_PROP_ENUM, n, c); \ - l = (list); \ - c = 0; \ - while (p && l->gen_mask) { \ - if (l->gen_mask & (1 << (gen))) { \ - drm_property_add_enum(p, c, l->type, l->name); \ - c++; \ - } \ - l++; \ - } \ - } \ -} while(0) - -int -nouveau_display_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; - struct drm_connector *connector; - int ret; - - ret = disp->init(dev); - if (ret) - return ret; - - drm_kms_helper_poll_enable(dev); - - /* enable hotplug interrupts */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct nouveau_connector *conn = nouveau_connector(connector); - nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true); - } - - return ret; -} - -void -nouveau_display_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; - struct drm_connector *connector; - - /* disable hotplug interrupts */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - struct nouveau_connector *conn = nouveau_connector(connector); - nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, false); - } - - drm_kms_helper_poll_disable(dev); - disp->fini(dev); -} - -int -nouveau_display_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; - int ret, gen; - - drm_mode_config_init(dev); - drm_mode_create_scaling_mode_property(dev); - drm_mode_create_dvi_i_properties(dev); - - if (dev_priv->card_type < NV_50) - gen = 0; - else - if (dev_priv->card_type < NV_D0) - gen = 1; - else - gen = 2; - - PROP_ENUM(disp->dithering_mode, gen, "dithering mode", dither_mode); - PROP_ENUM(disp->dithering_depth, gen, "dithering depth", dither_depth); - PROP_ENUM(disp->underscan_property, gen, "underscan", underscan); - - disp->underscan_hborder_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE, - "underscan hborder", 2); - disp->underscan_hborder_property->values[0] = 0; - disp->underscan_hborder_property->values[1] = 128; - - disp->underscan_vborder_property = - drm_property_create(dev, DRM_MODE_PROP_RANGE, - "underscan vborder", 2); - disp->underscan_vborder_property->values[0] = 0; - disp->underscan_vborder_property->values[1] = 128; - - dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; - dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); - - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - if (dev_priv->card_type < NV_10) { - dev->mode_config.max_width = 2048; - dev->mode_config.max_height = 2048; - } else - if (dev_priv->card_type < NV_50) { - dev->mode_config.max_width = 4096; - dev->mode_config.max_height = 4096; - } else { - dev->mode_config.max_width = 8192; - dev->mode_config.max_height = 8192; - } - - drm_kms_helper_poll_init(dev); - drm_kms_helper_poll_disable(dev); - - ret = disp->create(dev); - if (ret) - return ret; - - if (dev->mode_config.num_crtc) { - ret = drm_vblank_init(dev, dev->mode_config.num_crtc); - if (ret) - return ret; - } - - return ret; -} - -void -nouveau_display_destroy(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_display_engine *disp = &dev_priv->engine.display; - - drm_vblank_cleanup(dev); - - disp->destroy(dev); - - drm_kms_helper_poll_fini(dev); - drm_mode_config_cleanup(dev); -} - int nouveau_vblank_enable(struct drm_device *dev, int crtc) { @@ -482,10 +305,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, /* Emit a page flip */ if (dev_priv->card_type >= NV_50) { - if (dev_priv->card_type >= NV_D0) - ret = nvd0_display_flip_next(crtc, fb, chan, 0); - else - ret = nv50_display_flip_next(crtc, fb, chan); + ret = nv50_display_flip_next(crtc, fb, chan); if (ret) { nouveau_channel_put(&chan); goto fail_unreserve; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_dma.c b/trunk/drivers/gpu/drm/nouveau/nouveau_dma.c index 4c2e4e5925fe..00bc6eaad558 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -134,13 +134,11 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) * -EBUSY if timeout exceeded */ static inline int -READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) +READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout) { - uint64_t val; + uint32_t val; val = nvchan_rd32(chan, chan->user_get); - if (chan->user_get_hi) - val |= (uint64_t)nvchan_rd32(chan, chan->user_get_hi) << 32; /* reset counter as long as GET is still advancing, this is * to avoid misdetecting a GPU lockup if the GPU happens to @@ -220,8 +218,8 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count) static int nv50_dma_wait(struct nouveau_channel *chan, int slots, int count) { - uint64_t prev_get = 0; - int ret, cnt = 0; + uint32_t cnt = 0, prev_get = 0; + int ret; ret = nv50_dma_push_wait(chan, slots + 1); if (unlikely(ret)) @@ -263,8 +261,8 @@ nv50_dma_wait(struct nouveau_channel *chan, int slots, int count) int nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size) { - uint64_t prev_get = 0; - int cnt = 0, get; + uint32_t prev_get = 0, cnt = 0; + int get; if (chan->dma.ib_max) return nv50_dma_wait(chan, slots, size); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c b/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c index 9b93b703ceab..de5efe71fefd 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -29,7 +29,6 @@ #include "nouveau_connector.h" #include "nouveau_encoder.h" #include "nouveau_crtc.h" -#include "nouveau_gpio.h" /****************************************************************************** * aux channel util functions @@ -274,6 +273,8 @@ nouveau_dp_tu_update(struct drm_device *dev, int or, int link, u32 clk, u32 bpp) u8 * nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; struct bit_entry d; u8 *table; int i; @@ -288,7 +289,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) return NULL; } - table = ROMPTR(dev, d.data[0]); + table = ROMPTR(bios, d.data[0]); if (!table) { NV_ERROR(dev, "displayport table pointer invalid\n"); return NULL; @@ -305,7 +306,7 @@ nouveau_dp_bios_data(struct drm_device *dev, struct dcb_entry *dcb, u8 **entry) } for (i = 0; i < table[3]; i++) { - *entry = ROMPTR(dev, table[table[1] + (i * table[2])]); + *entry = ROMPTR(bios, table[table[1] + (i * table[2])]); if (*entry && bios_encoder_match(dcb, ROM32((*entry)[0]))) return table; } @@ -335,6 +336,7 @@ struct dp_state { static void dp_set_link_config(struct drm_device *dev, struct dp_state *dp) { + struct drm_nouveau_private *dev_priv = dev->dev_private; int or = dp->or, link = dp->link; u8 *entry, sink[2]; u32 dp_ctrl; @@ -358,7 +360,7 @@ dp_set_link_config(struct drm_device *dev, struct dp_state *dp) * table, that has (among other things) pointers to more scripts that * need to be executed, this time depending on link speed. */ - entry = ROMPTR(dev, dp->entry[10]); + entry = ROMPTR(&dev_priv->vbios, dp->entry[10]); if (entry) { if (dp->table[0] < 0x30) { while (dp->link_bw < (ROM16(entry[0]) * 10)) @@ -557,6 +559,8 @@ dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) bool nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) { + struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector = @@ -577,7 +581,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) dp.dcb = nv_encoder->dcb; dp.crtc = nv_crtc->index; - dp.auxch = auxch->drive; + dp.auxch = auxch->rd; dp.or = nv_encoder->or; dp.link = !(nv_encoder->dcb->sorconf.link & 1); dp.dpcd = nv_encoder->dp.dpcd; @@ -586,7 +590,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) * we take during link training (DP_SET_POWER is one), we need * to ignore them for the moment to avoid races. */ - nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false); + pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); /* enable down-spreading, if possible */ if (dp.table[1] >= 16) { @@ -635,7 +639,7 @@ nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); /* re-enable hotplug detect */ - nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true); + pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); return true; } @@ -652,7 +656,7 @@ nouveau_dp_detect(struct drm_encoder *encoder) if (!auxch) return false; - ret = auxch_tx(dev, auxch->drive, 9, DP_DPCD_REV, dpcd, 8); + ret = auxch_tx(dev, auxch->rd, 9, DP_DPCD_REV, dpcd, 8); if (ret) return false; @@ -680,7 +684,7 @@ int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, uint8_t *data, int data_nr) { - return auxch_tx(auxch->dev, auxch->drive, cmd, addr, data, data_nr); + return auxch_tx(auxch->dev, auxch->rd, cmd, addr, data, data_nr); } static int diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c index e4a7cfe7898d..f0a60afac446 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -124,10 +124,6 @@ MODULE_PARM_DESC(ctxfw, "Use external HUB/GPC ucode (fermi)\n"); int nouveau_ctxfw; module_param_named(ctxfw, nouveau_ctxfw, int, 0400); -MODULE_PARM_DESC(ctxfw, "Santise DCB table according to MXM-SIS\n"); -int nouveau_mxmdcb = 1; -module_param_named(mxmdcb, nouveau_mxmdcb, int, 0400); - int nouveau_fbpercrtc; #if 0 module_param_named(fbpercrtc, nouveau_fbpercrtc, int, 0400); @@ -182,11 +178,8 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - NV_INFO(dev, "Disabling display...\n"); - nouveau_display_fini(dev); - - NV_INFO(dev, "Disabling fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + NV_INFO(dev, "Disabling fbcon acceleration...\n"); + nouveau_fbcon_save_disable_accel(dev); NV_INFO(dev, "Unpinning framebuffer(s)...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -227,7 +220,7 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) ret = dev_priv->eng[e]->fini(dev, e, true); if (ret) { - NV_ERROR(dev, "... engine %d failed: %d\n", e, ret); + NV_ERROR(dev, "... engine %d failed: %d\n", i, ret); goto out_abort; } } @@ -253,6 +246,10 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) pci_set_power_state(pdev, PCI_D3hot); } + console_lock(); + nouveau_fbcon_set_suspend(dev, 1); + console_unlock(); + nouveau_fbcon_restore_accel(dev); return 0; out_abort: @@ -278,6 +275,8 @@ nouveau_pci_resume(struct pci_dev *pdev) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; + nouveau_fbcon_save_disable_accel(dev); + NV_INFO(dev, "We're back, enabling device...\n"); pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); @@ -297,6 +296,8 @@ nouveau_pci_resume(struct pci_dev *pdev) if (ret) return ret; + nouveau_pm_resume(dev); + if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) { ret = nouveau_mem_init_agp(dev); if (ret) { @@ -336,8 +337,6 @@ nouveau_pci_resume(struct pci_dev *pdev) } } - nouveau_pm_resume(dev); - NV_INFO(dev, "Restoring mode...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct nouveau_framebuffer *nouveau_fb; @@ -359,10 +358,16 @@ nouveau_pci_resume(struct pci_dev *pdev) NV_ERROR(dev, "Could not pin/map cursor.\n"); } - nouveau_fbcon_set_suspend(dev, 0); - nouveau_fbcon_zfill_all(dev); + engine->display.init(dev); + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); + u32 offset = nv_crtc->cursor.nvbo->bo.offset; - nouveau_display_init(dev); + nv_crtc->cursor.set_offset(nv_crtc, offset); + nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, + nv_crtc->cursor_saved_y); + } /* Force CLUT to get re-loaded during modeset */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -371,17 +376,15 @@ nouveau_pci_resume(struct pci_dev *pdev) nv_crtc->lut.depth = 0; } - drm_helper_resume_force_mode(dev); + console_lock(); + nouveau_fbcon_set_suspend(dev, 0); + console_unlock(); - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - u32 offset = nv_crtc->cursor.nvbo->bo.offset; + nouveau_fbcon_zfill_all(dev); - nv_crtc->cursor.set_offset(nv_crtc, offset); - nv_crtc->cursor.set_pos(nv_crtc, nv_crtc->cursor_saved_x, - nv_crtc->cursor_saved_y); - } + drm_helper_resume_force_mode(dev); + nouveau_fbcon_restore_accel(dev); return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h index 38134a9c7578..dfddb7e078a1 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -163,9 +163,6 @@ enum nouveau_flags { #define NVOBJ_ENGINE_COPY0 3 #define NVOBJ_ENGINE_COPY1 4 #define NVOBJ_ENGINE_MPEG 5 -#define NVOBJ_ENGINE_PPP NVOBJ_ENGINE_MPEG -#define NVOBJ_ENGINE_BSP 6 -#define NVOBJ_ENGINE_VP 7 #define NVOBJ_ENGINE_DISPLAY 15 #define NVOBJ_ENGINE_NR 16 @@ -232,7 +229,6 @@ struct nouveau_channel { /* mapping of the regs controlling the fifo */ void __iomem *user; uint32_t user_get; - uint32_t user_get_hi; uint32_t user_put; /* Fencing */ @@ -250,7 +246,7 @@ struct nouveau_channel { struct nouveau_gpuobj *pushbuf; struct nouveau_bo *pushbuf_bo; struct nouveau_vma pushbuf_vma; - uint64_t pushbuf_base; + uint32_t pushbuf_base; /* Notifier memory */ struct nouveau_bo *notifier_bo; @@ -397,25 +393,24 @@ struct nouveau_display_engine { int (*early_init)(struct drm_device *); void (*late_takedown)(struct drm_device *); int (*create)(struct drm_device *); - void (*destroy)(struct drm_device *); int (*init)(struct drm_device *); - void (*fini)(struct drm_device *); - - struct drm_property *dithering_mode; - struct drm_property *dithering_depth; - struct drm_property *underscan_property; - struct drm_property *underscan_hborder_property; - struct drm_property *underscan_vborder_property; + void (*destroy)(struct drm_device *); }; struct nouveau_gpio_engine { - spinlock_t lock; - struct list_head isr; - int (*init)(struct drm_device *); - void (*fini)(struct drm_device *); - int (*drive)(struct drm_device *, int line, int dir, int out); - int (*sense)(struct drm_device *, int line); - void (*irq_enable)(struct drm_device *, int line, bool); + void *priv; + + int (*init)(struct drm_device *); + void (*takedown)(struct drm_device *); + + int (*get)(struct drm_device *, enum dcb_gpio_tag); + int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); + + int (*irq_register)(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); + void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); + bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); }; struct nouveau_pm_voltage_level { @@ -489,7 +484,7 @@ struct nouveau_pm_level { u32 copy; u32 daemon; u32 vdec; - u32 dom6; + u32 unk05; /* nv50:nva3, roughly.. */ u32 unka0; /* nva3:nvc0 */ u32 hub01; /* nvc0- */ u32 hub06; /* nvc0- */ @@ -523,12 +518,6 @@ struct nouveau_pm_memtimings { int nr_timing; }; -struct nouveau_pm_fan { - u32 min_duty; - u32 max_duty; - u32 pwm_freq; -}; - struct nouveau_pm_engine { struct nouveau_pm_voltage voltage; struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL]; @@ -536,8 +525,6 @@ struct nouveau_pm_engine { struct nouveau_pm_memtimings memtimings; struct nouveau_pm_temp_sensor_constants sensor_constants; struct nouveau_pm_threshold_temp threshold_temp; - struct nouveau_pm_fan fan; - u32 pwm_divisor; struct nouveau_pm_level boot; struct nouveau_pm_level *cur; @@ -545,14 +532,19 @@ struct nouveau_pm_engine { struct device *hwmon; struct notifier_block acpi_nb; + int (*clock_get)(struct drm_device *, u32 id); + void *(*clock_pre)(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); + void (*clock_set)(struct drm_device *, void *); + int (*clocks_get)(struct drm_device *, struct nouveau_pm_level *); void *(*clocks_pre)(struct drm_device *, struct nouveau_pm_level *); - int (*clocks_set)(struct drm_device *, void *); + void (*clocks_set)(struct drm_device *, void *); int (*voltage_get)(struct drm_device *); int (*voltage_set)(struct drm_device *, int voltage); - int (*pwm_get)(struct drm_device *, int line, u32*, u32*); - int (*pwm_set)(struct drm_device *, int line, u32, u32); + int (*fanspeed_get)(struct drm_device *); + int (*fanspeed_set)(struct drm_device *, int fanspeed); int (*temp_get)(struct drm_device *); }; @@ -788,8 +780,6 @@ struct drm_nouveau_private { struct nouveau_vm *chan_vm; struct nvbios vbios; - u8 *mxms; - struct list_head i2c_ports; struct nv04_mode_state mode_reg; struct nv04_mode_state saved_reg; @@ -860,7 +850,6 @@ extern char *nouveau_perflvl; extern int nouveau_perflvl_wr; extern int nouveau_msi; extern int nouveau_ctxfw; -extern int nouveau_mxmdcb; extern int nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state); extern int nouveau_pci_resume(struct pci_dev *pdev); @@ -1086,6 +1075,8 @@ extern int nouveau_run_vbios_init(struct drm_device *); extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, struct dcb_entry *, int crtc); extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); +extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, + enum dcb_gpio_tag); extern struct dcb_connector_table_entry * nouveau_bios_connector_entry(struct drm_device *, int index); extern u32 get_pll_register(struct drm_device *, enum pll_types); @@ -1103,18 +1094,11 @@ extern int call_lvds_script(struct drm_device *, struct dcb_entry *, int head, enum LVDS_script, int pxclk); bool bios_encoder_match(struct dcb_entry *, u32 hash); -/* nouveau_mxm.c */ -int nouveau_mxm_init(struct drm_device *dev); -void nouveau_mxm_fini(struct drm_device *dev); - /* nouveau_ttm.c */ int nouveau_ttm_global_init(struct drm_nouveau_private *); void nouveau_ttm_global_release(struct drm_nouveau_private *); int nouveau_ttm_mmap(struct file *, struct vm_area_struct *); -/* nouveau_hdmi.c */ -void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *); - /* nouveau_dp.c */ int nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, uint8_t *data, int data_nr); @@ -1241,9 +1225,6 @@ extern int nvc0_graph_isr_chid(struct drm_device *dev, u64 inst); /* nv84_crypt.c */ extern int nv84_crypt_create(struct drm_device *); -/* nv98_crypt.c */ -extern int nv98_crypt_create(struct drm_device *dev); - /* nva3_copy.c */ extern int nva3_copy_create(struct drm_device *dev); @@ -1256,17 +1237,6 @@ extern int nv31_mpeg_create(struct drm_device *dev); /* nv50_mpeg.c */ extern int nv50_mpeg_create(struct drm_device *dev); -/* nv84_bsp.c */ -/* nv98_bsp.c */ -extern int nv84_bsp_create(struct drm_device *dev); - -/* nv84_vp.c */ -/* nv98_vp.c */ -extern int nv84_vp_create(struct drm_device *dev); - -/* nv98_ppp.c */ -extern int nv98_ppp_create(struct drm_device *dev); - /* nv04_instmem.c */ extern int nv04_instmem_init(struct drm_device *); extern void nv04_instmem_takedown(struct drm_device *); @@ -1344,19 +1314,13 @@ extern int nv17_tv_create(struct drm_connector *, struct dcb_entry *); extern int nv04_display_early_init(struct drm_device *); extern void nv04_display_late_takedown(struct drm_device *); extern int nv04_display_create(struct drm_device *); -extern void nv04_display_destroy(struct drm_device *); extern int nv04_display_init(struct drm_device *); -extern void nv04_display_fini(struct drm_device *); +extern void nv04_display_destroy(struct drm_device *); /* nvd0_display.c */ extern int nvd0_display_create(struct drm_device *); -extern void nvd0_display_destroy(struct drm_device *); extern int nvd0_display_init(struct drm_device *); -extern void nvd0_display_fini(struct drm_device *); -struct nouveau_bo *nvd0_display_crtc_sema(struct drm_device *, int crtc); -void nvd0_display_flip_stop(struct drm_crtc *); -int nvd0_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, - struct nouveau_channel *, u32 swap_interval); +extern void nvd0_display_destroy(struct drm_device *); /* nv04_crtc.c */ extern int nv04_crtc_create(struct drm_device *, int index); @@ -1451,10 +1415,6 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, struct drm_file *); /* nouveau_display.c */ -int nouveau_display_create(struct drm_device *dev); -void nouveau_display_destroy(struct drm_device *dev); -int nouveau_display_init(struct drm_device *dev); -void nouveau_display_fini(struct drm_device *dev); int nouveau_vblank_enable(struct drm_device *dev, int crtc); void nouveau_vblank_disable(struct drm_device *dev, int crtc); int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -1469,22 +1429,23 @@ int nouveau_display_dumb_destroy(struct drm_file *, struct drm_device *, uint32_t handle); /* nv10_gpio.c */ -int nv10_gpio_init(struct drm_device *dev); -void nv10_gpio_fini(struct drm_device *dev); -int nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out); -int nv10_gpio_sense(struct drm_device *dev, int line); -void nv10_gpio_irq_enable(struct drm_device *, int line, bool on); +int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); /* nv50_gpio.c */ int nv50_gpio_init(struct drm_device *dev); void nv50_gpio_fini(struct drm_device *dev); -int nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out); -int nv50_gpio_sense(struct drm_device *dev, int line); -void nv50_gpio_irq_enable(struct drm_device *, int line, bool on); -int nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out); -int nvd0_gpio_sense(struct drm_device *dev, int line); - -/* nv50_calc.c */ +int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); +int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); +int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); +void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, + void (*)(void *, int), void *); +bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); + +/* nv50_calc. */ int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, int *N1, int *M1, int *N2, int *M2, int *P); int nva3_calc_pll(struct drm_device *, struct pll_lims *, @@ -1607,13 +1568,6 @@ extern void nv_wo32(struct nouveau_gpuobj *, u32 offset, u32 val); #define NV_TRACEWARN(d, fmt, arg...) NV_PRINTK(KERN_NOTICE, d, fmt, ##arg) #define NV_TRACE(d, fmt, arg...) NV_PRINTK(KERN_INFO, d, fmt, ##arg) #define NV_WARN(d, fmt, arg...) NV_PRINTK(KERN_WARNING, d, fmt, ##arg) -#define NV_WARNONCE(d, fmt, arg...) do { \ - static int _warned = 0; \ - if (!_warned) { \ - NV_WARN(d, fmt, ##arg); \ - _warned = 1; \ - } \ -} while(0) /* nouveau_reg_debug bitmask */ enum { diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_fb.h b/trunk/drivers/gpu/drm/nouveau/nouveau_fb.h index f3fb649fe454..f4dd30150879 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_fb.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_fb.h @@ -42,6 +42,8 @@ nouveau_framebuffer(struct drm_framebuffer *fb) return container_of(fb, struct nouveau_framebuffer, base); } +extern const struct drm_mode_config_funcs nouveau_mode_config_funcs; + int nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb, struct drm_mode_fb_cmd2 *mode_cmd, struct nouveau_bo *nvbo); #endif /* __NOUVEAU_FB_H__ */ diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 9892218d7452..dbb151834121 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -36,7 +36,6 @@ #include #include #include -#include #include "drmP.h" #include "drm.h" @@ -549,13 +548,7 @@ void nouveau_fbcon_restore_accel(struct drm_device *dev) void nouveau_fbcon_set_suspend(struct drm_device *dev, int state) { struct drm_nouveau_private *dev_priv = dev->dev_private; - console_lock(); - if (state == 0) - nouveau_fbcon_save_disable_accel(dev); fb_set_suspend(dev_priv->nfbdev->helper.fbdev, state); - if (state == 1) - nouveau_fbcon_restore_accel(dev); - console_unlock(); } void nouveau_fbcon_zfill_all(struct drm_device *dev) diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_gpio.c b/trunk/drivers/gpu/drm/nouveau/nouveau_gpio.c deleted file mode 100644 index a580cc62337a..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_gpio.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_i2c.h" -#include "nouveau_gpio.h" - -static u8 * -dcb_gpio_table(struct drm_device *dev) -{ - u8 *dcb = dcb_table(dev); - if (dcb) { - if (dcb[0] >= 0x30 && dcb[1] >= 0x0c) - return ROMPTR(dev, dcb[0x0a]); - if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) - return ROMPTR(dev, dcb[-15]); - } - return NULL; -} - -static u8 * -dcb_gpio_entry(struct drm_device *dev, int idx, int ent, u8 *version) -{ - u8 *table = dcb_gpio_table(dev); - if (table) { - *version = table[0]; - if (*version < 0x30 && ent < table[2]) - return table + 3 + (ent * table[1]); - else if (ent < table[2]) - return table + table[1] + (ent * table[3]); - } - return NULL; -} - -int -nouveau_gpio_drive(struct drm_device *dev, int idx, int line, int dir, int out) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - return pgpio->drive ? pgpio->drive(dev, line, dir, out) : -ENODEV; -} - -int -nouveau_gpio_sense(struct drm_device *dev, int idx, int line) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - return pgpio->sense ? pgpio->sense(dev, line) : -ENODEV; -} - -int -nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, - struct gpio_func *gpio) -{ - u8 *table, *entry, version; - int i = -1; - - if (line == 0xff && func == 0xff) - return -EINVAL; - - while ((entry = dcb_gpio_entry(dev, idx, ++i, &version))) { - if (version < 0x40) { - u16 data = ROM16(entry[0]); - *gpio = (struct gpio_func) { - .line = (data & 0x001f) >> 0, - .func = (data & 0x07e0) >> 5, - .log[0] = (data & 0x1800) >> 11, - .log[1] = (data & 0x6000) >> 13, - }; - } else - if (version < 0x41) { - *gpio = (struct gpio_func) { - .line = entry[0] & 0x1f, - .func = entry[1], - .log[0] = (entry[3] & 0x18) >> 3, - .log[1] = (entry[3] & 0x60) >> 5, - }; - } else { - *gpio = (struct gpio_func) { - .line = entry[0] & 0x3f, - .func = entry[1], - .log[0] = (entry[4] & 0x30) >> 4, - .log[1] = (entry[4] & 0xc0) >> 6, - }; - } - - if ((line == 0xff || line == gpio->line) && - (func == 0xff || func == gpio->func)) - return 0; - } - - /* DCB 2.2, fixed TVDAC GPIO data */ - if ((table = dcb_table(dev)) && table[0] >= 0x22) { - if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct gpio_func) { - .func = DCB_GPIO_TVDAC0, - .line = table[-4] >> 4, - .log[0] = !!(table[-5] & 2), - .log[1] = !(table[-5] & 2), - }; - return 0; - } - } - - /* Apple iMac G4 NV18 */ - if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { - if (func == DCB_GPIO_TVDAC0) { - *gpio = (struct gpio_func) { - .func = DCB_GPIO_TVDAC0, - .line = 4, - .log[0] = 0, - .log[1] = 1, - }; - return 0; - } - } - - return -EINVAL; -} - -int -nouveau_gpio_set(struct drm_device *dev, int idx, u8 tag, u8 line, int state) -{ - struct gpio_func gpio; - int ret; - - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); - if (ret == 0) { - int dir = !!(gpio.log[state] & 0x02); - int out = !!(gpio.log[state] & 0x01); - ret = nouveau_gpio_drive(dev, idx, gpio.line, dir, out); - } - - return ret; -} - -int -nouveau_gpio_get(struct drm_device *dev, int idx, u8 tag, u8 line) -{ - struct gpio_func gpio; - int ret; - - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); - if (ret == 0) { - ret = nouveau_gpio_sense(dev, idx, gpio.line); - if (ret >= 0) - ret = (ret == (gpio.log[1] & 1)); - } - - return ret; -} - -int -nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct gpio_func gpio; - int ret; - - ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); - if (ret == 0) { - if (idx == 0 && pgpio->irq_enable) - pgpio->irq_enable(dev, gpio.line, on); - else - ret = -ENODEV; - } - - return ret; -} - -struct gpio_isr { - struct drm_device *dev; - struct list_head head; - struct work_struct work; - int idx; - struct gpio_func func; - void (*handler)(void *, int); - void *data; - bool inhibit; -}; - -static void -nouveau_gpio_isr_bh(struct work_struct *work) -{ - struct gpio_isr *isr = container_of(work, struct gpio_isr, work); - struct drm_device *dev = isr->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - unsigned long flags; - int state; - - state = nouveau_gpio_get(dev, isr->idx, isr->func.func, isr->func.line); - if (state >= 0) - isr->handler(isr->data, state); - - spin_lock_irqsave(&pgpio->lock, flags); - isr->inhibit = false; - spin_unlock_irqrestore(&pgpio->lock, flags); -} - -void -nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct gpio_isr *isr; - - if (idx != 0) - return; - - spin_lock(&pgpio->lock); - list_for_each_entry(isr, &pgpio->isr, head) { - if (line_mask & (1 << isr->func.line)) { - if (isr->inhibit) - continue; - isr->inhibit = true; - schedule_work(&isr->work); - } - } - spin_unlock(&pgpio->lock); -} - -int -nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, - void (*handler)(void *, int), void *data) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct gpio_isr *isr; - unsigned long flags; - int ret; - - isr = kzalloc(sizeof(*isr), GFP_KERNEL); - if (!isr) - return -ENOMEM; - - ret = nouveau_gpio_find(dev, idx, tag, line, &isr->func); - if (ret) { - kfree(isr); - return ret; - } - - INIT_WORK(&isr->work, nouveau_gpio_isr_bh); - isr->dev = dev; - isr->handler = handler; - isr->data = data; - isr->idx = idx; - - spin_lock_irqsave(&pgpio->lock, flags); - list_add(&isr->head, &pgpio->isr); - spin_unlock_irqrestore(&pgpio->lock, flags); - return 0; -} - -void -nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, - void (*handler)(void *, int), void *data) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - struct gpio_isr *isr, *tmp; - struct gpio_func func; - unsigned long flags; - LIST_HEAD(tofree); - int ret; - - ret = nouveau_gpio_find(dev, idx, tag, line, &func); - if (ret == 0) { - spin_lock_irqsave(&pgpio->lock, flags); - list_for_each_entry_safe(isr, tmp, &pgpio->isr, head) { - if (memcmp(&isr->func, &func, sizeof(func)) || - isr->idx != idx || - isr->handler != handler || isr->data != data) - continue; - list_move(&isr->head, &tofree); - } - spin_unlock_irqrestore(&pgpio->lock, flags); - - list_for_each_entry_safe(isr, tmp, &tofree, head) { - flush_work_sync(&isr->work); - kfree(isr); - } - } -} - -int -nouveau_gpio_create(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - INIT_LIST_HEAD(&pgpio->isr); - spin_lock_init(&pgpio->lock); - - return nouveau_gpio_init(dev); -} - -void -nouveau_gpio_destroy(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - nouveau_gpio_fini(dev); - BUG_ON(!list_empty(&pgpio->isr)); -} - -int -nouveau_gpio_init(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - int ret = 0; - - if (pgpio->init) - ret = pgpio->init(dev); - - return ret; -} - -void -nouveau_gpio_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; - - if (pgpio->fini) - pgpio->fini(dev); -} - -void -nouveau_gpio_reset(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u8 *entry, version; - int ent = -1; - - while ((entry = dcb_gpio_entry(dev, 0, ++ent, &version))) { - u8 func = 0xff, line, defs, unk0, unk1; - if (version >= 0x41) { - defs = !!(entry[0] & 0x80); - line = entry[0] & 0x3f; - func = entry[1]; - unk0 = entry[2]; - unk1 = entry[3] & 0x1f; - } else - if (version >= 0x40) { - line = entry[0] & 0x1f; - func = entry[1]; - defs = !!(entry[3] & 0x01); - unk0 = !!(entry[3] & 0x02); - unk1 = !!(entry[3] & 0x04); - } else { - break; - } - - if (func == 0xff) - continue; - - nouveau_gpio_func_set(dev, func, defs); - - if (dev_priv->card_type >= NV_D0) { - nv_mask(dev, 0x00d610 + (line * 4), 0xff, unk0); - if (unk1--) - nv_mask(dev, 0x00d640 + (unk1 * 4), 0xff, line); - } else - if (dev_priv->card_type >= NV_50) { - static const u32 regs[] = { 0xe100, 0xe28c }; - u32 val = (unk1 << 16) | unk0; - u32 reg = regs[line >> 4]; line &= 0x0f; - - nv_mask(dev, reg, 0x00010001 << line, val << line); - } - } -} diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_gpio.h b/trunk/drivers/gpu/drm/nouveau/nouveau_gpio.h deleted file mode 100644 index 64c5cb077ace..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_gpio.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __NOUVEAU_GPIO_H__ -#define __NOUVEAU_GPIO_H__ - -struct gpio_func { - u8 func; - u8 line; - u8 log[2]; -}; - -/* nouveau_gpio.c */ -int nouveau_gpio_create(struct drm_device *); -void nouveau_gpio_destroy(struct drm_device *); -int nouveau_gpio_init(struct drm_device *); -void nouveau_gpio_fini(struct drm_device *); -void nouveau_gpio_reset(struct drm_device *); -int nouveau_gpio_drive(struct drm_device *, int idx, int line, - int dir, int out); -int nouveau_gpio_sense(struct drm_device *, int idx, int line); -int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line, - struct gpio_func *); -int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state); -int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line); -int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); -void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask); -int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, - void (*)(void *, int state), void *data); -void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, - void (*)(void *, int state), void *data); - -static inline bool -nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) -{ - struct gpio_func func; - return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0; -} - -static inline int -nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) -{ - return nouveau_gpio_set(dev, 0, tag, 0xff, state); -} - -static inline int -nouveau_gpio_func_get(struct drm_device *dev, u8 tag) -{ - return nouveau_gpio_get(dev, 0, tag, 0xff); -} - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_hdmi.c b/trunk/drivers/gpu/drm/nouveau/nouveau_hdmi.c deleted file mode 100644 index 59ea1c14eca0..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_hdmi.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_connector.h" -#include "nouveau_encoder.h" -#include "nouveau_crtc.h" - -static bool -hdmi_sor(struct drm_encoder *encoder) -{ - struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; - if (dev_priv->chipset < 0xa3) - return false; - return true; -} - -static inline u32 -hdmi_base(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); - if (!hdmi_sor(encoder)) - return 0x616500 + (nv_crtc->index * 0x800); - return 0x61c500 + (nv_encoder->or * 0x800); -} - -static void -hdmi_wr32(struct drm_encoder *encoder, u32 reg, u32 val) -{ - nv_wr32(encoder->dev, hdmi_base(encoder) + reg, val); -} - -static u32 -hdmi_rd32(struct drm_encoder *encoder, u32 reg) -{ - return nv_rd32(encoder->dev, hdmi_base(encoder) + reg); -} - -static u32 -hdmi_mask(struct drm_encoder *encoder, u32 reg, u32 mask, u32 val) -{ - u32 tmp = hdmi_rd32(encoder, reg); - hdmi_wr32(encoder, reg, (tmp & ~mask) | val); - return tmp; -} - -static void -nouveau_audio_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; - u32 or = nv_encoder->or * 0x800; - - if (hdmi_sor(encoder)) { - nv_mask(dev, 0x61c448 + or, 0x00000003, 0x00000000); - } -} - -static void -nouveau_audio_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector; - struct drm_device *dev = encoder->dev; - u32 or = nv_encoder->or * 0x800; - int i; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (!drm_detect_monitor_audio(nv_connector->edid)) { - nouveau_audio_disconnect(encoder); - return; - } - - if (hdmi_sor(encoder)) { - nv_mask(dev, 0x61c448 + or, 0x00000001, 0x00000001); - - drm_edid_to_eld(&nv_connector->base, nv_connector->edid); - if (nv_connector->base.eld[0]) { - u8 *eld = nv_connector->base.eld; - for (i = 0; i < eld[2] * 4; i++) - nv_wr32(dev, 0x61c440 + or, (i << 8) | eld[i]); - for (i = eld[2] * 4; i < 0x60; i++) - nv_wr32(dev, 0x61c440 + or, (i << 8) | 0x00); - nv_mask(dev, 0x61c448 + or, 0x00000002, 0x00000002); - } - } -} - -static void -nouveau_hdmi_infoframe(struct drm_encoder *encoder, u32 ctrl, u8 *frame) -{ - /* calculate checksum for the infoframe */ - u8 sum = 0, i; - for (i = 0; i < frame[2]; i++) - sum += frame[i]; - frame[3] = 256 - sum; - - /* disable infoframe, and write header */ - hdmi_mask(encoder, ctrl + 0x00, 0x00000001, 0x00000000); - hdmi_wr32(encoder, ctrl + 0x08, *(u32 *)frame & 0xffffff); - - /* register scans tell me the audio infoframe has only one set of - * subpack regs, according to tegra (gee nvidia, it'd be nice if we - * could get those docs too!), the hdmi block pads out the rest of - * the packet on its own. - */ - if (ctrl == 0x020) - frame[2] = 6; - - /* write out checksum and data, weird weird 7 byte register pairs */ - for (i = 0; i < frame[2] + 1; i += 7) { - u32 rsubpack = ctrl + 0x0c + ((i / 7) * 8); - u32 *subpack = (u32 *)&frame[3 + i]; - hdmi_wr32(encoder, rsubpack + 0, subpack[0]); - hdmi_wr32(encoder, rsubpack + 4, subpack[1] & 0xffffff); - } - - /* enable the infoframe */ - hdmi_mask(encoder, ctrl, 0x00000001, 0x00000001); -} - -static void -nouveau_hdmi_video_infoframe(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - const u8 Y = 0, A = 0, B = 0, S = 0, C = 0, M = 0, R = 0; - const u8 ITC = 0, EC = 0, Q = 0, SC = 0, VIC = 0, PR = 0; - const u8 bar_top = 0, bar_bottom = 0, bar_left = 0, bar_right = 0; - u8 frame[20]; - - frame[0x00] = 0x82; /* AVI infoframe */ - frame[0x01] = 0x02; /* version */ - frame[0x02] = 0x0d; /* length */ - frame[0x03] = 0x00; - frame[0x04] = (Y << 5) | (A << 4) | (B << 2) | S; - frame[0x05] = (C << 6) | (M << 4) | R; - frame[0x06] = (ITC << 7) | (EC << 4) | (Q << 2) | SC; - frame[0x07] = VIC; - frame[0x08] = PR; - frame[0x09] = bar_top & 0xff; - frame[0x0a] = bar_top >> 8; - frame[0x0b] = bar_bottom & 0xff; - frame[0x0c] = bar_bottom >> 8; - frame[0x0d] = bar_left & 0xff; - frame[0x0e] = bar_left >> 8; - frame[0x0f] = bar_right & 0xff; - frame[0x10] = bar_right >> 8; - frame[0x11] = 0x00; - frame[0x12] = 0x00; - frame[0x13] = 0x00; - - nouveau_hdmi_infoframe(encoder, 0x020, frame); -} - -static void -nouveau_hdmi_audio_infoframe(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - const u8 CT = 0x00, CC = 0x01, ceaSS = 0x00, SF = 0x00, FMT = 0x00; - const u8 CA = 0x00, DM_INH = 0, LSV = 0x00; - u8 frame[12]; - - frame[0x00] = 0x84; /* Audio infoframe */ - frame[0x01] = 0x01; /* version */ - frame[0x02] = 0x0a; /* length */ - frame[0x03] = 0x00; - frame[0x04] = (CT << 4) | CC; - frame[0x05] = (SF << 2) | ceaSS; - frame[0x06] = FMT; - frame[0x07] = CA; - frame[0x08] = (DM_INH << 7) | (LSV << 3); - frame[0x09] = 0x00; - frame[0x0a] = 0x00; - frame[0x0b] = 0x00; - - nouveau_hdmi_infoframe(encoder, 0x000, frame); -} - -static void -nouveau_hdmi_disconnect(struct drm_encoder *encoder) -{ - nouveau_audio_disconnect(encoder); - - /* disable audio and avi infoframes */ - hdmi_mask(encoder, 0x000, 0x00000001, 0x00000000); - hdmi_mask(encoder, 0x020, 0x00000001, 0x00000000); - - /* disable hdmi */ - hdmi_mask(encoder, 0x0a4, 0x40000000, 0x00000000); -} - -void -nouveau_hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector; - struct drm_device *dev = encoder->dev; - u32 max_ac_packet, rekey; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (!mode || !nv_connector || !nv_connector->edid || - !drm_detect_hdmi_monitor(nv_connector->edid)) { - nouveau_hdmi_disconnect(encoder); - return; - } - - nouveau_hdmi_video_infoframe(encoder, mode); - nouveau_hdmi_audio_infoframe(encoder, mode); - - hdmi_mask(encoder, 0x0d0, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - hdmi_mask(encoder, 0x068, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - hdmi_mask(encoder, 0x078, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - nv_mask(dev, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nv_mask(dev, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nv_mask(dev, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* value matches nvidia binary driver, and tegra constant */ - rekey = 56; - - max_ac_packet = mode->htotal - mode->hdisplay; - max_ac_packet -= rekey; - max_ac_packet -= 18; /* constant from tegra */ - max_ac_packet /= 32; - - /* enable hdmi */ - hdmi_mask(encoder, 0x0a4, 0x5f1f003f, 0x40000000 | /* enable */ - 0x1f000000 | /* unknown */ - max_ac_packet << 16 | - rekey); - - nouveau_audio_mode_set(encoder, mode); -} diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_hwsq.h b/trunk/drivers/gpu/drm/nouveau/nouveau_hwsq.h deleted file mode 100644 index 697687593a81..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_hwsq.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2010 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#ifndef __NOUVEAU_HWSQ_H__ -#define __NOUVEAU_HWSQ_H__ - -struct hwsq_ucode { - u8 data[0x200]; - union { - u8 *u08; - u16 *u16; - u32 *u32; - } ptr; - u16 len; - - u32 reg; - u32 val; -}; - -static inline void -hwsq_init(struct hwsq_ucode *hwsq) -{ - hwsq->ptr.u08 = hwsq->data; - hwsq->reg = 0xffffffff; - hwsq->val = 0xffffffff; -} - -static inline void -hwsq_fini(struct hwsq_ucode *hwsq) -{ - do { - *hwsq->ptr.u08++ = 0x7f; - hwsq->len = hwsq->ptr.u08 - hwsq->data; - } while (hwsq->len & 3); - hwsq->ptr.u08 = hwsq->data; -} - -static inline void -hwsq_usec(struct hwsq_ucode *hwsq, u8 usec) -{ - u32 shift = 0; - while (usec & ~3) { - usec >>= 2; - shift++; - } - - *hwsq->ptr.u08++ = (shift << 2) | usec; -} - -static inline void -hwsq_setf(struct hwsq_ucode *hwsq, u8 flag, int val) -{ - flag += 0x80; - if (val >= 0) - flag += 0x20; - if (val >= 1) - flag += 0x20; - *hwsq->ptr.u08++ = flag; -} - -static inline void -hwsq_op5f(struct hwsq_ucode *hwsq, u8 v0, u8 v1) -{ - *hwsq->ptr.u08++ = 0x5f; - *hwsq->ptr.u08++ = v0; - *hwsq->ptr.u08++ = v1; -} - -static inline void -hwsq_wr32(struct hwsq_ucode *hwsq, u32 reg, u32 val) -{ - if (val != hwsq->val) { - if ((val & 0xffff0000) == (hwsq->val & 0xffff0000)) { - *hwsq->ptr.u08++ = 0x42; - *hwsq->ptr.u16++ = (val & 0x0000ffff); - } else { - *hwsq->ptr.u08++ = 0xe2; - *hwsq->ptr.u32++ = val; - } - - hwsq->val = val; - } - - if ((reg & 0xffff0000) == (hwsq->reg & 0xffff0000)) { - *hwsq->ptr.u08++ = 0x40; - *hwsq->ptr.u16++ = (reg & 0x0000ffff); - } else { - *hwsq->ptr.u08++ = 0xe0; - *hwsq->ptr.u32++ = reg; - } - hwsq->reg = reg; -} - -#endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c b/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c index 820ae7f52044..d39b2202b197 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.c @@ -29,465 +29,262 @@ #include "nouveau_i2c.h" #include "nouveau_hw.h" -#define T_TIMEOUT 2200000 -#define T_RISEFALL 1000 -#define T_HOLD 5000 - static void -i2c_drive_scl(void *data, int state) +nv04_i2c_setscl(void *data, int state) { - struct nouveau_i2c_chan *port = data; - if (port->type == 0) { - u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); - if (state) val |= 0x20; - else val &= 0xdf; - NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); - } else - if (port->type == 4) { - nv_mask(port->dev, port->drive, 0x2f, state ? 0x21 : 0x01); - } else - if (port->type == 5) { - if (state) port->state |= 0x01; - else port->state &= 0xfe; - nv_wr32(port->dev, port->drive, 4 | port->state); - } + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; + + val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xd0) | (state ? 0x20 : 0); + NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); } static void -i2c_drive_sda(void *data, int state) +nv04_i2c_setsda(void *data, int state) { - struct nouveau_i2c_chan *port = data; - if (port->type == 0) { - u8 val = NVReadVgaCrtc(port->dev, 0, port->drive); - if (state) val |= 0x10; - else val &= 0xef; - NVWriteVgaCrtc(port->dev, 0, port->drive, val | 0x01); - } else - if (port->type == 4) { - nv_mask(port->dev, port->drive, 0x1f, state ? 0x11 : 0x01); - } else - if (port->type == 5) { - if (state) port->state |= 0x02; - else port->state &= 0xfd; - nv_wr32(port->dev, port->drive, 4 | port->state); - } -} + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; -static int -i2c_sense_scl(void *data) -{ - struct nouveau_i2c_chan *port = data; - struct drm_nouveau_private *dev_priv = port->dev->dev_private; - if (port->type == 0) { - return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x04); - } else - if (port->type == 4) { - return !!(nv_rd32(port->dev, port->sense) & 0x00040000); - } else - if (port->type == 5) { - if (dev_priv->card_type < NV_D0) - return !!(nv_rd32(port->dev, port->sense) & 0x01); - else - return !!(nv_rd32(port->dev, port->sense) & 0x10); - } - return 0; + val = (NVReadVgaCrtc(dev, 0, i2c->wr) & 0xe0) | (state ? 0x10 : 0); + NVWriteVgaCrtc(dev, 0, i2c->wr, val | 0x01); } static int -i2c_sense_sda(void *data) +nv04_i2c_getscl(void *data) { - struct nouveau_i2c_chan *port = data; - struct drm_nouveau_private *dev_priv = port->dev->dev_private; - if (port->type == 0) { - return !!(NVReadVgaCrtc(port->dev, 0, port->sense) & 0x08); - } else - if (port->type == 4) { - return !!(nv_rd32(port->dev, port->sense) & 0x00080000); - } else - if (port->type == 5) { - if (dev_priv->card_type < NV_D0) - return !!(nv_rd32(port->dev, port->sense) & 0x02); - else - return !!(nv_rd32(port->dev, port->sense) & 0x20); - } - return 0; -} + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; -static void -i2c_delay(struct nouveau_i2c_chan *port, u32 nsec) -{ - udelay((nsec + 500) / 1000); + return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 4); } -static bool -i2c_raise_scl(struct nouveau_i2c_chan *port) +static int +nv04_i2c_getsda(void *data) { - u32 timeout = T_TIMEOUT / T_RISEFALL; - - i2c_drive_scl(port, 1); - do { - i2c_delay(port, T_RISEFALL); - } while (!i2c_sense_scl(port) && --timeout); + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; - return timeout != 0; + return !!(NVReadVgaCrtc(dev, 0, i2c->rd) & 8); } -static int -i2c_start(struct nouveau_i2c_chan *port) +static void +nv4e_i2c_setscl(void *data, int state) { - int ret = 0; - - port->state = i2c_sense_scl(port); - port->state |= i2c_sense_sda(port) << 1; - if (port->state != 3) { - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 1); - if (!i2c_raise_scl(port)) - ret = -EBUSY; - } + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; - i2c_drive_sda(port, 0); - i2c_delay(port, T_HOLD); - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); - return ret; + val = (nv_rd32(dev, i2c->wr) & 0xd0) | (state ? 0x20 : 0); + nv_wr32(dev, i2c->wr, val | 0x01); } static void -i2c_stop(struct nouveau_i2c_chan *port) +nv4e_i2c_setsda(void *data, int state) { - i2c_drive_scl(port, 0); - i2c_drive_sda(port, 0); - i2c_delay(port, T_RISEFALL); - - i2c_drive_scl(port, 1); - i2c_delay(port, T_HOLD); - i2c_drive_sda(port, 1); - i2c_delay(port, T_HOLD); + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; + uint8_t val; + + val = (nv_rd32(dev, i2c->wr) & 0xe0) | (state ? 0x10 : 0); + nv_wr32(dev, i2c->wr, val | 0x01); } static int -i2c_bitw(struct nouveau_i2c_chan *port, int sda) +nv4e_i2c_getscl(void *data) { - i2c_drive_sda(port, sda); - i2c_delay(port, T_RISEFALL); + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; - if (!i2c_raise_scl(port)) - return -ETIMEDOUT; - i2c_delay(port, T_HOLD); - - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); - return 0; + return !!((nv_rd32(dev, i2c->rd) >> 16) & 4); } static int -i2c_bitr(struct nouveau_i2c_chan *port) +nv4e_i2c_getsda(void *data) { - int sda; + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; - i2c_drive_sda(port, 1); - i2c_delay(port, T_RISEFALL); - - if (!i2c_raise_scl(port)) - return -ETIMEDOUT; - i2c_delay(port, T_HOLD); - - sda = i2c_sense_sda(port); - - i2c_drive_scl(port, 0); - i2c_delay(port, T_HOLD); - return sda; + return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); } +static const uint32_t nv50_i2c_port[] = { + 0x00e138, 0x00e150, 0x00e168, 0x00e180, + 0x00e254, 0x00e274, 0x00e764, 0x00e780, + 0x00e79c, 0x00e7b8 +}; +#define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) + static int -i2c_get_byte(struct nouveau_i2c_chan *port, u8 *byte, bool last) +nv50_i2c_getscl(void *data) { - int i, bit; - - *byte = 0; - for (i = 7; i >= 0; i--) { - bit = i2c_bitr(port); - if (bit < 0) - return bit; - *byte |= bit << i; - } + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; - return i2c_bitw(port, last ? 1 : 0); + return !!(nv_rd32(dev, i2c->rd) & 1); } + static int -i2c_put_byte(struct nouveau_i2c_chan *port, u8 byte) +nv50_i2c_getsda(void *data) { - int i, ret; - for (i = 7; i >= 0; i--) { - ret = i2c_bitw(port, !!(byte & (1 << i))); - if (ret < 0) - return ret; - } + struct nouveau_i2c_chan *i2c = data; + struct drm_device *dev = i2c->dev; - ret = i2c_bitr(port); - if (ret == 1) /* nack */ - ret = -EIO; - return ret; + return !!(nv_rd32(dev, i2c->rd) & 2); } -static int -i2c_addr(struct nouveau_i2c_chan *port, struct i2c_msg *msg) +static void +nv50_i2c_setscl(void *data, int state) { - u32 addr = msg->addr << 1; - if (msg->flags & I2C_M_RD) - addr |= 1; - return i2c_put_byte(port, addr); + struct nouveau_i2c_chan *i2c = data; + + nv_wr32(i2c->dev, i2c->wr, 4 | (i2c->data ? 2 : 0) | (state ? 1 : 0)); } -static int -i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) +static void +nv50_i2c_setsda(void *data, int state) { - struct nouveau_i2c_chan *port = (struct nouveau_i2c_chan *)adap; - struct i2c_msg *msg = msgs; - int ret = 0, mcnt = num; - - while (!ret && mcnt--) { - u8 remaining = msg->len; - u8 *ptr = msg->buf; - - ret = i2c_start(port); - if (ret == 0) - ret = i2c_addr(port, msg); - - if (msg->flags & I2C_M_RD) { - while (!ret && remaining--) - ret = i2c_get_byte(port, ptr++, !remaining); - } else { - while (!ret && remaining--) - ret = i2c_put_byte(port, *ptr++); - } + struct nouveau_i2c_chan *i2c = data; - msg++; - } - - i2c_stop(port); - return (ret < 0) ? ret : num; + nv_mask(i2c->dev, i2c->wr, 0x00000006, 4 | (state ? 2 : 0)); + i2c->data = state; } -static u32 -i2c_bit_func(struct i2c_adapter *adap) +static int +nvd0_i2c_getscl(void *data) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + struct nouveau_i2c_chan *i2c = data; + return !!(nv_rd32(i2c->dev, i2c->rd) & 0x10); } -const struct i2c_algorithm i2c_bit_algo = { - .master_xfer = i2c_bit_xfer, - .functionality = i2c_bit_func -}; - -static const uint32_t nv50_i2c_port[] = { - 0x00e138, 0x00e150, 0x00e168, 0x00e180, - 0x00e254, 0x00e274, 0x00e764, 0x00e780, - 0x00e79c, 0x00e7b8 -}; - -static u8 * -i2c_table(struct drm_device *dev, u8 *version) +static int +nvd0_i2c_getsda(void *data) { - u8 *dcb = dcb_table(dev), *i2c = NULL; - if (dcb) { - if (dcb[0] >= 0x15) - i2c = ROMPTR(dev, dcb[2]); - if (dcb[0] >= 0x30) - i2c = ROMPTR(dev, dcb[4]); - } - - /* early revisions had no version number, use dcb version */ - if (i2c) { - *version = dcb[0]; - if (*version >= 0x30) - *version = i2c[0]; - } - - return i2c; + struct nouveau_i2c_chan *i2c = data; + return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); } int -nouveau_i2c_init(struct drm_device *dev) +nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvbios *bios = &dev_priv->vbios; - struct nouveau_i2c_chan *port; - u8 *i2c, *entry, legacy[2][4] = {}; - u8 version, entries, recordlen; - int ret, i; - - INIT_LIST_HEAD(&dev_priv->i2c_ports); - - i2c = i2c_table(dev, &version); - if (!i2c) { - u8 *bmp = &bios->data[bios->offset]; - if (bios->type != NVBIOS_BMP) - return -ENODEV; - - legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX; - legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX; - legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX; - legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX; - - /* BMP (from v4.0) has i2c info in the structure, it's in a - * fixed location on earlier VBIOS - */ - if (bmp[5] < 4) - i2c = &bios->data[0x48]; - else - i2c = &bmp[0x36]; - - if (i2c[4]) legacy[0][0] = i2c[4]; - if (i2c[5]) legacy[0][1] = i2c[5]; - if (i2c[6]) legacy[1][0] = i2c[6]; - if (i2c[7]) legacy[1][1] = i2c[7]; - } + struct nouveau_i2c_chan *i2c; + int ret; - if (i2c && version >= 0x30) { - entry = i2c[1] + i2c; - entries = i2c[2]; - recordlen = i2c[3]; - } else - if (i2c) { - entry = i2c; - entries = 16; - recordlen = 4; - } else { - entry = legacy[0]; - entries = 2; - recordlen = 4; - } + if (entry->chan) + return -EEXIST; - for (i = 0; i < entries; i++, entry += recordlen) { - port = kzalloc(sizeof(*port), GFP_KERNEL); - if (port == NULL) { - nouveau_i2c_fini(dev); - return -ENOMEM; - } - - port->type = entry[3]; - if (version < 0x30) { - port->type &= 0x07; - if (port->type == 0x07) - port->type = 0xff; - } - - if (port->type == 0xff) { - kfree(port); - continue; - } - - switch (port->type) { - case 0: /* NV04:NV50 */ - port->drive = entry[0]; - port->sense = entry[1]; - port->adapter.algo = &i2c_bit_algo; - break; - case 4: /* NV4E */ - port->drive = 0x600800 + entry[1]; - port->sense = port->drive; - port->adapter.algo = &i2c_bit_algo; - break; - case 5: /* NV50- */ - port->drive = entry[0] & 0x0f; - if (dev_priv->card_type < NV_D0) { - if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) - break; - port->drive = nv50_i2c_port[port->drive]; - port->sense = port->drive; - } else { - port->drive = 0x00d014 + (port->drive * 0x20); - port->sense = port->drive; - } - port->adapter.algo = &i2c_bit_algo; - break; - case 6: /* NV50- DP AUX */ - port->drive = entry[0]; - port->sense = port->drive; - port->adapter.algo = &nouveau_dp_i2c_algo; - break; - default: - break; - } + if (dev_priv->card_type >= NV_50 && + dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { + NV_ERROR(dev, "unknown i2c port %d\n", entry->read); + return -EINVAL; + } - if (!port->adapter.algo) { - NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", - i, port->type, port->drive, port->sense); - kfree(port); - continue; + i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); + if (i2c == NULL) + return -ENOMEM; + + switch (entry->port_type) { + case 0: + i2c->bit.setsda = nv04_i2c_setsda; + i2c->bit.setscl = nv04_i2c_setscl; + i2c->bit.getsda = nv04_i2c_getsda; + i2c->bit.getscl = nv04_i2c_getscl; + i2c->rd = entry->read; + i2c->wr = entry->write; + break; + case 4: + i2c->bit.setsda = nv4e_i2c_setsda; + i2c->bit.setscl = nv4e_i2c_setscl; + i2c->bit.getsda = nv4e_i2c_getsda; + i2c->bit.getscl = nv4e_i2c_getscl; + i2c->rd = 0x600800 + entry->read; + i2c->wr = 0x600800 + entry->write; + break; + case 5: + i2c->bit.setsda = nv50_i2c_setsda; + i2c->bit.setscl = nv50_i2c_setscl; + if (dev_priv->card_type < NV_D0) { + i2c->bit.getsda = nv50_i2c_getsda; + i2c->bit.getscl = nv50_i2c_getscl; + i2c->rd = nv50_i2c_port[entry->read]; + i2c->wr = i2c->rd; + } else { + i2c->bit.getsda = nvd0_i2c_getsda; + i2c->bit.getscl = nvd0_i2c_getscl; + i2c->rd = 0x00d014 + (entry->read * 0x20); + i2c->wr = i2c->rd; } + break; + case 6: + i2c->rd = entry->read; + i2c->wr = entry->write; + break; + default: + NV_ERROR(dev, "DCB I2C port type %d unknown\n", + entry->port_type); + kfree(i2c); + return -EINVAL; + } - snprintf(port->adapter.name, sizeof(port->adapter.name), - "nouveau-%s-%d", pci_name(dev->pdev), i); - port->adapter.owner = THIS_MODULE; - port->adapter.dev.parent = &dev->pdev->dev; - port->dev = dev; - port->index = i; - port->dcb = ROM32(entry[0]); - i2c_set_adapdata(&port->adapter, i2c); - - ret = i2c_add_adapter(&port->adapter); - if (ret) { - NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); - kfree(port); - continue; - } + snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), + "nouveau-%s-%d", pci_name(dev->pdev), index); + i2c->adapter.owner = THIS_MODULE; + i2c->adapter.dev.parent = &dev->pdev->dev; + i2c->dev = dev; + i2c_set_adapdata(&i2c->adapter, i2c); + + if (entry->port_type < 6) { + i2c->adapter.algo_data = &i2c->bit; + i2c->bit.udelay = 40; + i2c->bit.timeout = usecs_to_jiffies(5000); + i2c->bit.data = i2c; + ret = i2c_bit_add_bus(&i2c->adapter); + } else { + i2c->adapter.algo = &nouveau_dp_i2c_algo; + ret = i2c_add_adapter(&i2c->adapter); + } - list_add_tail(&port->head, &dev_priv->i2c_ports); + if (ret) { + NV_ERROR(dev, "Failed to register i2c %d\n", index); + kfree(i2c); + return ret; } + entry->chan = i2c; return 0; } void -nouveau_i2c_fini(struct drm_device *dev) +nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *port, *tmp; + if (!entry->chan) + return; - list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) { - i2c_del_adapter(&port->adapter); - kfree(port); - } + i2c_del_adapter(&entry->chan->adapter); + kfree(entry->chan); + entry->chan = NULL; } struct nouveau_i2c_chan * -nouveau_i2c_find(struct drm_device *dev, u8 index) +nouveau_i2c_find(struct drm_device *dev, int index) { struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *port; - - if (index == NV_I2C_DEFAULT(0) || - index == NV_I2C_DEFAULT(1)) { - u8 version, *i2c = i2c_table(dev, &version); - if (i2c && version >= 0x30) { - if (index == NV_I2C_DEFAULT(0)) - index = (i2c[4] & 0x0f); - else - index = (i2c[4] & 0xf0) >> 4; - } else { - index = 2; - } - } - - list_for_each_entry(port, &dev_priv->i2c_ports, head) { - if (port->index == index) - break; - } + struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index]; - if (&port->head == &dev_priv->i2c_ports) + if (index >= DCB_MAX_NUM_I2C_ENTRIES) return NULL; - if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { - u32 reg = 0x00e500, val; - if (port->type == 6) { - reg += port->drive * 0x50; + if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) { + uint32_t reg = 0xe500, val; + + if (i2c->port_type == 6) { + reg += i2c->read * 0x50; val = 0x2002; } else { - reg += ((port->dcb & 0x1e00) >> 9) * 0x50; + reg += ((i2c->entry & 0x1e00) >> 9) * 0x50; val = 0xe001; } @@ -497,7 +294,9 @@ nouveau_i2c_find(struct drm_device *dev, u8 index) nv_mask(dev, reg + 0x00, 0x0000f003, val); } - return port; + if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) + return NULL; + return i2c->chan; } bool @@ -532,13 +331,9 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, index); int i; - if (!i2c) { - NV_DEBUG(dev, "No bus when probing %s on %d\n", what, index); - return -ENODEV; - } + NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, index); - NV_DEBUG(dev, "Probing %ss on I2C bus: %d\n", what, i2c->index); - for (i = 0; info[i].addr; i++) { + for (i = 0; i2c && info[i].addr; i++) { if (nouveau_probe_i2c_addr(i2c, info[i].addr) && (!match || match(i2c, &info[i]))) { NV_INFO(dev, "Detected %s: %s\n", what, info[i].type); @@ -547,5 +342,6 @@ nouveau_i2c_identify(struct drm_device *dev, const char *what, } NV_DEBUG(dev, "No devices found.\n"); + return -ENODEV; } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.h b/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.h index 4d2e4e9031be..422b62fd8272 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_i2c.h @@ -27,25 +27,20 @@ #include #include "drm_dp_helper.h" -#define NV_I2C_PORT(n) (0x00 + (n)) -#define NV_I2C_PORT_NUM 0x10 -#define NV_I2C_DEFAULT(n) (0x80 + (n)) +struct dcb_i2c_entry; struct nouveau_i2c_chan { struct i2c_adapter adapter; struct drm_device *dev; - struct list_head head; - u8 index; - u8 type; - u32 dcb; - u32 drive; - u32 sense; - u32 state; + struct i2c_algo_bit_data bit; + unsigned rd; + unsigned wr; + unsigned data; }; -int nouveau_i2c_init(struct drm_device *); -void nouveau_i2c_fini(struct drm_device *); -struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index); +int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); +void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); +struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); int nouveau_i2c_identify(struct drm_device *dev, const char *what, struct i2c_board_info *info, diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c b/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c index c3a5745e9c79..37fcaa260e98 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -644,10 +644,10 @@ nouveau_mem_timing_init(struct drm_device *dev) return; if (P.version == 1) - hdr = (struct nouveau_pm_tbl_header *) ROMPTR(dev, P.data[4]); + hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[4]); else if (P.version == 2) - hdr = (struct nouveau_pm_tbl_header *) ROMPTR(dev, P.data[8]); + hdr = (struct nouveau_pm_tbl_header *) ROMPTR(bios, P.data[8]); else { NV_WARN(dev, "unknown mem for BIT P %d\n", P.version); } diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_mxm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_mxm.c deleted file mode 100644 index 8bccddf4eff0..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_mxm.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include - -#include "drmP.h" -#include "nouveau_drv.h" - -#define MXM_DBG(dev, fmt, args...) NV_DEBUG((dev), "MXM: " fmt, ##args) -#define MXM_MSG(dev, fmt, args...) NV_INFO((dev), "MXM: " fmt, ##args) - -static u8 * -mxms_data(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - return dev_priv->mxms; - -} - -static u16 -mxms_version(struct drm_device *dev) -{ - u8 *mxms = mxms_data(dev); - u16 version = (mxms[4] << 8) | mxms[5]; - switch (version ) { - case 0x0200: - case 0x0201: - case 0x0300: - return version; - default: - break; - } - - MXM_DBG(dev, "unknown version %d.%d\n", mxms[4], mxms[5]); - return 0x0000; -} - -static u16 -mxms_headerlen(struct drm_device *dev) -{ - return 8; -} - -static u16 -mxms_structlen(struct drm_device *dev) -{ - return *(u16 *)&mxms_data(dev)[6]; -} - -static bool -mxms_checksum(struct drm_device *dev) -{ - u16 size = mxms_headerlen(dev) + mxms_structlen(dev); - u8 *mxms = mxms_data(dev), sum = 0; - while (size--) - sum += *mxms++; - if (sum) { - MXM_DBG(dev, "checksum invalid\n"); - return false; - } - return true; -} - -static bool -mxms_valid(struct drm_device *dev) -{ - u8 *mxms = mxms_data(dev); - if (*(u32 *)mxms != 0x5f4d584d) { - MXM_DBG(dev, "signature invalid\n"); - return false; - } - - if (!mxms_version(dev) || !mxms_checksum(dev)) - return false; - - return true; -} - -static bool -mxms_foreach(struct drm_device *dev, u8 types, - bool (*exec)(struct drm_device *, u8 *, void *), void *info) -{ - u8 *mxms = mxms_data(dev); - u8 *desc = mxms + mxms_headerlen(dev); - u8 *fini = desc + mxms_structlen(dev) - 1; - while (desc < fini) { - u8 type = desc[0] & 0x0f; - u8 headerlen = 0; - u8 recordlen = 0; - u8 entries = 0; - - switch (type) { - case 0: /* Output Device Structure */ - if (mxms_version(dev) >= 0x0300) - headerlen = 8; - else - headerlen = 6; - break; - case 1: /* System Cooling Capability Structure */ - case 2: /* Thermal Structure */ - case 3: /* Input Power Structure */ - headerlen = 4; - break; - case 4: /* GPIO Device Structure */ - headerlen = 4; - recordlen = 2; - entries = (ROM32(desc[0]) & 0x01f00000) >> 20; - break; - case 5: /* Vendor Specific Structure */ - headerlen = 8; - break; - case 6: /* Backlight Control Structure */ - if (mxms_version(dev) >= 0x0300) { - headerlen = 4; - recordlen = 8; - entries = (desc[1] & 0xf0) >> 4; - } else { - headerlen = 8; - } - break; - case 7: /* Fan Control Structure */ - headerlen = 8; - recordlen = 4; - entries = desc[1] & 0x07; - break; - default: - MXM_DBG(dev, "unknown descriptor type %d\n", type); - return false; - } - - if ((drm_debug & DRM_UT_DRIVER) && (exec == NULL)) { - static const char * mxms_desc_name[] = { - "ODS", "SCCS", "TS", "IPS", - "GSD", "VSS", "BCS", "FCS", - }; - u8 *dump = desc; - int i, j; - - MXM_DBG(dev, "%4s: ", mxms_desc_name[type]); - for (j = headerlen - 1; j >= 0; j--) - printk("%02x", dump[j]); - printk("\n"); - dump += headerlen; - - for (i = 0; i < entries; i++, dump += recordlen) { - MXM_DBG(dev, " "); - for (j = recordlen - 1; j >= 0; j--) - printk("%02x", dump[j]); - printk("\n"); - } - } - - if (types & (1 << type)) { - if (!exec(dev, desc, info)) - return false; - } - - desc += headerlen + (entries * recordlen); - } - - return true; -} - -static u8 * -mxm_table(struct drm_device *dev, u8 *size) -{ - struct bit_entry x; - - if (bit_table(dev, 'x', &x)) { - MXM_DBG(dev, "BIT 'x' table not present\n"); - return NULL; - } - - if (x.version != 1 || x.length < 3) { - MXM_MSG(dev, "BIT x table %d/%d unknown\n", - x.version, x.length); - return NULL; - } - - *size = x.length; - return x.data; -} - -/* These map MXM v2.x digital connection values to the appropriate SOR/link, - * hopefully they're correct for all boards within the same chipset... - * - * MXM v3.x VBIOS are nicer and provide pointers to these tables. - */ -static u8 nv84_sor_map[16] = { - 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static u8 nv92_sor_map[16] = { - 0x00, 0x12, 0x22, 0x11, 0x32, 0x31, 0x11, 0x31, - 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static u8 nv94_sor_map[16] = { - 0x00, 0x14, 0x24, 0x11, 0x34, 0x31, 0x11, 0x31, - 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static u8 nv96_sor_map[16] = { - 0x00, 0x14, 0x24, 0x00, 0x34, 0x00, 0x11, 0x31, - 0x11, 0x31, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static u8 nv98_sor_map[16] = { - 0x00, 0x14, 0x12, 0x11, 0x00, 0x31, 0x11, 0x31, - 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static u8 -mxm_sor_map(struct drm_device *dev, u8 conn) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u8 len, *mxm = mxm_table(dev, &len); - if (mxm && len >= 6) { - u8 *map = ROMPTR(dev, mxm[4]); - if (map) { - if (map[0] == 0x10) { - if (conn < map[3]) - return map[map[1] + conn]; - return 0x00; - } - - MXM_MSG(dev, "unknown sor map 0x%02x\n", map[0]); - } - } - - if (dev_priv->chipset == 0x84 || dev_priv->chipset == 0x86) - return nv84_sor_map[conn]; - if (dev_priv->chipset == 0x92) - return nv92_sor_map[conn]; - if (dev_priv->chipset == 0x94) - return nv94_sor_map[conn]; - if (dev_priv->chipset == 0x96) - return nv96_sor_map[conn]; - if (dev_priv->chipset == 0x98) - return nv98_sor_map[conn]; - - MXM_MSG(dev, "missing sor map\n"); - return 0x00; -} - -static u8 -mxm_ddc_map(struct drm_device *dev, u8 port) -{ - u8 len, *mxm = mxm_table(dev, &len); - if (mxm && len >= 8) { - u8 *map = ROMPTR(dev, mxm[6]); - if (map) { - if (map[0] == 0x10) { - if (port < map[3]) - return map[map[1] + port]; - return 0x00; - } - - MXM_MSG(dev, "unknown ddc map 0x%02x\n", map[0]); - } - } - - /* v2.x: directly write port as dcb i2cidx */ - return (port << 4) | port; -} - -struct mxms_odev { - u8 outp_type; - u8 conn_type; - u8 ddc_port; - u8 dig_conn; -}; - -static void -mxms_output_device(struct drm_device *dev, u8 *pdata, struct mxms_odev *desc) -{ - u64 data = ROM32(pdata[0]); - if (mxms_version(dev) >= 0x0300) - data |= (u64)ROM16(pdata[4]) << 32; - - desc->outp_type = (data & 0x00000000000000f0ULL) >> 4; - desc->ddc_port = (data & 0x0000000000000f00ULL) >> 8; - desc->conn_type = (data & 0x000000000001f000ULL) >> 12; - desc->dig_conn = (data & 0x0000000000780000ULL) >> 19; -} - -struct context { - u32 *outp; - struct mxms_odev desc; -}; - -static bool -mxm_match_tmds_partner(struct drm_device *dev, u8 *data, void *info) -{ - struct context *ctx = info; - struct mxms_odev desc; - - mxms_output_device(dev, data, &desc); - if (desc.outp_type == 2 && - desc.dig_conn == ctx->desc.dig_conn) - return false; - return true; -} - -static bool -mxm_match_dcb(struct drm_device *dev, u8 *data, void *info) -{ - struct context *ctx = info; - u64 desc = *(u64 *)data; - - mxms_output_device(dev, data, &ctx->desc); - - /* match dcb encoder type to mxm-ods device type */ - if ((ctx->outp[0] & 0x0000000f) != ctx->desc.outp_type) - return true; - - /* digital output, have some extra stuff to match here, there's a - * table in the vbios that provides a mapping from the mxm digital - * connection enum values to SOR/link - */ - if ((desc & 0x00000000000000f0) >= 0x20) { - /* check against sor index */ - u8 link = mxm_sor_map(dev, ctx->desc.dig_conn); - if ((ctx->outp[0] & 0x0f000000) != (link & 0x0f) << 24) - return true; - - /* check dcb entry has a compatible link field */ - link = (link & 0x30) >> 4; - if ((link & ((ctx->outp[1] & 0x00000030) >> 4)) != link) - return true; - } - - /* mark this descriptor accounted for by setting invalid device type, - * except of course some manufactures don't follow specs properly and - * we need to avoid killing off the TMDS function on DP connectors - * if MXM-SIS is missing an entry for it. - */ - data[0] &= ~0xf0; - if (ctx->desc.outp_type == 6 && ctx->desc.conn_type == 6 && - mxms_foreach(dev, 0x01, mxm_match_tmds_partner, ctx)) { - data[0] |= 0x20; /* modify descriptor to match TMDS now */ - } else { - data[0] |= 0xf0; - } - - return false; -} - -static int -mxm_dcb_sanitise_entry(struct drm_device *dev, void *data, int idx, u8 *dcbe) -{ - struct context ctx = { .outp = (u32 *)dcbe }; - u8 type, i2cidx, link; - u8 *conn; - - /* look for an output device structure that matches this dcb entry. - * if one isn't found, disable it. - */ - if (mxms_foreach(dev, 0x01, mxm_match_dcb, &ctx)) { - MXM_DBG(dev, "disable %d: 0x%08x 0x%08x\n", - idx, ctx.outp[0], ctx.outp[1]); - ctx.outp[0] |= 0x0000000f; - return 0; - } - - /* modify the output's ddc/aux port, there's a pointer to a table - * with the mapping from mxm ddc/aux port to dcb i2c_index in the - * vbios mxm table - */ - i2cidx = mxm_ddc_map(dev, ctx.desc.ddc_port); - if ((ctx.outp[0] & 0x0000000f) != OUTPUT_DP) - i2cidx = (i2cidx & 0x0f) << 4; - else - i2cidx = (i2cidx & 0xf0); - - if (i2cidx != 0xf0) { - ctx.outp[0] &= ~0x000000f0; - ctx.outp[0] |= i2cidx; - } - - /* override dcb sorconf.link, based on what mxm data says */ - switch (ctx.desc.outp_type) { - case 0x00: /* Analog CRT */ - case 0x01: /* Analog TV/HDTV */ - break; - default: - link = mxm_sor_map(dev, ctx.desc.dig_conn) & 0x30; - ctx.outp[1] &= ~0x00000030; - ctx.outp[1] |= link; - break; - } - - /* we may need to fixup various other vbios tables based on what - * the descriptor says the connector type should be. - * - * in a lot of cases, the vbios tables will claim DVI-I is possible, - * and the mxm data says the connector is really HDMI. another - * common example is DP->eDP. - */ - conn = dcb_conn(dev, (ctx.outp[0] & 0x0000f000) >> 12); - type = conn[0]; - switch (ctx.desc.conn_type) { - case 0x01: /* LVDS */ - ctx.outp[1] |= 0x00000004; /* use_power_scripts */ - /* XXX: modify default link width in LVDS table */ - break; - case 0x02: /* HDMI */ - type = DCB_CONNECTOR_HDMI_1; - break; - case 0x03: /* DVI-D */ - type = DCB_CONNECTOR_DVI_D; - break; - case 0x0e: /* eDP, falls through to DPint */ - ctx.outp[1] |= 0x00010000; - case 0x07: /* DP internal, wtf is this?? HP8670w */ - ctx.outp[1] |= 0x00000004; /* use_power_scripts? */ - type = DCB_CONNECTOR_eDP; - break; - default: - break; - } - - if (mxms_version(dev) >= 0x0300) - conn[0] = type; - - return 0; -} - -static bool -mxm_show_unmatched(struct drm_device *dev, u8 *data, void *info) -{ - u64 desc = *(u64 *)data; - if ((desc & 0xf0) != 0xf0) - MXM_MSG(dev, "unmatched output device 0x%016llx\n", desc); - return true; -} - -static void -mxm_dcb_sanitise(struct drm_device *dev) -{ - u8 *dcb = dcb_table(dev); - if (!dcb || dcb[0] != 0x40) { - MXM_DBG(dev, "unsupported DCB version\n"); - return; - } - - dcb_outp_foreach(dev, NULL, mxm_dcb_sanitise_entry); - mxms_foreach(dev, 0x01, mxm_show_unmatched, NULL); -} - -static bool -mxm_shadow_rom_fetch(struct nouveau_i2c_chan *i2c, u8 addr, - u8 offset, u8 size, u8 *data) -{ - struct i2c_msg msgs[] = { - { .addr = addr, .flags = 0, .len = 1, .buf = &offset }, - { .addr = addr, .flags = I2C_M_RD, .len = size, .buf = data, }, - }; - - return i2c_transfer(&i2c->adapter, msgs, 2) == 2; -} - -static bool -mxm_shadow_rom(struct drm_device *dev, u8 version) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_i2c_chan *i2c = NULL; - u8 i2cidx, mxms[6], addr, size; - - i2cidx = mxm_ddc_map(dev, 1 /* LVDS_DDC */) & 0x0f; - if (i2cidx < 0x0f) - i2c = nouveau_i2c_find(dev, i2cidx); - if (!i2c) - return false; - - addr = 0x54; - if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) { - addr = 0x56; - if (!mxm_shadow_rom_fetch(i2c, addr, 0, 6, mxms)) - return false; - } - - dev_priv->mxms = mxms; - size = mxms_headerlen(dev) + mxms_structlen(dev); - dev_priv->mxms = kmalloc(size, GFP_KERNEL); - - if (dev_priv->mxms && - mxm_shadow_rom_fetch(i2c, addr, 0, size, dev_priv->mxms)) - return true; - - kfree(dev_priv->mxms); - dev_priv->mxms = NULL; - return false; -} - -#if defined(CONFIG_ACPI) -static bool -mxm_shadow_dsm(struct drm_device *dev, u8 version) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - static char muid[] = { - 0x00, 0xA4, 0x04, 0x40, 0x7D, 0x91, 0xF2, 0x4C, - 0xB8, 0x9C, 0x79, 0xB6, 0x2F, 0xD5, 0x56, 0x65 - }; - u32 mxms_args[] = { 0x00000000 }; - union acpi_object args[4] = { - /* _DSM MUID */ - { .buffer.type = 3, - .buffer.length = sizeof(muid), - .buffer.pointer = muid, - }, - /* spec says this can be zero to mean "highest revision", but - * of course there's at least one bios out there which fails - * unless you pass in exactly the version it supports.. - */ - { .integer.type = ACPI_TYPE_INTEGER, - .integer.value = (version & 0xf0) << 4 | (version & 0x0f), - }, - /* MXMS function */ - { .integer.type = ACPI_TYPE_INTEGER, - .integer.value = 0x00000010, - }, - /* Pointer to MXMS arguments */ - { .buffer.type = ACPI_TYPE_BUFFER, - .buffer.length = sizeof(mxms_args), - .buffer.pointer = (char *)mxms_args, - }, - }; - struct acpi_object_list list = { ARRAY_SIZE(args), args }; - struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_handle handle; - int ret; - - handle = DEVICE_ACPI_HANDLE(&dev->pdev->dev); - if (!handle) - return false; - - ret = acpi_evaluate_object(handle, "_DSM", &list, &retn); - if (ret) { - MXM_DBG(dev, "DSM MXMS failed: %d\n", ret); - return false; - } - - obj = retn.pointer; - if (obj->type == ACPI_TYPE_BUFFER) { - dev_priv->mxms = kmemdup(obj->buffer.pointer, - obj->buffer.length, GFP_KERNEL); - } else - if (obj->type == ACPI_TYPE_INTEGER) { - MXM_DBG(dev, "DSM MXMS returned 0x%llx\n", obj->integer.value); - } - - kfree(obj); - return dev_priv->mxms != NULL; -} -#endif - -#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) - -#define WMI_WMMX_GUID "F6CB5C3C-9CAE-4EBD-B577-931EA32A2CC0" - -static bool -mxm_shadow_wmi(struct drm_device *dev, u8 version) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mxms_args[] = { 0x534D584D /* MXMS */, version, 0 }; - struct acpi_buffer args = { sizeof(mxms_args), mxms_args }; - struct acpi_buffer retn = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - - if (!wmi_has_guid(WMI_WMMX_GUID)) - return false; - - status = wmi_evaluate_method(WMI_WMMX_GUID, 0, 0, &args, &retn); - if (ACPI_FAILURE(status)) { - MXM_DBG(dev, "WMMX MXMS returned %d\n", status); - return false; - } - - obj = retn.pointer; - if (obj->type == ACPI_TYPE_BUFFER) { - dev_priv->mxms = kmemdup(obj->buffer.pointer, - obj->buffer.length, GFP_KERNEL); - } - - kfree(obj); - return dev_priv->mxms != NULL; -} -#endif - -struct mxm_shadow_h { - const char *name; - bool (*exec)(struct drm_device *, u8 version); -} _mxm_shadow[] = { - { "ROM", mxm_shadow_rom }, -#if defined(CONFIG_ACPI) - { "DSM", mxm_shadow_dsm }, -#endif -#if defined(CONFIG_ACPI_WMI) || defined(CONFIG_ACPI_WMI_MODULE) - { "WMI", mxm_shadow_wmi }, -#endif - {} -}; - -static int -mxm_shadow(struct drm_device *dev, u8 version) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct mxm_shadow_h *shadow = _mxm_shadow; - do { - MXM_DBG(dev, "checking %s\n", shadow->name); - if (shadow->exec(dev, version)) { - if (mxms_valid(dev)) - return 0; - kfree(dev_priv->mxms); - dev_priv->mxms = NULL; - } - } while ((++shadow)->name); - return -ENOENT; -} - -int -nouveau_mxm_init(struct drm_device *dev) -{ - u8 mxm_size, *mxm = mxm_table(dev, &mxm_size); - if (!mxm || !mxm[0]) { - MXM_MSG(dev, "no VBIOS data, nothing to do\n"); - return 0; - } - - MXM_MSG(dev, "BIOS version %d.%d\n", mxm[0] >> 4, mxm[0] & 0x0f); - - if (mxm_shadow(dev, mxm[0])) { - MXM_MSG(dev, "failed to locate valid SIS\n"); - return -EINVAL; - } - - MXM_MSG(dev, "MXMS Version %d.%d\n", - mxms_version(dev) >> 8, mxms_version(dev) & 0xff); - mxms_foreach(dev, 0, NULL, NULL); - - if (nouveau_mxmdcb) - mxm_dcb_sanitise(dev); - return 0; -} - -void -nouveau_mxm_fini(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - kfree(dev_priv->mxms); - dev_priv->mxms = NULL; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_notifier.c b/trunk/drivers/gpu/drm/nouveau/nouveau_notifier.c index 2ef883c4bbc1..6abdbe6530a7 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_notifier.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_notifier.c @@ -115,7 +115,7 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_gpuobj *nobj = NULL; struct drm_mm_node *mem; - uint64_t offset; + uint32_t offset; int target, ret; mem = drm_mm_search_free_in_range(&chan->notifier_heap, size, 0, diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_object.c b/trunk/drivers/gpu/drm/nouveau/nouveau_object.c index cc419fae794b..960c0ae0c0c3 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_object.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_object.c @@ -723,14 +723,14 @@ nvc0_gpuobj_channel_init(struct nouveau_channel *chan, struct nouveau_vm *vm) nv_wo32(chan->ramin, 0x020c, 0x000000ff); /* map display semaphore buffers into channel's vm */ - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo; - if (dev_priv->card_type >= NV_D0) - bo = nvd0_display_crtc_sema(dev, i); - else - bo = nv50_display(dev)->crtc[i].sem.bo; - - ret = nouveau_bo_vma_add(bo, chan->vm, &chan->dispc_vma[i]); + if (dev_priv->card_type >= NV_D0) + return 0; + + for (i = 0; i < 2; i++) { + struct nv50_display_crtc *dispc = &nv50_display(dev)->crtc[i]; + + ret = nouveau_bo_vma_add(dispc->sem.bo, chan->vm, + &chan->dispc_vma[i]); if (ret) return ret; } @@ -879,14 +879,9 @@ nouveau_gpuobj_channel_takedown(struct nouveau_channel *chan) NV_DEBUG(dev, "ch%d\n", chan->id); - if (dev_priv->card_type >= NV_D0) { - for (i = 0; i < dev->mode_config.num_crtc; i++) { - struct nouveau_bo *bo = nvd0_display_crtc_sema(dev, i); - nouveau_bo_vma_del(bo, &chan->dispc_vma[i]); - } - } else - if (dev_priv->card_type >= NV_50) { + if (dev_priv->card_type >= NV_50 && dev_priv->card_type <= NV_C0) { struct nv50_display *disp = nv50_display(dev); + for (i = 0; i < dev->mode_config.num_crtc; i++) { struct nv50_display_crtc *dispc = &disp->crtc[i]; nouveau_bo_vma_del(dispc->sem.bo, &chan->dispc_vma[i]); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_perf.c b/trunk/drivers/gpu/drm/nouveau/nouveau_perf.c index 58f497343cec..33d03fbf00df 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_perf.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_perf.c @@ -41,7 +41,7 @@ legacy_perf_init(struct drm_device *dev) return; } - perf = ROMPTR(dev, bmp[0x73]); + perf = ROMPTR(bios, bmp[0x73]); if (!perf) { NV_DEBUG(dev, "No memclock table pointer found.\n"); return; @@ -87,7 +87,7 @@ nouveau_perf_timing(struct drm_device *dev, struct bit_entry *P, * ramcfg to select the correct subentry */ if (P->version == 2) { - u8 *tmap = ROMPTR(dev, P->data[4]); + u8 *tmap = ROMPTR(bios, P->data[4]); if (!tmap) { NV_DEBUG(dev, "no timing map pointer\n"); return NULL; @@ -140,6 +140,7 @@ nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, struct nouveau_pm_level *perflvl) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nvbios *bios = &dev_priv->vbios; u8 *vmap; int id; @@ -164,7 +165,7 @@ nouveau_perf_voltage(struct drm_device *dev, struct bit_entry *P, return; } - vmap = ROMPTR(dev, P->data[32]); + vmap = ROMPTR(bios, P->data[32]); if (!vmap) { NV_DEBUG(dev, "volt map table pointer invalid\n"); return; @@ -199,14 +200,12 @@ nouveau_perf_init(struct drm_device *dev) return; } - perf = ROMPTR(dev, P.data[0]); + perf = ROMPTR(bios, P.data[0]); version = perf[0]; headerlen = perf[1]; if (version < 0x40) { recordlen = perf[3] + (perf[4] * perf[5]); entries = perf[2]; - - pm->pwm_divisor = ROM16(perf[6]); } else { recordlen = perf[2] + (perf[3] * perf[4]); entries = perf[5]; @@ -217,7 +216,7 @@ nouveau_perf_init(struct drm_device *dev) return; } - perf = ROMPTR(dev, bios->data[bios->offset + 0x94]); + perf = ROMPTR(bios, bios->data[bios->offset + 0x94]); if (!perf) { NV_DEBUG(dev, "perf table pointer invalid\n"); return; @@ -284,6 +283,7 @@ nouveau_perf_init(struct drm_device *dev) perflvl->memory = ROM16(entry[11]) * 1000; else perflvl->memory = ROM16(entry[11]) * 2000; + break; case 0x25: perflvl->fanspeed = entry[4]; @@ -300,8 +300,8 @@ nouveau_perf_init(struct drm_device *dev) perflvl->core = ROM16(entry[8]) * 1000; perflvl->shader = ROM16(entry[10]) * 1000; perflvl->memory = ROM16(entry[12]) * 1000; - perflvl->vdec = ROM16(entry[16]) * 1000; - perflvl->dom6 = ROM16(entry[20]) * 1000; + /*XXX: confirm on 0x35 */ + perflvl->unk05 = ROM16(entry[16]) * 1000; break; case 0x40: #define subent(n) (ROM16(entry[perf[2] + ((n) * perf[3])]) & 0xfff) * 1000 diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c index aba3362d421a..a539fd257921 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.c @@ -26,7 +26,6 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" -#include "nouveau_gpio.h" #ifdef CONFIG_ACPI #include @@ -36,95 +35,22 @@ #include static int -nouveau_pwmfan_get(struct drm_device *dev) +nouveau_pm_clock_set(struct drm_device *dev, struct nouveau_pm_level *perflvl, + u8 id, u32 khz) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct gpio_func gpio; - u32 divs, duty; - int ret; - - if (!pm->pwm_get) - return -ENODEV; - - ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); - if (ret == 0) { - ret = pm->pwm_get(dev, gpio.line, &divs, &duty); - if (ret == 0) { - divs = max(divs, duty); - if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) - duty = divs - duty; - return (duty * 100) / divs; - } - - return nouveau_gpio_func_get(dev, gpio.func) * 100; - } - - return -ENODEV; -} - -static int -nouveau_pwmfan_set(struct drm_device *dev, int percent) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - struct gpio_func gpio; - u32 divs, duty; - int ret; - - if (!pm->pwm_set) - return -ENODEV; - - ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); - if (ret == 0) { - divs = pm->pwm_divisor; - if (pm->fan.pwm_freq) { - /*XXX: PNVIO clock more than likely... */ - divs = 135000 / pm->fan.pwm_freq; - if (dev_priv->chipset < 0xa3) - divs /= 4; - } - - duty = ((divs * percent) + 99) / 100; - if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) - duty = divs - duty; + void *pre_state; - return pm->pwm_set(dev, gpio.line, divs, duty); - } - - return -ENODEV; -} - -static int -nouveau_pm_perflvl_aux(struct drm_device *dev, struct nouveau_pm_level *perflvl, - struct nouveau_pm_level *a, struct nouveau_pm_level *b) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - int ret; - - /*XXX: not on all boards, we should control based on temperature - * on recent boards.. or maybe on some other factor we don't - * know about? - */ - if (a->fanspeed && b->fanspeed && b->fanspeed > a->fanspeed) { - ret = nouveau_pwmfan_set(dev, perflvl->fanspeed); - if (ret && ret != -ENODEV) { - NV_ERROR(dev, "fanspeed set failed: %d\n", ret); - return ret; - } - } + if (khz == 0) + return 0; - if (pm->voltage.supported && pm->voltage_set) { - if (perflvl->volt_min && b->volt_min > a->volt_min) { - ret = pm->voltage_set(dev, perflvl->volt_min); - if (ret) { - NV_ERROR(dev, "voltage set failed: %d\n", ret); - return ret; - } - } - } + pre_state = pm->clock_pre(dev, perflvl, id, khz); + if (IS_ERR(pre_state)) + return PTR_ERR(pre_state); + if (pre_state) + pm->clock_set(dev, pre_state); return 0; } @@ -133,24 +59,31 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct nouveau_pm_level *perflvl) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - void *state; int ret; if (perflvl == pm->cur) return 0; - ret = nouveau_pm_perflvl_aux(dev, perflvl, pm->cur, perflvl); - if (ret) - return ret; - - state = pm->clocks_pre(dev, perflvl); - if (IS_ERR(state)) - return PTR_ERR(state); - pm->clocks_set(dev, state); + if (pm->voltage.supported && pm->voltage_set && perflvl->volt_min) { + ret = pm->voltage_set(dev, perflvl->volt_min); + if (ret) { + NV_ERROR(dev, "voltage_set %d failed: %d\n", + perflvl->volt_min, ret); + } + } - ret = nouveau_pm_perflvl_aux(dev, perflvl, perflvl, pm->cur); - if (ret) - return ret; + if (pm->clocks_pre) { + void *state = pm->clocks_pre(dev, perflvl); + if (IS_ERR(state)) + return PTR_ERR(state); + pm->clocks_set(dev, state); + } else + if (pm->clock_set) { + nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl->core); + nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl->shader); + nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl->memory); + nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl->unk05); + } pm->cur = perflvl; return 0; @@ -197,9 +130,28 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) memset(perflvl, 0, sizeof(*perflvl)); - ret = pm->clocks_get(dev, perflvl); - if (ret) - return ret; + if (pm->clocks_get) { + ret = pm->clocks_get(dev, perflvl); + if (ret) + return ret; + } else + if (pm->clock_get) { + ret = pm->clock_get(dev, PLL_CORE); + if (ret > 0) + perflvl->core = ret; + + ret = pm->clock_get(dev, PLL_MEMORY); + if (ret > 0) + perflvl->memory = ret; + + ret = pm->clock_get(dev, PLL_SHADER); + if (ret > 0) + perflvl->shader = ret; + + ret = pm->clock_get(dev, PLL_UNK05); + if (ret > 0) + perflvl->unk05 = ret; + } if (pm->voltage.supported && pm->voltage_get) { ret = pm->voltage_get(dev); @@ -209,10 +161,6 @@ nouveau_pm_perflvl_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) } } - ret = nouveau_pwmfan_get(dev); - if (ret > 0) - perflvl->fanspeed = ret; - return 0; } @@ -464,172 +412,6 @@ static SENSOR_DEVICE_ATTR(update_rate, S_IRUGO, nouveau_hwmon_show_update_rate, NULL, 0); -static ssize_t -nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct gpio_func gpio; - u32 cycles, cur, prev; - u64 start; - int ret; - - ret = nouveau_gpio_find(dev, 0, DCB_GPIO_FAN_SENSE, 0xff, &gpio); - if (ret) - return ret; - - /* Monitor the GPIO input 0x3b for 250ms. - * When the fan spins, it changes the value of GPIO FAN_SENSE. - * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. - */ - start = ptimer->read(dev); - prev = nouveau_gpio_sense(dev, 0, gpio.line); - cycles = 0; - do { - cur = nouveau_gpio_sense(dev, 0, gpio.line); - if (prev != cur) { - cycles++; - prev = cur; - } - - usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ - } while (ptimer->read(dev) - start < 250000000); - - /* interpolate to get rpm */ - return sprintf(buf, "%i\n", cycles / 4 * 4 * 60); -} -static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, - NULL, 0); - -static ssize_t -nouveau_hwmon_get_pwm0(struct device *d, struct device_attribute *a, char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - int ret; - - ret = nouveau_pwmfan_get(dev); - if (ret < 0) - return ret; - - return sprintf(buf, "%i\n", ret); -} - -static ssize_t -nouveau_hwmon_set_pwm0(struct device *d, struct device_attribute *a, - const char *buf, size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - int ret = -ENODEV; - long value; - - if (nouveau_perflvl_wr != 7777) - return -EPERM; - - if (strict_strtol(buf, 10, &value) == -EINVAL) - return -EINVAL; - - if (value < pm->fan.min_duty) - value = pm->fan.min_duty; - if (value > pm->fan.max_duty) - value = pm->fan.max_duty; - - ret = nouveau_pwmfan_set(dev, value); - if (ret) - return ret; - - return count; -} - -static SENSOR_DEVICE_ATTR(pwm0, S_IRUGO | S_IWUSR, - nouveau_hwmon_get_pwm0, - nouveau_hwmon_set_pwm0, 0); - -static ssize_t -nouveau_hwmon_get_pwm0_min(struct device *d, - struct device_attribute *a, char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - - return sprintf(buf, "%i\n", pm->fan.min_duty); -} - -static ssize_t -nouveau_hwmon_set_pwm0_min(struct device *d, struct device_attribute *a, - const char *buf, size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - long value; - - if (strict_strtol(buf, 10, &value) == -EINVAL) - return -EINVAL; - - if (value < 0) - value = 0; - - if (pm->fan.max_duty - value < 10) - value = pm->fan.max_duty - 10; - - if (value < 10) - pm->fan.min_duty = 10; - else - pm->fan.min_duty = value; - - return count; -} - -static SENSOR_DEVICE_ATTR(pwm0_min, S_IRUGO | S_IWUSR, - nouveau_hwmon_get_pwm0_min, - nouveau_hwmon_set_pwm0_min, 0); - -static ssize_t -nouveau_hwmon_get_pwm0_max(struct device *d, - struct device_attribute *a, char *buf) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - - return sprintf(buf, "%i\n", pm->fan.max_duty); -} - -static ssize_t -nouveau_hwmon_set_pwm0_max(struct device *d, struct device_attribute *a, - const char *buf, size_t count) -{ - struct drm_device *dev = dev_get_drvdata(d); - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_pm_engine *pm = &dev_priv->engine.pm; - long value; - - if (strict_strtol(buf, 10, &value) == -EINVAL) - return -EINVAL; - - if (value < 0) - value = 0; - - if (value - pm->fan.min_duty < 10) - value = pm->fan.min_duty + 10; - - if (value > 100) - pm->fan.max_duty = 100; - else - pm->fan.max_duty = value; - - return count; -} - -static SENSOR_DEVICE_ATTR(pwm0_max, S_IRUGO | S_IWUSR, - nouveau_hwmon_get_pwm0_max, - nouveau_hwmon_set_pwm0_max, 0); - static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, @@ -638,26 +420,10 @@ static struct attribute *hwmon_attributes[] = { &sensor_dev_attr_update_rate.dev_attr.attr, NULL }; -static struct attribute *hwmon_fan_rpm_attributes[] = { - &sensor_dev_attr_fan0_input.dev_attr.attr, - NULL -}; -static struct attribute *hwmon_pwm_fan_attributes[] = { - &sensor_dev_attr_pwm0.dev_attr.attr, - &sensor_dev_attr_pwm0_min.dev_attr.attr, - &sensor_dev_attr_pwm0_max.dev_attr.attr, - NULL -}; static const struct attribute_group hwmon_attrgroup = { .attrs = hwmon_attributes, }; -static const struct attribute_group hwmon_fan_rpm_attrgroup = { - .attrs = hwmon_fan_rpm_attributes, -}; -static const struct attribute_group hwmon_pwm_fan_attrgroup = { - .attrs = hwmon_pwm_fan_attributes, -}; #endif static int @@ -667,7 +433,7 @@ nouveau_hwmon_init(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_pm_engine *pm = &dev_priv->engine.pm; struct device *hwmon_dev; - int ret = 0; + int ret; if (!pm->temp_get) return -ENODEV; @@ -680,46 +446,17 @@ nouveau_hwmon_init(struct drm_device *dev) return ret; } dev_set_drvdata(hwmon_dev, dev); - - /* default sysfs entries */ ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); if (ret) { - if (ret) - goto error; - } - - /* if the card has a pwm fan */ - /*XXX: incorrect, need better detection for this, some boards have - * the gpio entries for pwm fan control even when there's no - * actual fan connected to it... therm table? */ - if (nouveau_pwmfan_get(dev) >= 0) { - ret = sysfs_create_group(&dev->pdev->dev.kobj, - &hwmon_pwm_fan_attrgroup); - if (ret) - goto error; - } - - /* if the card can read the fan rpm */ - if (nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) { - ret = sysfs_create_group(&dev->pdev->dev.kobj, - &hwmon_fan_rpm_attrgroup); - if (ret) - goto error; + NV_ERROR(dev, + "Unable to create hwmon sysfs file: %d\n", ret); + hwmon_device_unregister(hwmon_dev); + return ret; } pm->hwmon = hwmon_dev; - - return 0; - -error: - NV_ERROR(dev, "Unable to create some hwmon sysfs files: %d\n", ret); - hwmon_device_unregister(hwmon_dev); - pm->hwmon = NULL; - return ret; -#else - pm->hwmon = NULL; - return 0; #endif + return 0; } static void @@ -731,9 +468,6 @@ nouveau_hwmon_fini(struct drm_device *dev) if (pm->hwmon) { sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); - sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_pwm_fan_attrgroup); - sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_fan_rpm_attrgroup); - hwmon_device_unregister(pm->hwmon); } #endif diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.h b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.h index 2f8e14fbcff8..8ac02cdd03a1 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_pm.h @@ -47,33 +47,29 @@ void nouveau_mem_timing_init(struct drm_device *); void nouveau_mem_timing_fini(struct drm_device *); /* nv04_pm.c */ -int nv04_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nv04_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nv04_pm_clocks_set(struct drm_device *, void *); +int nv04_pm_clock_get(struct drm_device *, u32 id); +void *nv04_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); +void nv04_pm_clock_set(struct drm_device *, void *); /* nv40_pm.c */ int nv40_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); void *nv40_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nv40_pm_clocks_set(struct drm_device *, void *); -int nv40_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); -int nv40_pm_pwm_set(struct drm_device *, int, u32, u32); +void nv40_pm_clocks_set(struct drm_device *, void *); /* nv50_pm.c */ -int nv50_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nv50_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nv50_pm_clocks_set(struct drm_device *, void *); -int nv50_pm_pwm_get(struct drm_device *, int, u32 *, u32 *); -int nv50_pm_pwm_set(struct drm_device *, int, u32, u32); +int nv50_pm_clock_get(struct drm_device *, u32 id); +void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, + u32 id, int khz); +void nv50_pm_clock_set(struct drm_device *, void *); /* nva3_pm.c */ int nva3_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); void *nva3_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nva3_pm_clocks_set(struct drm_device *, void *); +void nva3_pm_clocks_set(struct drm_device *, void *); /* nvc0_pm.c */ int nvc0_pm_clocks_get(struct drm_device *, struct nouveau_pm_level *); -void *nvc0_pm_clocks_pre(struct drm_device *, struct nouveau_pm_level *); -int nvc0_pm_clocks_set(struct drm_device *, void *); /* nouveau_temp.c */ void nouveau_temp_init(struct drm_device *dev); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_state.c b/trunk/drivers/gpu/drm/nouveau/nouveau_state.c index f5e98910d17f..d8831ab42bb9 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_state.c @@ -36,7 +36,6 @@ #include "nouveau_drm.h" #include "nouveau_fbcon.h" #include "nouveau_ramht.h" -#include "nouveau_gpio.h" #include "nouveau_pm.h" #include "nv50_display.h" @@ -81,12 +80,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; + engine->display.destroy = nv04_display_destroy; + engine->gpio.init = nouveau_stub_init; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = NULL; + engine->gpio.set = NULL; + engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; engine->vram.init = nouveau_mem_detect; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; @@ -126,14 +129,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; + engine->display.destroy = nv04_display_destroy; + engine->gpio.init = nouveau_stub_init; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nv10_gpio_get; + engine->gpio.set = nv10_gpio_set; + engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; engine->vram.init = nouveau_mem_detect; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; @@ -173,14 +178,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; + engine->display.destroy = nv04_display_destroy; + engine->gpio.init = nouveau_stub_init; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nv10_gpio_get; + engine->gpio.set = nv10_gpio_set; + engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; engine->vram.init = nouveau_mem_detect; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; @@ -220,14 +227,16 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; - engine->pm.clocks_get = nv04_pm_clocks_get; - engine->pm.clocks_pre = nv04_pm_clocks_pre; - engine->pm.clocks_set = nv04_pm_clocks_set; + engine->display.destroy = nv04_display_destroy; + engine->gpio.init = nouveau_stub_init; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nv10_gpio_get; + engine->gpio.set = nv10_gpio_set; + engine->gpio.irq_enable = NULL; + engine->pm.clock_get = nv04_pm_clock_get; + engine->pm.clock_pre = nv04_pm_clock_pre; + engine->pm.clock_set = nv04_pm_clock_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; engine->vram.init = nouveau_mem_detect; @@ -270,22 +279,19 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv04_display_early_init; engine->display.late_takedown = nv04_display_late_takedown; engine->display.create = nv04_display_create; - engine->display.destroy = nv04_display_destroy; engine->display.init = nv04_display_init; - engine->display.fini = nv04_display_fini; - engine->gpio.init = nv10_gpio_init; - engine->gpio.fini = nv10_gpio_fini; - engine->gpio.drive = nv10_gpio_drive; - engine->gpio.sense = nv10_gpio_sense; - engine->gpio.irq_enable = nv10_gpio_irq_enable; + engine->display.destroy = nv04_display_destroy; + engine->gpio.init = nouveau_stub_init; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nv10_gpio_get; + engine->gpio.set = nv10_gpio_set; + engine->gpio.irq_enable = NULL; engine->pm.clocks_get = nv40_pm_clocks_get; engine->pm.clocks_pre = nv40_pm_clocks_pre; engine->pm.clocks_set = nv40_pm_clocks_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; engine->pm.temp_get = nv40_temp_get; - engine->pm.pwm_get = nv40_pm_pwm_get; - engine->pm.pwm_set = nv40_pm_pwm_set; engine->vram.init = nouveau_mem_detect; engine->vram.takedown = nouveau_stub_takedown; engine->vram.flags_valid = nouveau_mem_flags_valid; @@ -328,13 +334,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; - engine->display.destroy = nv50_display_destroy; engine->display.init = nv50_display_init; - engine->display.fini = nv50_display_fini; + engine->display.destroy = nv50_display_destroy; engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nv50_gpio_drive; - engine->gpio.sense = nv50_gpio_sense; + engine->gpio.takedown = nv50_gpio_fini; + engine->gpio.get = nv50_gpio_get; + engine->gpio.set = nv50_gpio_set; + engine->gpio.irq_register = nv50_gpio_irq_register; + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; engine->gpio.irq_enable = nv50_gpio_irq_enable; switch (dev_priv->chipset) { case 0x84: @@ -347,9 +354,9 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) case 0xaa: case 0xac: case 0x50: - engine->pm.clocks_get = nv50_pm_clocks_get; - engine->pm.clocks_pre = nv50_pm_clocks_pre; - engine->pm.clocks_set = nv50_pm_clocks_set; + engine->pm.clock_get = nv50_pm_clock_get; + engine->pm.clock_pre = nv50_pm_clock_pre; + engine->pm.clock_set = nv50_pm_clock_set; break; default: engine->pm.clocks_get = nva3_pm_clocks_get; @@ -363,8 +370,6 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->pm.temp_get = nv84_temp_get; else engine->pm.temp_get = nv40_temp_get; - engine->pm.pwm_get = nv50_pm_pwm_get; - engine->pm.pwm_set = nv50_pm_pwm_set; engine->vram.init = nv50_vram_init; engine->vram.takedown = nv50_vram_fini; engine->vram.get = nv50_vram_new; @@ -402,13 +407,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nv50_display_early_init; engine->display.late_takedown = nv50_display_late_takedown; engine->display.create = nv50_display_create; - engine->display.destroy = nv50_display_destroy; engine->display.init = nv50_display_init; - engine->display.fini = nv50_display_fini; + engine->display.destroy = nv50_display_destroy; engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nv50_gpio_drive; - engine->gpio.sense = nv50_gpio_sense; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nv50_gpio_get; + engine->gpio.set = nv50_gpio_set; + engine->gpio.irq_register = nv50_gpio_irq_register; + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->vram.init = nvc0_vram_init; engine->vram.takedown = nv50_vram_fini; @@ -417,12 +423,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->vram.flags_valid = nvc0_vram_flags_valid; engine->pm.temp_get = nv84_temp_get; engine->pm.clocks_get = nvc0_pm_clocks_get; - engine->pm.clocks_pre = nvc0_pm_clocks_pre; - engine->pm.clocks_set = nvc0_pm_clocks_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; - engine->pm.pwm_get = nv50_pm_pwm_get; - engine->pm.pwm_set = nv50_pm_pwm_set; break; case 0xd0: engine->instmem.init = nvc0_instmem_init; @@ -455,23 +457,21 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nvd0_display_create; - engine->display.destroy = nvd0_display_destroy; engine->display.init = nvd0_display_init; - engine->display.fini = nvd0_display_fini; + engine->display.destroy = nvd0_display_destroy; engine->gpio.init = nv50_gpio_init; - engine->gpio.fini = nv50_gpio_fini; - engine->gpio.drive = nvd0_gpio_drive; - engine->gpio.sense = nvd0_gpio_sense; + engine->gpio.takedown = nouveau_stub_takedown; + engine->gpio.get = nvd0_gpio_get; + engine->gpio.set = nvd0_gpio_set; + engine->gpio.irq_register = nv50_gpio_irq_register; + engine->gpio.irq_unregister = nv50_gpio_irq_unregister; engine->gpio.irq_enable = nv50_gpio_irq_enable; engine->vram.init = nvc0_vram_init; engine->vram.takedown = nv50_vram_fini; engine->vram.get = nvc0_vram_new; engine->vram.put = nv50_vram_del; engine->vram.flags_valid = nvc0_vram_flags_valid; - engine->pm.temp_get = nv84_temp_get; engine->pm.clocks_get = nvc0_pm_clocks_get; - engine->pm.clocks_pre = nvc0_pm_clocks_pre; - engine->pm.clocks_set = nvc0_pm_clocks_set; engine->pm.voltage_get = nouveau_voltage_gpio_get; engine->pm.voltage_set = nouveau_voltage_gpio_set; break; @@ -615,7 +615,7 @@ nouveau_card_init(struct drm_device *dev) goto out_gart; /* PGPIO */ - ret = nouveau_gpio_create(dev); + ret = engine->gpio.init(dev); if (ret) goto out_mc; @@ -648,7 +648,6 @@ nouveau_card_init(struct drm_device *dev) nv50_graph_create(dev); break; case NV_C0: - case NV_D0: nvc0_graph_create(dev); break; default: @@ -664,11 +663,6 @@ nouveau_card_init(struct drm_device *dev) case 0xa0: nv84_crypt_create(dev); break; - case 0x98: - case 0xaa: - case 0xac: - nv98_crypt_create(dev); - break; } switch (dev_priv->card_type) { @@ -690,25 +684,15 @@ nouveau_card_init(struct drm_device *dev) break; } - if (dev_priv->chipset >= 0xa3 || dev_priv->chipset == 0x98) { - nv84_bsp_create(dev); - nv84_vp_create(dev); - nv98_ppp_create(dev); - } else - if (dev_priv->chipset >= 0x84) { - nv50_mpeg_create(dev); - nv84_bsp_create(dev); - nv84_vp_create(dev); - } else - if (dev_priv->chipset >= 0x50) { - nv50_mpeg_create(dev); - } else if (dev_priv->card_type == NV_40 || dev_priv->chipset == 0x31 || dev_priv->chipset == 0x34 || - dev_priv->chipset == 0x36) { + dev_priv->chipset == 0x36) nv31_mpeg_create(dev); - } + else + if (dev_priv->card_type == NV_50 && + (dev_priv->chipset < 0x98 || dev_priv->chipset == 0xa0)) + nv50_mpeg_create(dev); for (e = 0; e < NVOBJ_ENGINE_NR; e++) { if (dev_priv->eng[e]) { @@ -728,7 +712,27 @@ nouveau_card_init(struct drm_device *dev) if (ret) goto out_fifo; - ret = nouveau_display_create(dev); + /* initialise general modesetting */ + drm_mode_config_init(dev); + drm_mode_create_scaling_mode_property(dev); + drm_mode_create_dithering_property(dev); + dev->mode_config.funcs = (void *)&nouveau_mode_config_funcs; + dev->mode_config.fb_base = pci_resource_start(dev->pdev, 1); + dev->mode_config.min_width = 0; + dev->mode_config.min_height = 0; + if (dev_priv->card_type < NV_10) { + dev->mode_config.max_width = 2048; + dev->mode_config.max_height = 2048; + } else + if (dev_priv->card_type < NV_50) { + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; + } else { + dev->mode_config.max_width = 8192; + dev->mode_config.max_height = 8192; + } + + ret = engine->display.create(dev); if (ret) goto out_irq; @@ -748,11 +752,12 @@ nouveau_card_init(struct drm_device *dev) } if (dev->mode_config.num_crtc) { - ret = nouveau_display_init(dev); + ret = drm_vblank_init(dev, dev->mode_config.num_crtc); if (ret) goto out_chan; nouveau_fbcon_init(dev); + drm_kms_helper_poll_init(dev); } return 0; @@ -763,7 +768,7 @@ nouveau_card_init(struct drm_device *dev) nouveau_fence_fini(dev); out_disp: nouveau_backlight_exit(dev); - nouveau_display_destroy(dev); + engine->display.destroy(dev); out_irq: nouveau_irq_fini(dev); out_fifo: @@ -783,7 +788,7 @@ nouveau_card_init(struct drm_device *dev) out_timer: engine->timer.takedown(dev); out_gpio: - nouveau_gpio_destroy(dev); + engine->gpio.takedown(dev); out_mc: engine->mc.takedown(dev); out_gart: @@ -813,8 +818,9 @@ static void nouveau_card_takedown(struct drm_device *dev) int e; if (dev->mode_config.num_crtc) { + drm_kms_helper_poll_fini(dev); nouveau_fbcon_fini(dev); - nouveau_display_fini(dev); + drm_vblank_cleanup(dev); } if (dev_priv->channel) { @@ -823,7 +829,8 @@ static void nouveau_card_takedown(struct drm_device *dev) } nouveau_backlight_exit(dev); - nouveau_display_destroy(dev); + engine->display.destroy(dev); + drm_mode_config_cleanup(dev); if (!dev_priv->noaccel) { engine->fifo.takedown(dev); @@ -836,7 +843,7 @@ static void nouveau_card_takedown(struct drm_device *dev) } engine->fb.takedown(dev); engine->timer.takedown(dev); - nouveau_gpio_destroy(dev); + engine->gpio.takedown(dev); engine->mc.takedown(dev); engine->display.late_takedown(dev); @@ -1103,11 +1110,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) dev_priv->noaccel = !!nouveau_noaccel; if (nouveau_noaccel == -1) { switch (dev_priv->chipset) { - case 0xd9: /* known broken */ +#if 0 + case 0xXX: /* known broken */ NV_INFO(dev, "acceleration disabled by default, pass " "noaccel=0 to force enable\n"); dev_priv->noaccel = true; break; +#endif default: dev_priv->noaccel = false; break; @@ -1229,7 +1238,7 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, getparam->value = 1; break; case NOUVEAU_GETPARAM_HAS_PAGEFLIP: - getparam->value = 1; + getparam->value = dev_priv->card_type < NV_D0; break; case NOUVEAU_GETPARAM_GRAPH_UNITS: /* NV40 and NV50 versions are quite different, but register diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_temp.c b/trunk/drivers/gpu/drm/nouveau/nouveau_temp.c index 0f5a30160556..5a46446dd5a8 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_temp.c @@ -55,10 +55,6 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) temps->down_clock = 100; temps->fan_boost = 90; - /* Set the default range for the pwm fan */ - pm->fan.min_duty = 30; - pm->fan.max_duty = 100; - /* Set the known default values to setup the temperature sensor */ if (dev_priv->card_type >= NV_40) { switch (dev_priv->chipset) { @@ -160,26 +156,11 @@ nouveau_temp_vbios_parse(struct drm_device *dev, u8 *temp) case 0x13: sensor->slope_div = value; break; - case 0x22: - pm->fan.min_duty = value & 0xff; - pm->fan.max_duty = (value & 0xff00) >> 8; - break; - case 0x26: - pm->fan.pwm_freq = value; - break; } temp += recordlen; } nouveau_temp_safety_checks(dev); - - /* check the fan min/max settings */ - if (pm->fan.min_duty < 10) - pm->fan.min_duty = 10; - if (pm->fan.max_duty > 100) - pm->fan.max_duty = 100; - if (pm->fan.max_duty < pm->fan.min_duty) - pm->fan.max_duty = pm->fan.min_duty; } static int @@ -286,6 +267,8 @@ probe_monitoring_device(struct nouveau_i2c_chan *i2c, static void nouveau_temp_probe_i2c(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct dcb_table *dcb = &dev_priv->vbios.dcb; struct i2c_board_info info[] = { { I2C_BOARD_INFO("w83l785ts", 0x2d) }, { I2C_BOARD_INFO("w83781d", 0x2d) }, @@ -294,9 +277,11 @@ nouveau_temp_probe_i2c(struct drm_device *dev) { I2C_BOARD_INFO("lm99", 0x4c) }, { } }; + int idx = (dcb->version >= 0x40 ? + dcb->i2c_default_indices & 0xf : 2); nouveau_i2c_identify(dev, "monitoring device", info, - probe_monitoring_device, NV_I2C_DEFAULT(0)); + probe_monitoring_device, idx); } void @@ -312,9 +297,9 @@ nouveau_temp_init(struct drm_device *dev) return; if (P.version == 1) - temp = ROMPTR(dev, P.data[12]); + temp = ROMPTR(bios, P.data[12]); else if (P.version == 2) - temp = ROMPTR(dev, P.data[16]); + temp = ROMPTR(bios, P.data[16]); else NV_WARN(dev, "unknown temp for BIT P %d\n", P.version); diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_vm.c b/trunk/drivers/gpu/drm/nouveau/nouveau_vm.c index 2bf6c0350b4b..ef0832b29ad2 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_vm.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_vm.c @@ -78,10 +78,9 @@ nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node) void nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length, - struct nouveau_mem *mem) + struct nouveau_mem *mem, dma_addr_t *list) { struct nouveau_vm *vm = vma->vm; - dma_addr_t *list = mem->pages; int big = vma->node->type != vm->spg_shift; u32 offset = vma->node->offset + (delta >> 12); u32 bits = vma->node->type - 12; diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_vm.h b/trunk/drivers/gpu/drm/nouveau/nouveau_vm.h index 4fb6e728734d..6ce995f7797e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_vm.h +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_vm.h @@ -89,7 +89,7 @@ void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *); void nouveau_vm_unmap(struct nouveau_vma *); void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length); void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length, - struct nouveau_mem *); + struct nouveau_mem *, dma_addr_t *); /* nv50_vm.c */ void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, diff --git a/trunk/drivers/gpu/drm/nouveau/nouveau_volt.c b/trunk/drivers/gpu/drm/nouveau/nouveau_volt.c index b010cb997b34..86d03e15735d 100644 --- a/trunk/drivers/gpu/drm/nouveau/nouveau_volt.c +++ b/trunk/drivers/gpu/drm/nouveau/nouveau_volt.c @@ -26,7 +26,6 @@ #include "nouveau_drv.h" #include "nouveau_pm.h" -#include "nouveau_gpio.h" static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); @@ -35,6 +34,7 @@ int nouveau_voltage_gpio_get(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; u8 vid = 0; int i; @@ -43,7 +43,7 @@ nouveau_voltage_gpio_get(struct drm_device *dev) if (!(volt->vid_mask & (1 << i))) continue; - vid |= nouveau_gpio_func_get(dev, vidtag[i]) << i; + vid |= gpio->get(dev, vidtag[i]) << i; } return nouveau_volt_lvl_lookup(dev, vid); @@ -53,6 +53,7 @@ int nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; int vid, i; @@ -64,7 +65,7 @@ nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) if (!(volt->vid_mask & (1 << i))) continue; - nouveau_gpio_func_set(dev, vidtag[i], !!(vid & (1 << i))); + gpio->set(dev, vidtag[i], !!(vid & (1 << i))); } return 0; @@ -116,10 +117,10 @@ nouveau_volt_init(struct drm_device *dev) return; if (P.version == 1) - volt = ROMPTR(dev, P.data[16]); + volt = ROMPTR(bios, P.data[16]); else if (P.version == 2) - volt = ROMPTR(dev, P.data[12]); + volt = ROMPTR(bios, P.data[12]); else { NV_WARN(dev, "unknown volt for BIT P %d\n", P.version); } @@ -129,7 +130,7 @@ nouveau_volt_init(struct drm_device *dev) return; } - volt = ROMPTR(dev, bios->data[bios->offset + 0x98]); + volt = ROMPTR(bios, bios->data[bios->offset + 0x98]); } if (!volt) { @@ -193,7 +194,7 @@ nouveau_volt_init(struct drm_device *dev) return; } - if (!nouveau_gpio_func_valid(dev, vidtag[i])) { + if (!nouveau_bios_gpio_entry(dev, vidtag[i])) { NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); return; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c index 8300266ffaea..e000455e06d0 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dac.c @@ -32,7 +32,6 @@ #include "nouveau_connector.h" #include "nouveau_crtc.h" #include "nouveau_hw.h" -#include "nouveau_gpio.h" #include "nvreg.h" int nv04_dac_output_offset(struct drm_encoder *encoder) @@ -221,6 +220,7 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, @@ -252,11 +252,11 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); } - saved_gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); - saved_gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); + saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); + saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); + gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); + gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); msleep(4); @@ -306,8 +306,8 @@ uint32_t nv17_dac_sample_load(struct drm_encoder *encoder) nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); + gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1); + gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0); return sample; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c index 2258746016f8..12098bf839c4 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -289,7 +289,6 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, struct nouveau_connector *nv_connector = nouveau_crtc_connector_get(nv_crtc); struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct drm_display_mode *output_mode = &nv_encoder->mode; - struct drm_connector *connector = &nv_connector->base; uint32_t mode_ratio, panel_ratio; NV_DEBUG_KMS(dev, "Output mode on CRTC %d:\n", nv_crtc->index); @@ -341,15 +340,10 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, output_mode->clock > 165000) regp->fp_control |= (2 << 24); if (nv_encoder->dcb->type == OUTPUT_LVDS) { - bool duallink = false, dummy; - if (nv_connector->edid && - nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { - duallink = (((u8 *)nv_connector->edid)[121] == 2); - } else { - nouveau_bios_parse_lvds_table(dev, output_mode->clock, - &duallink, &dummy); - } + bool duallink, dummy; + nouveau_bios_parse_lvds_table(dev, output_mode->clock, + &duallink, &dummy); if (duallink) regp->fp_control |= (8 << 28); } else @@ -413,9 +407,7 @@ static void nv04_dfp_mode_set(struct drm_encoder *encoder, } /* Output property. */ - if ((nv_connector->dithering_mode == DITHERING_MODE_ON) || - (nv_connector->dithering_mode == DITHERING_MODE_AUTO && - encoder->crtc->fb->depth > connector->display_info.bpc * 3)) { + if (nv_connector->use_dithering) { if (dev_priv->chipset == 0x11) regp->dither = savep->dither | 0x00010000; else { diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_display.c b/trunk/drivers/gpu/drm/nouveau/nv04_display.c index 7047d37e8dab..6bd8518d7b2e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_display.c @@ -243,11 +243,6 @@ nv04_display_init(struct drm_device *dev) return 0; } -void -nv04_display_fini(struct drm_device *dev) -{ -} - static void nv04_vblank_crtc0_isr(struct drm_device *dev) { diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_pm.c b/trunk/drivers/gpu/drm/nouveau/nv04_pm.c index 6e7589918fa9..9ae92a87b8cc 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_pm.c @@ -27,111 +27,68 @@ #include "nouveau_hw.h" #include "nouveau_pm.h" -int -nv04_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ - int ret; - - ret = nouveau_hw_get_clock(dev, PLL_CORE); - if (ret < 0) - return ret; - perflvl->core = ret; - - ret = nouveau_hw_get_clock(dev, PLL_MEMORY); - if (ret < 0) - return ret; - perflvl->memory = ret; - - return 0; -} - -struct nv04_pm_clock { +struct nv04_pm_state { struct pll_lims pll; struct nouveau_pll_vals calc; }; -struct nv04_pm_state { - struct nv04_pm_clock core; - struct nv04_pm_clock memory; -}; - -static int -calc_pll(struct drm_device *dev, u32 id, int khz, struct nv04_pm_clock *clk) +int +nv04_pm_clock_get(struct drm_device *dev, u32 id) { - int ret; - - ret = get_pll_limits(dev, id, &clk->pll); - if (ret) - return ret; - - ret = nouveau_calc_pll_mnp(dev, &clk->pll, khz, &clk->calc); - if (!ret) - return -EINVAL; - - return 0; + return nouveau_hw_get_clock(dev, id); } void * -nv04_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) +nv04_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, + u32 id, int khz) { - struct nv04_pm_state *info; + struct nv04_pm_state *state; int ret; - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) return ERR_PTR(-ENOMEM); - ret = calc_pll(dev, PLL_CORE, perflvl->core, &info->core); - if (ret) - goto error; + ret = get_pll_limits(dev, id, &state->pll); + if (ret) { + kfree(state); + return (ret == -ENOENT) ? NULL : ERR_PTR(ret); + } - if (perflvl->memory) { - ret = calc_pll(dev, PLL_MEMORY, perflvl->memory, &info->memory); - if (ret) - goto error; + ret = nouveau_calc_pll_mnp(dev, &state->pll, khz, &state->calc); + if (!ret) { + kfree(state); + return ERR_PTR(-EINVAL); } - return info; -error: - kfree(info); - return ERR_PTR(ret); + return state; } -static void -prog_pll(struct drm_device *dev, struct nv04_pm_clock *clk) +void +nv04_pm_clock_set(struct drm_device *dev, void *pre_state) { struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 reg = clk->pll.reg; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + struct nv04_pm_state *state = pre_state; + u32 reg = state->pll.reg; /* thank the insane nouveau_hw_setpll() interface for this */ if (dev_priv->card_type >= NV_40) reg += 4; - nouveau_hw_setpll(dev, reg, &clk->calc); -} - -int -nv04_pm_clocks_set(struct drm_device *dev, void *pre_state) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct nv04_pm_state *state = pre_state; - - prog_pll(dev, &state->core); + nouveau_hw_setpll(dev, reg, &state->calc); - if (state->memory.pll.reg) { - prog_pll(dev, &state->memory); - if (dev_priv->card_type < NV_30) { - if (dev_priv->card_type == NV_20) - nv_mask(dev, 0x1002c4, 0, 1 << 20); + if (dev_priv->card_type < NV_30 && reg == NV_PRAMDAC_MPLL_COEFF) { + if (dev_priv->card_type == NV_20) + nv_mask(dev, 0x1002c4, 0, 1 << 20); - /* Reset the DLLs */ - nv_mask(dev, 0x1002c0, 0, 1 << 8); - } + /* Reset the DLLs */ + nv_mask(dev, 0x1002c0, 0, 1 << 8); } - ptimer->init(dev); + if (reg == NV_PRAMDAC_NVPLL_COEFF) + ptimer->init(dev); kfree(state); - return 0; } + diff --git a/trunk/drivers/gpu/drm/nouveau/nv04_timer.c b/trunk/drivers/gpu/drm/nouveau/nv04_timer.c index 55c945290e52..263301b809dd 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv04_timer.c +++ b/trunk/drivers/gpu/drm/nouveau/nv04_timer.c @@ -2,7 +2,6 @@ #include "drm.h" #include "nouveau_drv.h" #include "nouveau_drm.h" -#include "nouveau_hw.h" int nv04_timer_init(struct drm_device *dev) @@ -18,7 +17,7 @@ nv04_timer_init(struct drm_device *dev) /* determine base clock for timer source */ if (dev_priv->chipset < 0x40) { - n = nouveau_hw_get_clock(dev, PLL_CORE); + n = dev_priv->engine.pm.clock_get(dev, PLL_CORE); } else if (dev_priv->chipset == 0x40) { /*XXX: figure this out */ diff --git a/trunk/drivers/gpu/drm/nouveau/nv10_gpio.c b/trunk/drivers/gpu/drm/nouveau/nv10_gpio.c index 550ad3fcf0af..007fc29e2f86 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv10_gpio.c +++ b/trunk/drivers/gpu/drm/nouveau/nv10_gpio.c @@ -27,97 +27,66 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_hw.h" -#include "nouveau_gpio.h" -int -nv10_gpio_sense(struct drm_device *dev, int line) +static bool +get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift, + uint32_t *mask) { - if (line < 2) { - line = line * 16; - line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line; - return !!(line & 0x0100); - } else - if (line < 10) { - line = (line - 2) * 4; - line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line; - return !!(line & 0x04); - } else - if (line < 14) { - line = (line - 10) * 4; - line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line; - return !!(line & 0x04); - } + if (ent->line < 2) { + *reg = NV_PCRTC_GPIO; + *shift = ent->line * 16; + *mask = 0x11; - return -EINVAL; -} + } else if (ent->line < 10) { + *reg = NV_PCRTC_GPIO_EXT; + *shift = (ent->line - 2) * 4; + *mask = 0x3; + + } else if (ent->line < 14) { + *reg = NV_PCRTC_850; + *shift = (ent->line - 10) * 4; + *mask = 0x3; -int -nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out) -{ - u32 reg, mask, data; - - if (line < 2) { - line = line * 16; - reg = NV_PCRTC_GPIO; - mask = 0x00000011; - data = (dir << 4) | out; - } else - if (line < 10) { - line = (line - 2) * 4; - reg = NV_PCRTC_GPIO_EXT; - mask = 0x00000003 << ((line - 2) * 4); - data = (dir << 1) | out; - } else - if (line < 14) { - line = (line - 10) * 4; - reg = NV_PCRTC_850; - mask = 0x00000003; - data = (dir << 1) | out; } else { - return -EINVAL; + return false; } - mask = NVReadCRTC(dev, 0, reg) & ~(mask << line); - NVWriteCRTC(dev, 0, reg, mask | (data << line)); - return 0; + return true; } -void -nv10_gpio_irq_enable(struct drm_device *dev, int line, bool on) +int +nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) { - u32 mask = 0x00010001 << line; + struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); + uint32_t reg, shift, mask, value; - nv_wr32(dev, 0x001104, mask); - nv_mask(dev, 0x001144, mask, on ? mask : 0); -} + if (!ent) + return -ENODEV; -static void -nv10_gpio_isr(struct drm_device *dev) -{ - u32 intr = nv_rd32(dev, 0x1104); - u32 hi = (intr & 0x0000ffff) >> 0; - u32 lo = (intr & 0xffff0000) >> 16; + if (!get_gpio_location(ent, ®, &shift, &mask)) + return -ENODEV; - nouveau_gpio_isr(dev, 0, hi | lo); + value = NVReadCRTC(dev, 0, reg) >> shift; - nv_wr32(dev, 0x001104, intr); + return (ent->invert ? 1 : 0) ^ (value & 1); } int -nv10_gpio_init(struct drm_device *dev) +nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) { - nv_wr32(dev, 0x001140, 0x00000000); - nv_wr32(dev, 0x001100, 0xffffffff); - nv_wr32(dev, 0x001144, 0x00000000); - nv_wr32(dev, 0x001104, 0xffffffff); - nouveau_irq_register(dev, 28, nv10_gpio_isr); /* PBUS */ - return 0; -} + struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); + uint32_t reg, shift, mask, value; -void -nv10_gpio_fini(struct drm_device *dev) -{ - nv_wr32(dev, 0x001140, 0x00000000); - nv_wr32(dev, 0x001144, 0x00000000); - nouveau_irq_unregister(dev, 28); + if (!ent) + return -ENODEV; + + if (!get_gpio_location(ent, ®, &shift, &mask)) + return -ENODEV; + + value = ((ent->invert ? 1 : 0) ^ (state ? 1 : 0)) << shift; + mask = ~(mask << shift); + + NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask)); + + return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv17_tv.c b/trunk/drivers/gpu/drm/nouveau/nv17_tv.c index 696d7e7dc2a0..3900cebba560 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv17_tv.c +++ b/trunk/drivers/gpu/drm/nouveau/nv17_tv.c @@ -30,7 +30,6 @@ #include "nouveau_encoder.h" #include "nouveau_connector.h" #include "nouveau_crtc.h" -#include "nouveau_gpio.h" #include "nouveau_hw.h" #include "nv17_tv.h" @@ -38,6 +37,7 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) { struct drm_device *dev = encoder->dev; struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; uint32_t testval, regoffset = nv04_dac_output_offset(encoder); uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; @@ -53,8 +53,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) head = (dacclk & 0x100) >> 8; /* Save the previous state. */ - gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); - gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); + gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); + gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); @@ -65,8 +65,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); /* Prepare the DAC for load detection. */ - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, true); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, true); + gpio->set(dev, DCB_GPIO_TVDAC1, true); + gpio->set(dev, DCB_GPIO_TVDAC0, true); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); @@ -111,8 +111,8 @@ static uint32_t nv42_tv_sample_load(struct drm_encoder *encoder) NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, gpio1); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, gpio0); + gpio->set(dev, DCB_GPIO_TVDAC1, gpio1); + gpio->set(dev, DCB_GPIO_TVDAC0, gpio0); return sample; } @@ -357,6 +357,8 @@ static bool nv17_tv_mode_fixup(struct drm_encoder *encoder, static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) { struct drm_device *dev = encoder->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); @@ -381,8 +383,8 @@ static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) nv_load_ptv(dev, regs, 200); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); - nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); + gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); + gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); } diff --git a/trunk/drivers/gpu/drm/nouveau/nv40_pm.c b/trunk/drivers/gpu/drm/nouveau/nv40_pm.c index c7615381c5d9..e676b0d53478 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv40_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nv40_pm.c @@ -222,7 +222,7 @@ nv40_pm_gr_idle(void *data) return true; } -int +void nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -231,7 +231,7 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) struct bit_entry M; u32 crtc_mask = 0; u8 sr1[2]; - int i, ret = -EAGAIN; + int i; /* determine which CRTCs are active, fetch VGA_SR1 for each */ for (i = 0; i < 2; i++) { @@ -263,8 +263,6 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) if (!nv_wait_cb(dev, nv40_pm_gr_idle, dev)) goto resume; - ret = 0; - /* set engine clocks */ nv_mask(dev, 0x00c040, 0x00000333, 0x00000000); nv_wr32(dev, 0x004004, info->npll_coef); @@ -347,48 +345,4 @@ nv40_pm_clocks_set(struct drm_device *dev, void *pre_state) spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); kfree(info); - return ret; -} - -int -nv40_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) -{ - if (line == 2) { - u32 reg = nv_rd32(dev, 0x0010f0); - if (reg & 0x80000000) { - *duty = (reg & 0x7fff0000) >> 16; - *divs = (reg & 0x00007fff); - return 0; - } - } else - if (line == 9) { - u32 reg = nv_rd32(dev, 0x0015f4); - if (reg & 0x80000000) { - *divs = nv_rd32(dev, 0x0015f8); - *duty = (reg & 0x7fffffff); - return 0; - } - } else { - NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); - return -ENODEV; - } - - return -EINVAL; -} - -int -nv40_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) -{ - if (line == 2) { - nv_wr32(dev, 0x0010f0, 0x80000000 | (duty << 16) | divs); - } else - if (line == 9) { - nv_wr32(dev, 0x0015f8, divs); - nv_wr32(dev, 0x0015f4, duty | 0x80000000); - } else { - NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", line); - return -ENODEV; - } - - return 0; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c b/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c index 8f6c2ace3adf..882080e0b4f5 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_crtc.c @@ -132,42 +132,33 @@ nv50_crtc_blank(struct nouveau_crtc *nv_crtc, bool blanked) } static int -nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) +nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) { - struct nouveau_channel *evo = nv50_display(nv_crtc->base.dev)->master; - struct nouveau_connector *nv_connector; - struct drm_connector *connector; - int head = nv_crtc->index, ret; - u32 mode = 0x00; + struct drm_device *dev = nv_crtc->base.dev; + struct nouveau_channel *evo = nv50_display(dev)->master; + int ret; - nv_connector = nouveau_crtc_connector_get(nv_crtc); - connector = &nv_connector->base; - if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { - if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) - mode = DITHERING_MODE_DYNAMIC2X2; - } else { - mode = nv_connector->dithering_mode; - } + NV_DEBUG_KMS(dev, "\n"); - if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) { - if (connector->display_info.bpc >= 8) - mode |= DITHERING_DEPTH_8BPC; - } else { - mode |= nv_connector->dithering_depth; + ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); + if (ret) { + NV_ERROR(dev, "no space while setting dither\n"); + return ret; } - ret = RING_SPACE(evo, 2 + (update ? 2 : 0)); - if (ret == 0) { - BEGIN_RING(evo, 0, NV50_EVO_CRTC(head, DITHER_CTRL), 1); - OUT_RING (evo, mode); - if (update) { - BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); - OUT_RING (evo, 0); - FIRE_RING (evo); - } + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DITHER_CTRL), 1); + if (on) + OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_ON); + else + OUT_RING(evo, NV50_EVO_CRTC_DITHER_CTRL_OFF); + + if (update) { + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); } - return ret; + return 0; } struct nouveau_connector * @@ -189,103 +180,80 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) } static int -nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) +nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) { - struct nouveau_connector *nv_connector; - struct drm_crtc *crtc = &nv_crtc->base; - struct drm_device *dev = crtc->dev; + struct nouveau_connector *nv_connector = + nouveau_crtc_connector_get(nv_crtc); + struct drm_device *dev = nv_crtc->base.dev; struct nouveau_channel *evo = nv50_display(dev)->master; - struct drm_display_mode *umode = &crtc->mode; - struct drm_display_mode *omode; - int scaling_mode, ret; - u32 ctrl = 0, oX, oY; + struct drm_display_mode *native_mode = NULL; + struct drm_display_mode *mode = &nv_crtc->base.mode; + uint32_t outX, outY, horiz, vert; + int ret; NV_DEBUG_KMS(dev, "\n"); - nv_connector = nouveau_crtc_connector_get(nv_crtc); - if (!nv_connector || !nv_connector->native_mode) { - NV_ERROR(dev, "no native mode, forcing panel scaling\n"); - scaling_mode = DRM_MODE_SCALE_NONE; - } else { - scaling_mode = nv_connector->scaling_mode; - } - - /* start off at the resolution we programmed the crtc for, this - * effectively handles NONE/FULL scaling - */ - if (scaling_mode != DRM_MODE_SCALE_NONE) - omode = nv_connector->native_mode; - else - omode = umode; - - oX = omode->hdisplay; - oY = omode->vdisplay; - if (omode->flags & DRM_MODE_FLAG_DBLSCAN) - oY *= 2; - - /* add overscan compensation if necessary, will keep the aspect - * ratio the same as the backend mode unless overridden by the - * user setting both hborder and vborder properties. - */ - if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON || - (nv_connector->underscan == UNDERSCAN_AUTO && - nv_connector->edid && - drm_detect_hdmi_monitor(nv_connector->edid)))) { - u32 bX = nv_connector->underscan_hborder; - u32 bY = nv_connector->underscan_vborder; - u32 aspect = (oY << 19) / oX; - - if (bX) { - oX -= (bX * 2); - if (bY) oY -= (bY * 2); - else oY = ((oX * aspect) + (aspect / 2)) >> 19; + switch (scaling_mode) { + case DRM_MODE_SCALE_NONE: + break; + default: + if (!nv_connector || !nv_connector->native_mode) { + NV_ERROR(dev, "No native mode, forcing panel scaling\n"); + scaling_mode = DRM_MODE_SCALE_NONE; } else { - oX -= (oX >> 4) + 32; - if (bY) oY -= (bY * 2); - else oY = ((oX * aspect) + (aspect / 2)) >> 19; + native_mode = nv_connector->native_mode; } + break; } - /* handle CENTER/ASPECT scaling, taking into account the areas - * removed already for overscan compensation - */ switch (scaling_mode) { - case DRM_MODE_SCALE_CENTER: - oX = min((u32)umode->hdisplay, oX); - oY = min((u32)umode->vdisplay, oY); - /* fall-through */ case DRM_MODE_SCALE_ASPECT: - if (oY < oX) { - u32 aspect = (umode->hdisplay << 19) / umode->vdisplay; - oX = ((oY * aspect) + (aspect / 2)) >> 19; + horiz = (native_mode->hdisplay << 19) / mode->hdisplay; + vert = (native_mode->vdisplay << 19) / mode->vdisplay; + + if (vert > horiz) { + outX = (mode->hdisplay * horiz) >> 19; + outY = (mode->vdisplay * horiz) >> 19; } else { - u32 aspect = (umode->vdisplay << 19) / umode->hdisplay; - oY = ((oX * aspect) + (aspect / 2)) >> 19; + outX = (mode->hdisplay * vert) >> 19; + outY = (mode->vdisplay * vert) >> 19; } break; + case DRM_MODE_SCALE_FULLSCREEN: + outX = native_mode->hdisplay; + outY = native_mode->vdisplay; + break; + case DRM_MODE_SCALE_CENTER: + case DRM_MODE_SCALE_NONE: default: + outX = mode->hdisplay; + outY = mode->vdisplay; break; } - if (umode->hdisplay != oX || umode->vdisplay != oY || - umode->flags & DRM_MODE_FLAG_INTERLACE || - umode->flags & DRM_MODE_FLAG_DBLSCAN) - ctrl |= NV50_EVO_CRTC_SCALE_CTRL_ACTIVE; - - ret = RING_SPACE(evo, 5); + ret = RING_SPACE(evo, update ? 7 : 5); if (ret) return ret; + /* Got a better name for SCALER_ACTIVE? */ + /* One day i've got to really figure out why this is needed. */ BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CTRL), 1); - OUT_RING (evo, ctrl); + if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) || + (mode->flags & DRM_MODE_FLAG_INTERLACE) || + mode->hdisplay != outX || mode->vdisplay != outY) { + OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_ACTIVE); + } else { + OUT_RING(evo, NV50_EVO_CRTC_SCALE_CTRL_INACTIVE); + } + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_RES1), 2); - OUT_RING (evo, oY << 16 | oX); - OUT_RING (evo, oY << 16 | oX); + OUT_RING(evo, outY << 16 | outX); + OUT_RING(evo, outY << 16 | outX); if (update) { - nv50_display_flip_stop(crtc); - nv50_display_sync(dev); - nv50_display_flip_next(crtc, crtc->fb, NULL); + BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); + OUT_RING(evo, 0); + FIRE_RING(evo); } return 0; @@ -365,6 +333,7 @@ nv50_crtc_destroy(struct drm_crtc *crtc) nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); nouveau_bo_unmap(nv_crtc->cursor.nvbo); nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo); + kfree(nv_crtc->mode); kfree(nv_crtc); } @@ -472,6 +441,39 @@ nv50_crtc_dpms(struct drm_crtc *crtc, int mode) { } +static int +nv50_crtc_wait_complete(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; + struct nv50_display *disp = nv50_display(dev); + struct nouveau_channel *evo = disp->master; + u64 start; + int ret; + + ret = RING_SPACE(evo, 6); + if (ret) + return ret; + BEGIN_RING(evo, 0, 0x0084, 1); + OUT_RING (evo, 0x80000000); + BEGIN_RING(evo, 0, 0x0080, 1); + OUT_RING (evo, 0); + BEGIN_RING(evo, 0, 0x0084, 1); + OUT_RING (evo, 0x00000000); + + nv_wo32(disp->ntfy, 0x000, 0x00000000); + FIRE_RING (evo); + + start = ptimer->read(dev); + do { + if (nv_ro32(disp->ntfy, 0x000)) + return 0; + } while (ptimer->read(dev) - start < 2000000000ULL); + + return -EBUSY; +} + static void nv50_crtc_prepare(struct drm_crtc *crtc) { @@ -495,7 +497,7 @@ nv50_crtc_commit(struct drm_crtc *crtc) nv50_crtc_blank(nv_crtc, false); drm_vblank_post_modeset(dev, nv_crtc->index); - nv50_display_sync(dev); + nv50_crtc_wait_complete(crtc); nv50_display_flip_next(crtc, crtc->fb, NULL); } @@ -591,76 +593,90 @@ nv50_crtc_do_mode_set_base(struct drm_crtc *crtc, } static int -nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, - struct drm_display_mode *mode, int x, int y, +nv50_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode, int x, int y, struct drm_framebuffer *old_fb) { struct drm_device *dev = crtc->dev; struct nouveau_channel *evo = nv50_display(dev)->master; struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - u32 head = nv_crtc->index * 0x400; - u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1; - u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1; - u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks; - u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks; - u32 vblan2e = 0, vblan2s = 1; + struct nouveau_connector *nv_connector = NULL; + uint32_t hsync_dur, vsync_dur, hsync_start_to_end, vsync_start_to_end; + uint32_t hunk1, vunk1, vunk2a, vunk2b; int ret; - /* hw timing description looks like this: - * - * <---------display---------> - * ______ - * |____________|---------------------------|____________| - * - * ^ synce ^ blanke ^ blanks ^ active - * - * interlaced modes also have 2 additional values pointing at the end - * and start of the next field's blanking period. - */ + /* Find the connector attached to this CRTC */ + nv_connector = nouveau_crtc_connector_get(nv_crtc); + + *nv_crtc->mode = *adjusted_mode; + + NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); - hactive = mode->htotal; - hsynce = mode->hsync_end - mode->hsync_start - 1; - hbackp = mode->htotal - mode->hsync_end; - hblanke = hsynce + hbackp; - hfrontp = mode->hsync_start - mode->hdisplay; - hblanks = mode->htotal - hfrontp - 1; - - vactive = mode->vtotal * vscan / ilace; - vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1; - vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace; - vblanke = vsynce + vbackp; - vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; - vblanks = vactive - vfrontp - 1; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vblan2e = vactive + vsynce + vbackp; - vblan2s = vblan2e + (mode->vdisplay * vscan / ilace); - vactive = (vactive * 2) + 1; + hsync_dur = adjusted_mode->hsync_end - adjusted_mode->hsync_start; + vsync_dur = adjusted_mode->vsync_end - adjusted_mode->vsync_start; + hsync_start_to_end = adjusted_mode->htotal - adjusted_mode->hsync_start; + vsync_start_to_end = adjusted_mode->vtotal - adjusted_mode->vsync_start; + /* I can't give this a proper name, anyone else can? */ + hunk1 = adjusted_mode->htotal - + adjusted_mode->hsync_start + adjusted_mode->hdisplay; + vunk1 = adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vdisplay; + /* Another strange value, this time only for interlaced adjusted_modes. */ + vunk2a = 2 * adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vdisplay; + vunk2b = adjusted_mode->vtotal - + adjusted_mode->vsync_start + adjusted_mode->vtotal; + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + vsync_dur /= 2; + vsync_start_to_end /= 2; + vunk1 /= 2; + vunk2a /= 2; + vunk2b /= 2; + /* magic */ + if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN) { + vsync_start_to_end -= 1; + vunk1 -= 1; + vunk2a -= 1; + vunk2b -= 1; + } } - ret = RING_SPACE(evo, 18); - if (ret == 0) { - BEGIN_RING(evo, 0, 0x0804 + head, 2); - OUT_RING (evo, 0x00800000 | mode->clock); - OUT_RING (evo, (ilace == 2) ? 2 : 0); - BEGIN_RING(evo, 0, 0x0810 + head, 6); - OUT_RING (evo, 0x00000000); /* border colour */ - OUT_RING (evo, (vactive << 16) | hactive); - OUT_RING (evo, ( vsynce << 16) | hsynce); - OUT_RING (evo, (vblanke << 16) | hblanke); - OUT_RING (evo, (vblanks << 16) | hblanks); - OUT_RING (evo, (vblan2e << 16) | vblan2s); - BEGIN_RING(evo, 0, 0x082c + head, 1); - OUT_RING (evo, 0x00000000); - BEGIN_RING(evo, 0, 0x0900 + head, 1); - OUT_RING (evo, 0x00000311); /* makes sync channel work */ - BEGIN_RING(evo, 0, 0x08c8 + head, 1); - OUT_RING (evo, (umode->vdisplay << 16) | umode->hdisplay); - BEGIN_RING(evo, 0, 0x08d4 + head, 1); - OUT_RING (evo, 0x00000000); /* screen position */ + ret = RING_SPACE(evo, 17); + if (ret) + return ret; + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLOCK), 2); + OUT_RING(evo, adjusted_mode->clock | 0x800000); + OUT_RING(evo, (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 0); + + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, DISPLAY_START), 5); + OUT_RING(evo, 0); + OUT_RING(evo, (adjusted_mode->vtotal << 16) | adjusted_mode->htotal); + OUT_RING(evo, (vsync_dur - 1) << 16 | (hsync_dur - 1)); + OUT_RING(evo, (vsync_start_to_end - 1) << 16 | + (hsync_start_to_end - 1)); + OUT_RING(evo, (vunk1 - 1) << 16 | (hunk1 - 1)); + + if (adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK0824), 1); + OUT_RING(evo, (vunk2b - 1) << 16 | (vunk2a - 1)); + } else { + OUT_RING(evo, 0); + OUT_RING(evo, 0); } - nv_crtc->set_dither(nv_crtc, false); - nv_crtc->set_scale(nv_crtc, false); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, UNK082C), 1); + OUT_RING(evo, 0); + + /* This is the actual resolution of the mode. */ + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, REAL_RES), 1); + OUT_RING(evo, (mode->vdisplay << 16) | mode->hdisplay); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, SCALE_CENTER_OFFSET), 1); + OUT_RING(evo, NV50_EVO_CRTC_SCALE_CENTER_OFFSET_VAL(0, 0)); + + nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false); + nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false); return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false); } @@ -676,7 +692,7 @@ nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, if (ret) return ret; - ret = nv50_display_sync(crtc->dev); + ret = nv50_crtc_wait_complete(crtc); if (ret) return ret; @@ -695,7 +711,7 @@ nv50_crtc_mode_set_base_atomic(struct drm_crtc *crtc, if (ret) return ret; - return nv50_display_sync(crtc->dev); + return nv50_crtc_wait_complete(crtc); } static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = { @@ -721,6 +737,12 @@ nv50_crtc_create(struct drm_device *dev, int index) if (!nv_crtc) return -ENOMEM; + nv_crtc->mode = kzalloc(sizeof(*nv_crtc->mode), GFP_KERNEL); + if (!nv_crtc->mode) { + kfree(nv_crtc); + return -ENOMEM; + } + /* Default CLUT parameters, will be activated on the hw upon * first mode set. */ @@ -742,6 +764,7 @@ nv50_crtc_create(struct drm_device *dev, int index) } if (ret) { + kfree(nv_crtc->mode); kfree(nv_crtc); return ret; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_dac.c b/trunk/drivers/gpu/drm/nouveau/nv50_dac.c index a0f2bebf49e3..808f3ec8f827 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_dac.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_dac.c @@ -199,6 +199,11 @@ nv50_dac_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, return true; } +static void +nv50_dac_prepare(struct drm_encoder *encoder) +{ +} + static void nv50_dac_commit(struct drm_encoder *encoder) { @@ -261,7 +266,7 @@ static const struct drm_encoder_helper_funcs nv50_dac_helper_funcs = { .save = nv50_dac_save, .restore = nv50_dac_restore, .mode_fixup = nv50_dac_mode_fixup, - .prepare = nv50_dac_disconnect, + .prepare = nv50_dac_prepare, .commit = nv50_dac_commit, .mode_set = nv50_dac_mode_set, .get_crtc = nv50_dac_crtc_get, diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_display.c b/trunk/drivers/gpu/drm/nouveau/nv50_display.c index 7ba28e08ee31..06de250fe617 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_display.c @@ -50,53 +50,9 @@ nv50_sor_nr(struct drm_device *dev) return 4; } -static int -evo_icmd(struct drm_device *dev, int ch, u32 mthd, u32 data) -{ - int ret = 0; - nv_mask(dev, 0x610300 + (ch * 0x08), 0x00000001, 0x00000001); - nv_wr32(dev, 0x610304 + (ch * 0x08), data); - nv_wr32(dev, 0x610300 + (ch * 0x08), 0x80000001 | mthd); - if (!nv_wait(dev, 0x610300 + (ch * 0x08), 0x80000000, 0x00000000)) - ret = -EBUSY; - if (ret || (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)) - NV_INFO(dev, "EvoPIO: %d 0x%04x 0x%08x\n", ch, mthd, data); - nv_mask(dev, 0x610300 + (ch * 0x08), 0x00000001, 0x00000000); - return ret; -} - int nv50_display_early_init(struct drm_device *dev) { - u32 ctrl = nv_rd32(dev, 0x610200); - int i; - - /* check if master evo channel is already active, a good a sign as any - * that the display engine is in a weird state (hibernate/kexec), if - * it is, do our best to reset the display engine... - */ - if ((ctrl & 0x00000003) == 0x00000003) { - NV_INFO(dev, "PDISP: EVO(0) 0x%08x, resetting...\n", ctrl); - - /* deactivate both heads first, PDISP will disappear forever - * (well, until you power cycle) on some boards as soon as - * PMC_ENABLE is hit unless they are.. - */ - for (i = 0; i < 2; i++) { - evo_icmd(dev, 0, 0x0880 + (i * 0x400), 0x05000000); - evo_icmd(dev, 0, 0x089c + (i * 0x400), 0); - evo_icmd(dev, 0, 0x0840 + (i * 0x400), 0); - evo_icmd(dev, 0, 0x0844 + (i * 0x400), 0); - evo_icmd(dev, 0, 0x085c + (i * 0x400), 0); - evo_icmd(dev, 0, 0x0874 + (i * 0x400), 0); - } - evo_icmd(dev, 0, 0x0080, 0); - - /* reset PDISP */ - nv_mask(dev, 0x000200, 0x40000000, 0x00000000); - nv_mask(dev, 0x000200, 0x40000000, 0x40000000); - } - return 0; } @@ -105,41 +61,12 @@ nv50_display_late_takedown(struct drm_device *dev) { } -int -nv50_display_sync(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; - struct nv50_display *disp = nv50_display(dev); - struct nouveau_channel *evo = disp->master; - u64 start; - int ret; - - ret = RING_SPACE(evo, 6); - if (ret == 0) { - BEGIN_RING(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x80000000); - BEGIN_RING(evo, 0, 0x0080, 1); - OUT_RING (evo, 0); - BEGIN_RING(evo, 0, 0x0084, 1); - OUT_RING (evo, 0x00000000); - - nv_wo32(disp->ntfy, 0x000, 0x00000000); - FIRE_RING (evo); - - start = ptimer->read(dev); - do { - if (nv_ro32(disp->ntfy, 0x000)) - return 0; - } while (ptimer->read(dev) - start < 2000000000ULL); - } - - return -EBUSY; -} - int nv50_display_init(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct drm_connector *connector; struct nouveau_channel *evo; int ret, i; u32 val; @@ -234,6 +161,16 @@ nv50_display_init(struct drm_device *dev) NV50_PDISPLAY_INTR_EN_1_CLK_UNK20 | NV50_PDISPLAY_INTR_EN_1_CLK_UNK40); + /* enable hotplug interrupts */ + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct nouveau_connector *conn = nouveau_connector(connector); + + if (conn->dcb->gpio_tag == 0xff) + continue; + + pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); + } + ret = nv50_evo_init(dev); if (ret) return ret; @@ -241,19 +178,36 @@ nv50_display_init(struct drm_device *dev) nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9); - ret = RING_SPACE(evo, 3); + ret = RING_SPACE(evo, 15); if (ret) return ret; BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2); - OUT_RING (evo, NV50_EVO_UNK84_NOTIFY_DISABLED); - OUT_RING (evo, NvEvoSync); + OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED); + OUT_RING(evo, NvEvoSync); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1); + OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1); + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, DISPLAY_START), 1); + OUT_RING(evo, 0); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1); + OUT_RING(evo, 0); + /* required to make display sync channels not hate life */ + BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1); + OUT_RING (evo, 0x00000311); + BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1); + OUT_RING (evo, 0x00000311); + FIRE_RING(evo); + if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2)) + NV_ERROR(dev, "evo pushbuf stalled\n"); + - return nv50_display_sync(dev); + return 0; } -void -nv50_display_fini(struct drm_device *dev) +static int nv50_display_disable(struct drm_device *dev) { + struct drm_nouveau_private *dev_priv = dev->dev_private; struct nv50_display *disp = nv50_display(dev); struct nouveau_channel *evo = disp->master; struct drm_crtc *drm_crtc; @@ -316,10 +270,18 @@ nv50_display_fini(struct drm_device *dev) /* disable interrupts. */ nv_wr32(dev, NV50_PDISPLAY_INTR_EN_1, 0x00000000); + + /* disable hotplug interrupts */ + nv_wr32(dev, 0xe054, 0xffffffff); + nv_wr32(dev, 0xe050, 0x00000000); + if (dev_priv->chipset >= 0x90) { + nv_wr32(dev, 0xe074, 0xffffffff); + nv_wr32(dev, 0xe070, 0x00000000); + } + return 0; } -int -nv50_display_create(struct drm_device *dev) +int nv50_display_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct dcb_table *dcb = &dev_priv->vbios.dcb; @@ -379,7 +341,7 @@ nv50_display_create(struct drm_device *dev) tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev); nouveau_irq_register(dev, 26, nv50_display_isr); - ret = nv50_evo_create(dev); + ret = nv50_display_init(dev); if (ret) { nv50_display_destroy(dev); return ret; @@ -395,7 +357,7 @@ nv50_display_destroy(struct drm_device *dev) NV_DEBUG_KMS(dev, "\n"); - nv50_evo_destroy(dev); + nv50_display_disable(dev); nouveau_irq_unregister(dev, 26); kfree(disp); } @@ -559,7 +521,7 @@ nv50_display_script_select(struct drm_device *dev, struct dcb_entry *dcb, } else { /* determine number of lvds links */ if (nv_connector && nv_connector->edid && - nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { + nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { /* http://www.spwg.org */ if (((u8 *)nv_connector->edid)[121] == 2) script |= 0x0100; @@ -760,8 +722,8 @@ nv50_display_unk20_handler(struct drm_device *dev) if (crtc >= 0) { pclk = nv_rd32(dev, NV50_PDISPLAY_CRTC_P(crtc, CLOCK)); pclk &= 0x003fffff; - if (pclk) - nv50_crtc_set_clock(dev, crtc, pclk); + + nv50_crtc_set_clock(dev, crtc, pclk); tmp = nv_rd32(dev, NV50_PDISPLAY_CRTC_CLK_CTRL2(crtc)); tmp &= ~0x000000f; diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_display.h b/trunk/drivers/gpu/drm/nouveau/nv50_display.h index 95874f7c043c..c2da503a22aa 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_display.h +++ b/trunk/drivers/gpu/drm/nouveau/nv50_display.h @@ -69,18 +69,14 @@ int nv50_display_early_init(struct drm_device *dev); void nv50_display_late_takedown(struct drm_device *dev); int nv50_display_create(struct drm_device *dev); int nv50_display_init(struct drm_device *dev); -void nv50_display_fini(struct drm_device *dev); void nv50_display_destroy(struct drm_device *dev); int nv50_crtc_blank(struct nouveau_crtc *, bool blank); int nv50_crtc_set_clock(struct drm_device *, int head, int pclk); -int nv50_display_sync(struct drm_device *); int nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *, struct nouveau_channel *chan); void nv50_display_flip_stop(struct drm_crtc *); -int nv50_evo_create(struct drm_device *dev); -void nv50_evo_destroy(struct drm_device *dev); int nv50_evo_init(struct drm_device *dev); void nv50_evo_fini(struct drm_device *dev); void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base, diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_evo.c b/trunk/drivers/gpu/drm/nouveau/nv50_evo.c index 9b962e989d7c..c99d9751880c 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_evo.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_evo.c @@ -218,7 +218,7 @@ nv50_evo_channel_fini(struct nouveau_channel *evo) } } -void +static void nv50_evo_destroy(struct drm_device *dev) { struct nv50_display *disp = nv50_display(dev); @@ -235,7 +235,7 @@ nv50_evo_destroy(struct drm_device *dev) nv50_evo_channel_del(&disp->master); } -int +static int nv50_evo_create(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; @@ -388,6 +388,12 @@ nv50_evo_init(struct drm_device *dev) struct nv50_display *disp = nv50_display(dev); int ret, i; + if (!disp->master) { + ret = nv50_evo_create(dev); + if (ret) + return ret; + } + ret = nv50_evo_channel_init(disp->master); if (ret) return ret; @@ -414,4 +420,6 @@ nv50_evo_fini(struct drm_device *dev) if (disp->master) nv50_evo_channel_fini(disp->master); + + nv50_evo_destroy(dev); } diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_fifo.c b/trunk/drivers/gpu/drm/nouveau/nv50_fifo.c index 3bc2a565c20b..c34a074f7ea1 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_fifo.c @@ -230,7 +230,6 @@ 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; - uint64_t ib_offset = chan->pushbuf_base + chan->dma.ib_base * 4; unsigned long flags; int ret; @@ -281,9 +280,8 @@ nv50_fifo_create_context(struct nouveau_channel *chan) nv_wo32(ramfc, 0x7c, 0x30000001); nv_wo32(ramfc, 0x78, 0x00000000); nv_wo32(ramfc, 0x3c, 0x403f6078); - nv_wo32(ramfc, 0x50, lower_32_bits(ib_offset)); - nv_wo32(ramfc, 0x54, upper_32_bits(ib_offset) | - drm_order(chan->dma.ib_max + 1) << 16); + nv_wo32(ramfc, 0x50, chan->pushbuf_base + chan->dma.ib_base * 4); + nv_wo32(ramfc, 0x54, drm_order(chan->dma.ib_max + 1) << 16); if (dev_priv->chipset != 0x50) { nv_wo32(chan->ramin, 0, chan->id); diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c b/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c index f429e6a8ca7a..793a5ccca121 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_gpio.c @@ -25,95 +25,229 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_hw.h" -#include "nouveau_gpio.h" #include "nv50_display.h" +static void nv50_gpio_isr(struct drm_device *dev); +static void nv50_gpio_isr_bh(struct work_struct *work); + +struct nv50_gpio_priv { + struct list_head handlers; + spinlock_t lock; +}; + +struct nv50_gpio_handler { + struct drm_device *dev; + struct list_head head; + struct work_struct work; + bool inhibit; + + struct dcb_gpio_entry *gpio; + + void (*handler)(void *data, int state); + void *data; +}; + static int -nv50_gpio_location(int line, u32 *reg, u32 *shift) +nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) { const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; - if (line >= 32) + if (gpio->line >= 32) return -EINVAL; - *reg = nv50_gpio_reg[line >> 3]; - *shift = (line & 7) << 2; + *reg = nv50_gpio_reg[gpio->line >> 3]; + *shift = (gpio->line & 7) << 2; return 0; } int -nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out) +nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) { - u32 reg, shift; + struct dcb_gpio_entry *gpio; + uint32_t r, s, v; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; - if (nv50_gpio_location(line, ®, &shift)) + if (nv50_gpio_location(gpio, &r, &s)) return -EINVAL; - nv_mask(dev, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); - return 0; + v = nv_rd32(dev, r) >> (s + 2); + return ((v & 1) == (gpio->state[1] & 1)); } int -nv50_gpio_sense(struct drm_device *dev, int line) +nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) { - u32 reg, shift; + struct dcb_gpio_entry *gpio; + uint32_t r, s, v; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; - if (nv50_gpio_location(line, ®, &shift)) + if (nv50_gpio_location(gpio, &r, &s)) return -EINVAL; - return !!(nv_rd32(dev, reg) & (4 << shift)); + v = nv_rd32(dev, r) & ~(0x3 << s); + v |= (gpio->state[state] ^ 2) << s; + nv_wr32(dev, r, v); + return 0; } -void -nv50_gpio_irq_enable(struct drm_device *dev, int line, bool on) +int +nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) { - u32 reg = line < 16 ? 0xe050 : 0xe070; - u32 mask = 0x00010001 << (line & 0xf); + struct dcb_gpio_entry *gpio; + u32 v; - nv_wr32(dev, reg + 4, mask); - nv_mask(dev, reg + 0, mask, on ? mask : 0); + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; + + v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); + v &= 0x00004000; + return (!!v == (gpio->state[1] & 1)); } int -nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out) +nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) { - u32 data = ((dir ^ 1) << 13) | (out << 12); - nv_mask(dev, 0x00d610 + (line * 4), 0x00003000, data); - nv_mask(dev, 0x00d604, 0x00000001, 0x00000001); /* update? */ + struct dcb_gpio_entry *gpio; + u32 v; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; + + v = gpio->state[state] ^ 2; + + nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); return 0; } int -nvd0_gpio_sense(struct drm_device *dev, int line) +nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, + void (*handler)(void *, int), void *data) { - return !!(nv_rd32(dev, 0x00d610 + (line * 4)) & 0x00004000); + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh; + struct dcb_gpio_entry *gpio; + unsigned long flags; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return -ENOENT; + + gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL); + if (!gpioh) + return -ENOMEM; + + INIT_WORK(&gpioh->work, nv50_gpio_isr_bh); + gpioh->dev = dev; + gpioh->gpio = gpio; + gpioh->handler = handler; + gpioh->data = data; + + spin_lock_irqsave(&priv->lock, flags); + list_add(&gpioh->head, &priv->handlers); + spin_unlock_irqrestore(&priv->lock, flags); + return 0; } -static void -nv50_gpio_isr(struct drm_device *dev) +void +nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, + void (*handler)(void *, int), void *data) { struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 intr0, intr1 = 0; - u32 hi, lo; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh, *tmp; + struct dcb_gpio_entry *gpio; + LIST_HEAD(tofree); + unsigned long flags; - intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); - if (dev_priv->chipset >= 0x90) - intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return; - hi = (intr0 & 0x0000ffff) | (intr1 << 16); - lo = (intr0 >> 16) | (intr1 & 0xffff0000); - nouveau_gpio_isr(dev, 0, hi | lo); + spin_lock_irqsave(&priv->lock, flags); + list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) { + if (gpioh->gpio != gpio || + gpioh->handler != handler || + gpioh->data != data) + continue; + list_move(&gpioh->head, &tofree); + } + spin_unlock_irqrestore(&priv->lock, flags); - nv_wr32(dev, 0xe054, intr0); - if (dev_priv->chipset >= 0x90) - nv_wr32(dev, 0xe074, intr1); + list_for_each_entry_safe(gpioh, tmp, &tofree, head) { + flush_work_sync(&gpioh->work); + kfree(gpioh); + } +} + +bool +nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) +{ + struct dcb_gpio_entry *gpio; + u32 reg, mask; + + gpio = nouveau_bios_gpio_entry(dev, tag); + if (!gpio) + return false; + + reg = gpio->line < 16 ? 0xe050 : 0xe070; + mask = 0x00010001 << (gpio->line & 0xf); + + nv_wr32(dev, reg + 4, mask); + reg = nv_mask(dev, reg + 0, mask, on ? mask : 0); + return (reg & mask) == mask; +} + +static int +nv50_gpio_create(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + INIT_LIST_HEAD(&priv->handlers); + spin_lock_init(&priv->lock); + pgpio->priv = priv; + return 0; +} + +static void +nv50_gpio_destroy(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + + kfree(pgpio->priv); + pgpio->priv = NULL; } int nv50_gpio_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + int ret; + + if (!pgpio->priv) { + ret = nv50_gpio_create(dev); + if (ret) + return ret; + } /* disable, and ack any pending gpio interrupts */ nv_wr32(dev, 0xe050, 0x00000000); @@ -136,4 +270,64 @@ nv50_gpio_fini(struct drm_device *dev) if (dev_priv->chipset >= 0x90) nv_wr32(dev, 0xe070, 0x00000000); nouveau_irq_unregister(dev, 21); + + nv50_gpio_destroy(dev); +} + +static void +nv50_gpio_isr_bh(struct work_struct *work) +{ + struct nv50_gpio_handler *gpioh = + container_of(work, struct nv50_gpio_handler, work); + struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + unsigned long flags; + int state; + + state = pgpio->get(gpioh->dev, gpioh->gpio->tag); + if (state < 0) + return; + + gpioh->handler(gpioh->data, state); + + spin_lock_irqsave(&priv->lock, flags); + gpioh->inhibit = false; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void +nv50_gpio_isr(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; + struct nv50_gpio_priv *priv = pgpio->priv; + struct nv50_gpio_handler *gpioh; + u32 intr0, intr1 = 0; + u32 hi, lo, ch; + + intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); + if (dev_priv->chipset >= 0x90) + intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); + + hi = (intr0 & 0x0000ffff) | (intr1 << 16); + lo = (intr0 >> 16) | (intr1 & 0xffff0000); + ch = hi | lo; + + nv_wr32(dev, 0xe054, intr0); + if (dev_priv->chipset >= 0x90) + nv_wr32(dev, 0xe074, intr1); + + spin_lock(&priv->lock); + list_for_each_entry(gpioh, &priv->handlers, head) { + if (!(ch & (1 << gpioh->gpio->line))) + continue; + + if (gpioh->inhibit) + continue; + gpioh->inhibit = true; + + schedule_work(&gpioh->work); + } + spin_unlock(&priv->lock); } diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_graph.c b/trunk/drivers/gpu/drm/nouveau/nv50_graph.c index 33d5711a918d..ac601f7c4e1a 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_graph.c @@ -616,9 +616,9 @@ nv50_pgraph_tp_trap(struct drm_device *dev, int type, uint32_t ustatus_old, } break; case 7: /* MP error */ - if (ustatus & 0x04030000) { + if (ustatus & 0x00010000) { nv50_pgraph_mp_trap(dev, i, display); - ustatus &= ~0x04030000; + ustatus &= ~0x00010000; } break; case 8: /* TPDMA error */ diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_pm.c b/trunk/drivers/gpu/drm/nouveau/nv50_pm.c index 03937212e9d8..3d5a86b98282 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_pm.c @@ -25,745 +25,122 @@ #include "drmP.h" #include "nouveau_drv.h" #include "nouveau_bios.h" -#include "nouveau_hw.h" #include "nouveau_pm.h" -#include "nouveau_hwsq.h" - -enum clk_src { - clk_src_crystal, - clk_src_href, - clk_src_hclk, - clk_src_hclkm3, - clk_src_hclkm3d2, - clk_src_host, - clk_src_nvclk, - clk_src_sclk, - clk_src_mclk, - clk_src_vdec, - clk_src_dom6 -}; - -static u32 read_clk(struct drm_device *, enum clk_src); - -static u32 -read_div(struct drm_device *dev) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - - switch (dev_priv->chipset) { - case 0x50: /* it exists, but only has bit 31, not the dividers.. */ - case 0x84: - case 0x86: - case 0x98: - case 0xa0: - return nv_rd32(dev, 0x004700); - case 0x92: - case 0x94: - case 0x96: - return nv_rd32(dev, 0x004800); - default: - return 0x00000000; - } -} - -static u32 -read_pll_src(struct drm_device *dev, u32 base) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 coef, ref = read_clk(dev, clk_src_crystal); - u32 rsel = nv_rd32(dev, 0x00e18c); - int P, N, M, id; - - switch (dev_priv->chipset) { - case 0x50: - case 0xa0: - switch (base) { - case 0x4020: - case 0x4028: id = !!(rsel & 0x00000004); break; - case 0x4008: id = !!(rsel & 0x00000008); break; - case 0x4030: id = 0; break; - default: - NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); - return 0; - } - - coef = nv_rd32(dev, 0x00e81c + (id * 0x0c)); - ref *= (coef & 0x01000000) ? 2 : 4; - P = (coef & 0x00070000) >> 16; - N = ((coef & 0x0000ff00) >> 8) + 1; - M = ((coef & 0x000000ff) >> 0) + 1; - break; - case 0x84: - case 0x86: - case 0x92: - coef = nv_rd32(dev, 0x00e81c); - P = (coef & 0x00070000) >> 16; - N = (coef & 0x0000ff00) >> 8; - M = (coef & 0x000000ff) >> 0; - break; - case 0x94: - case 0x96: - case 0x98: - rsel = nv_rd32(dev, 0x00c050); - switch (base) { - case 0x4020: rsel = (rsel & 0x00000003) >> 0; break; - case 0x4008: rsel = (rsel & 0x0000000c) >> 2; break; - case 0x4028: rsel = (rsel & 0x00001800) >> 11; break; - case 0x4030: rsel = 3; break; - default: - NV_ERROR(dev, "ref: bad pll 0x%06x\n", base); - return 0; - } - - switch (rsel) { - case 0: id = 1; break; - case 1: return read_clk(dev, clk_src_crystal); - case 2: return read_clk(dev, clk_src_href); - case 3: id = 0; break; - } - - coef = nv_rd32(dev, 0x00e81c + (id * 0x28)); - P = (nv_rd32(dev, 0x00e824 + (id * 0x28)) >> 16) & 7; - P += (coef & 0x00070000) >> 16; - N = (coef & 0x0000ff00) >> 8; - M = (coef & 0x000000ff) >> 0; - break; - default: - BUG_ON(1); - } - - if (M) - return (ref * N / M) >> P; - return 0; -} - -static u32 -read_pll_ref(struct drm_device *dev, u32 base) -{ - u32 src, mast = nv_rd32(dev, 0x00c040); - - switch (base) { - case 0x004028: - src = !!(mast & 0x00200000); - break; - case 0x004020: - src = !!(mast & 0x00400000); - break; - case 0x004008: - src = !!(mast & 0x00010000); - break; - case 0x004030: - src = !!(mast & 0x02000000); - break; - case 0x00e810: - return read_clk(dev, clk_src_crystal); - default: - NV_ERROR(dev, "bad pll 0x%06x\n", base); - return 0; - } - - if (src) - return read_clk(dev, clk_src_href); - return read_pll_src(dev, base); -} - -static u32 -read_pll(struct drm_device *dev, u32 base) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mast = nv_rd32(dev, 0x00c040); - u32 ctrl = nv_rd32(dev, base + 0); - u32 coef = nv_rd32(dev, base + 4); - u32 ref = read_pll_ref(dev, base); - u32 clk = 0; - int N1, N2, M1, M2; - - if (base == 0x004028 && (mast & 0x00100000)) { - /* wtf, appears to only disable post-divider on nva0 */ - if (dev_priv->chipset != 0xa0) - return read_clk(dev, clk_src_dom6); - } - - N2 = (coef & 0xff000000) >> 24; - M2 = (coef & 0x00ff0000) >> 16; - N1 = (coef & 0x0000ff00) >> 8; - M1 = (coef & 0x000000ff); - if ((ctrl & 0x80000000) && M1) { - clk = ref * N1 / M1; - if ((ctrl & 0x40000100) == 0x40000000) { - if (M2) - clk = clk * N2 / M2; - else - clk = 0; - } - } - - return clk; -} - -static u32 -read_clk(struct drm_device *dev, enum clk_src src) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 mast = nv_rd32(dev, 0x00c040); - u32 P = 0; - - switch (src) { - case clk_src_crystal: - return dev_priv->crystal; - case clk_src_href: - return 100000; /* PCIE reference clock */ - case clk_src_hclk: - return read_clk(dev, clk_src_href) * 27778 / 10000; - case clk_src_hclkm3: - return read_clk(dev, clk_src_hclk) * 3; - case clk_src_hclkm3d2: - return read_clk(dev, clk_src_hclk) * 3 / 2; - case clk_src_host: - switch (mast & 0x30000000) { - case 0x00000000: return read_clk(dev, clk_src_href); - case 0x10000000: break; - case 0x20000000: /* !0x50 */ - case 0x30000000: return read_clk(dev, clk_src_hclk); - } - break; - case clk_src_nvclk: - if (!(mast & 0x00100000)) - P = (nv_rd32(dev, 0x004028) & 0x00070000) >> 16; - switch (mast & 0x00000003) { - case 0x00000000: return read_clk(dev, clk_src_crystal) >> P; - case 0x00000001: return read_clk(dev, clk_src_dom6); - case 0x00000002: return read_pll(dev, 0x004020) >> P; - case 0x00000003: return read_pll(dev, 0x004028) >> P; - } - break; - case clk_src_sclk: - P = (nv_rd32(dev, 0x004020) & 0x00070000) >> 16; - switch (mast & 0x00000030) { - case 0x00000000: - if (mast & 0x00000080) - return read_clk(dev, clk_src_host) >> P; - return read_clk(dev, clk_src_crystal) >> P; - case 0x00000010: break; - case 0x00000020: return read_pll(dev, 0x004028) >> P; - case 0x00000030: return read_pll(dev, 0x004020) >> P; - } - break; - case clk_src_mclk: - P = (nv_rd32(dev, 0x004008) & 0x00070000) >> 16; - if (nv_rd32(dev, 0x004008) & 0x00000200) { - switch (mast & 0x0000c000) { - case 0x00000000: - return read_clk(dev, clk_src_crystal) >> P; - case 0x00008000: - case 0x0000c000: - return read_clk(dev, clk_src_href) >> P; - } - } else { - return read_pll(dev, 0x004008) >> P; - } - break; - case clk_src_vdec: - P = (read_div(dev) & 0x00000700) >> 8; - switch (dev_priv->chipset) { - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0xa0: - switch (mast & 0x00000c00) { - case 0x00000000: - if (dev_priv->chipset == 0xa0) /* wtf?? */ - return read_clk(dev, clk_src_nvclk) >> P; - return read_clk(dev, clk_src_crystal) >> P; - case 0x00000400: - return 0; - case 0x00000800: - if (mast & 0x01000000) - return read_pll(dev, 0x004028) >> P; - return read_pll(dev, 0x004030) >> P; - case 0x00000c00: - return read_clk(dev, clk_src_nvclk) >> P; - } - break; - case 0x98: - switch (mast & 0x00000c00) { - case 0x00000000: - return read_clk(dev, clk_src_nvclk) >> P; - case 0x00000400: - return 0; - case 0x00000800: - return read_clk(dev, clk_src_hclkm3d2) >> P; - case 0x00000c00: - return read_clk(dev, clk_src_mclk) >> P; - } - break; - } - break; - case clk_src_dom6: - switch (dev_priv->chipset) { - case 0x50: - case 0xa0: - return read_pll(dev, 0x00e810) >> 2; - case 0x84: - case 0x86: - case 0x92: - case 0x94: - case 0x96: - case 0x98: - P = (read_div(dev) & 0x00000007) >> 0; - switch (mast & 0x0c000000) { - case 0x00000000: return read_clk(dev, clk_src_href); - case 0x04000000: break; - case 0x08000000: return read_clk(dev, clk_src_hclk); - case 0x0c000000: - return read_clk(dev, clk_src_hclkm3) >> P; - } - break; - default: - break; - } - default: - break; - } - - NV_DEBUG(dev, "unknown clock source %d 0x%08x\n", src, mast); - return 0; -} - -int -nv50_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) - return 0; - - perflvl->core = read_clk(dev, clk_src_nvclk); - perflvl->shader = read_clk(dev, clk_src_sclk); - perflvl->memory = read_clk(dev, clk_src_mclk); - if (dev_priv->chipset != 0x50) { - perflvl->vdec = read_clk(dev, clk_src_vdec); - perflvl->dom6 = read_clk(dev, clk_src_dom6); - } - - return 0; -} struct nv50_pm_state { - struct hwsq_ucode mclk_hwsq; - u32 mscript; - - u32 emast; - u32 nctrl; - u32 ncoef; - u32 sctrl; - u32 scoef; - - u32 amast; - u32 pdivs; + struct nouveau_pm_level *perflvl; + struct pll_lims pll; + enum pll_types type; + int N, M, P; }; -static u32 -calc_pll(struct drm_device *dev, u32 reg, struct pll_lims *pll, - u32 clk, int *N1, int *M1, int *log2P) +int +nv50_pm_clock_get(struct drm_device *dev, u32 id) { - struct nouveau_pll_vals coef; - int ret; + struct pll_lims pll; + int P, N, M, ret; + u32 reg0, reg1; - ret = get_pll_limits(dev, reg, pll); + ret = get_pll_limits(dev, id, &pll); if (ret) - return 0; - - pll->vco2.maxfreq = 0; - pll->refclk = read_pll_ref(dev, reg); - if (!pll->refclk) - return 0; - - ret = nouveau_calc_pll_mnp(dev, pll, clk, &coef); - if (ret == 0) - return 0; + return ret; - *N1 = coef.N1; - *M1 = coef.M1; - *log2P = coef.log2P; - return ret; -} + reg0 = nv_rd32(dev, pll.reg + 0); + reg1 = nv_rd32(dev, pll.reg + 4); -static inline u32 -calc_div(u32 src, u32 target, int *div) -{ - u32 clk0 = src, clk1 = src; - for (*div = 0; *div <= 7; (*div)++) { - if (clk0 <= target) { - clk1 = clk0 << (*div ? 1 : 0); - break; + if ((reg0 & 0x80000000) == 0) { + if (id == PLL_SHADER) { + NV_DEBUG(dev, "Shader PLL is disabled. " + "Shader clock is twice the core\n"); + ret = nv50_pm_clock_get(dev, PLL_CORE); + if (ret > 0) + return ret << 1; + } else if (id == PLL_MEMORY) { + NV_DEBUG(dev, "Memory PLL is disabled. " + "Memory clock is equal to the ref_clk\n"); + return pll.refclk; } - clk0 >>= 1; - } - - if (target - clk0 <= clk1 - target) - return clk0; - (*div)--; - return clk1; -} - -static inline u32 -clk_same(u32 a, u32 b) -{ - return ((a / 1000) == (b / 1000)); -} - -static int -calc_mclk(struct drm_device *dev, u32 freq, struct hwsq_ucode *hwsq) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct pll_lims pll; - u32 mast = nv_rd32(dev, 0x00c040); - u32 ctrl = nv_rd32(dev, 0x004008); - u32 coef = nv_rd32(dev, 0x00400c); - u32 orig = ctrl; - u32 crtc_mask = 0; - int N, M, P; - int ret, i; - - /* use pcie refclock if possible, otherwise use mpll */ - ctrl &= ~0x81ff0200; - if (clk_same(freq, read_clk(dev, clk_src_href))) { - ctrl |= 0x00000200 | (pll.log2p_bias << 19); - } else { - ret = calc_pll(dev, 0x4008, &pll, freq, &N, &M, &P); - if (ret == 0) - return -EINVAL; - - ctrl |= 0x80000000 | (P << 22) | (P << 16); - ctrl |= pll.log2p_bias << 19; - coef = (N << 8) | M; - } - - mast &= ~0xc0000000; /* get MCLK_2 from HREF */ - mast |= 0x0000c000; /* use MCLK_2 as MPLL_BYPASS clock */ - - /* determine active crtcs */ - for (i = 0; i < 2; i++) { - if (nv_rd32(dev, NV50_PDISPLAY_CRTC_C(i, CLOCK))) - crtc_mask |= (1 << i); - } - - /* build the ucode which will reclock the memory for us */ - hwsq_init(hwsq); - if (crtc_mask) { - hwsq_op5f(hwsq, crtc_mask, 0x00); /* wait for scanout */ - hwsq_op5f(hwsq, crtc_mask, 0x01); /* wait for vblank */ } - if (dev_priv->chipset >= 0x92) - hwsq_wr32(hwsq, 0x611200, 0x00003300); /* disable scanout */ - hwsq_setf(hwsq, 0x10, 0); /* disable bus access */ - hwsq_op5f(hwsq, 0x00, 0x01); /* no idea :s */ - - /* prepare memory controller */ - hwsq_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge banks and idle */ - hwsq_wr32(hwsq, 0x1002d0, 0x00000001); /* force refresh */ - hwsq_wr32(hwsq, 0x100210, 0x00000000); /* stop the automatic refresh */ - hwsq_wr32(hwsq, 0x1002dc, 0x00000001); /* start self refresh mode */ - /* reclock memory */ - hwsq_wr32(hwsq, 0xc040, mast); - hwsq_wr32(hwsq, 0x4008, orig | 0x00000200); /* bypass MPLL */ - hwsq_wr32(hwsq, 0x400c, coef); - hwsq_wr32(hwsq, 0x4008, ctrl); + P = (reg0 & 0x00070000) >> 16; + N = (reg1 & 0x0000ff00) >> 8; + M = (reg1 & 0x000000ff); - /* restart memory controller */ - hwsq_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge banks and idle */ - hwsq_wr32(hwsq, 0x1002dc, 0x00000000); /* stop self refresh mode */ - hwsq_wr32(hwsq, 0x100210, 0x80000000); /* restart automatic refresh */ - hwsq_usec(hwsq, 12); /* wait for the PLL to stabilize */ - - hwsq_usec(hwsq, 48); /* may be unnecessary: causes flickering */ - hwsq_setf(hwsq, 0x10, 1); /* enable bus access */ - hwsq_op5f(hwsq, 0x00, 0x00); /* no idea, reverse of 0x00, 0x01? */ - if (dev_priv->chipset >= 0x92) - hwsq_wr32(hwsq, 0x611200, 0x00003330); /* enable scanout */ - hwsq_fini(hwsq); - return 0; + return ((pll.refclk * N / M) >> P); } void * -nv50_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) +nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, + u32 id, int khz) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_pm_state *info; - struct pll_lims pll; - int ret = -EINVAL; - int N, M, P1, P2; - u32 clk, out; + struct nv50_pm_state *state; + int dummy, ret; - if (dev_priv->chipset == 0xaa || - dev_priv->chipset == 0xac) - return ERR_PTR(-ENODEV); - - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) return ERR_PTR(-ENOMEM); + state->type = id; + state->perflvl = perflvl; - /* core: for the moment at least, always use nvpll */ - clk = calc_pll(dev, 0x4028, &pll, perflvl->core, &N, &M, &P1); - if (clk == 0) - goto error; - - info->emast = 0x00000003; - info->nctrl = 0x80000000 | (P1 << 19) | (P1 << 16); - info->ncoef = (N << 8) | M; - - /* shader: tie to nvclk if possible, otherwise use spll. have to be - * very careful that the shader clock is at least twice the core, or - * some chipsets will be very unhappy. i expect most or all of these - * cases will be handled by tying to nvclk, but it's possible there's - * corners - */ - if (P1-- && perflvl->shader == (perflvl->core << 1)) { - info->emast |= 0x00000020; - info->sctrl = 0x00000000 | (P1 << 19) | (P1 << 16); - info->scoef = nv_rd32(dev, 0x004024); - } else { - clk = calc_pll(dev, 0x4020, &pll, perflvl->shader, &N, &M, &P1); - if (clk == 0) - goto error; - - info->emast |= 0x00000030; - info->sctrl = 0x80000000 | (P1 << 19) | (P1 << 16); - info->scoef = (N << 8) | M; - } - - /* memory: build hwsq ucode which we'll use to reclock memory */ - info->mclk_hwsq.len = 0; - if (perflvl->memory) { - clk = calc_mclk(dev, perflvl->memory, &info->mclk_hwsq); - if (clk < 0) { - ret = clk; - goto error; - } - - info->mscript = perflvl->memscript; - } - - /* vdec: avoid modifying xpll until we know exactly how the other - * clock domains work, i suspect at least some of them can also be - * tied to xpll... - */ - info->amast = nv_rd32(dev, 0x00c040); - info->pdivs = read_div(dev); - if (perflvl->vdec) { - /* see how close we can get using nvclk as a source */ - clk = calc_div(perflvl->core, perflvl->vdec, &P1); - - /* see how close we can get using xpll/hclk as a source */ - if (dev_priv->chipset != 0x98) - out = read_pll(dev, 0x004030); - else - out = read_clk(dev, clk_src_hclkm3d2); - out = calc_div(out, perflvl->vdec, &P2); - - /* select whichever gets us closest */ - info->amast &= ~0x00000c00; - info->pdivs &= ~0x00000700; - if (abs((int)perflvl->vdec - clk) <= - abs((int)perflvl->vdec - out)) { - if (dev_priv->chipset != 0x98) - info->amast |= 0x00000c00; - info->pdivs |= P1 << 8; - } else { - info->amast |= 0x00000800; - info->pdivs |= P2 << 8; - } - } - - /* dom6: nfi what this is, but we're limited to various combinations - * of the host clock frequency - */ - if (perflvl->dom6) { - info->amast &= ~0x0c000000; - if (clk_same(perflvl->dom6, read_clk(dev, clk_src_href))) { - info->amast |= 0x00000000; - } else - if (clk_same(perflvl->dom6, read_clk(dev, clk_src_hclk))) { - info->amast |= 0x08000000; - } else { - clk = read_clk(dev, clk_src_hclk) * 3; - clk = calc_div(clk, perflvl->dom6, &P1); - - info->amast |= 0x0c000000; - info->pdivs = (info->pdivs & ~0x00000007) | P1; - } + ret = get_pll_limits(dev, id, &state->pll); + if (ret < 0) { + kfree(state); + return (ret == -ENOENT) ? NULL : ERR_PTR(ret); } - return info; -error: - kfree(info); - return ERR_PTR(ret); -} - -static int -prog_mclk(struct drm_device *dev, struct hwsq_ucode *hwsq) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - u32 hwsq_data, hwsq_kick; - int i; - - if (dev_priv->chipset < 0x90) { - hwsq_data = 0x001400; - hwsq_kick = 0x00000003; - } else { - hwsq_data = 0x080000; - hwsq_kick = 0x00000001; + ret = nv50_calc_pll(dev, &state->pll, khz, &state->N, &state->M, + &dummy, &dummy, &state->P); + if (ret < 0) { + kfree(state); + return ERR_PTR(ret); } - /* upload hwsq ucode */ - nv_mask(dev, 0x001098, 0x00000008, 0x00000000); - nv_wr32(dev, 0x001304, 0x00000000); - for (i = 0; i < hwsq->len / 4; i++) - nv_wr32(dev, hwsq_data + (i * 4), hwsq->ptr.u32[i]); - nv_mask(dev, 0x001098, 0x00000018, 0x00000018); - - /* launch, and wait for completion */ - nv_wr32(dev, 0x00130c, hwsq_kick); - if (!nv_wait(dev, 0x001308, 0x00000100, 0x00000000)) { - NV_ERROR(dev, "hwsq ucode exec timed out\n"); - NV_ERROR(dev, "0x001308: 0x%08x\n", nv_rd32(dev, 0x001308)); - for (i = 0; i < hwsq->len / 4; i++) { - NV_ERROR(dev, "0x%06x: 0x%08x\n", 0x1400 + (i * 4), - nv_rd32(dev, 0x001400 + (i * 4))); - } - - return -EIO; - } - - return 0; + return state; } -int -nv50_pm_clocks_set(struct drm_device *dev, void *data) +void +nv50_pm_clock_set(struct drm_device *dev, void *pre_state) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nv50_pm_state *info = data; - struct bit_entry M; - int ret = 0; + struct nv50_pm_state *state = pre_state; + struct nouveau_pm_level *perflvl = state->perflvl; + u32 reg = state->pll.reg, tmp; + struct bit_entry BIT_M; + u16 script; + int N = state->N; + int M = state->M; + int P = state->P; - /* halt and idle execution engines */ - nv_mask(dev, 0x002504, 0x00000001, 0x00000001); - if (!nv_wait(dev, 0x002504, 0x00000010, 0x00000010)) - goto error; + if (state->type == PLL_MEMORY && perflvl->memscript && + bit_table(dev, 'M', &BIT_M) == 0 && + BIT_M.version == 1 && BIT_M.length >= 0x0b) { + script = ROM16(BIT_M.data[0x05]); + if (script) + nouveau_bios_run_init_table(dev, script, NULL, -1); + script = ROM16(BIT_M.data[0x07]); + if (script) + nouveau_bios_run_init_table(dev, script, NULL, -1); + script = ROM16(BIT_M.data[0x09]); + if (script) + nouveau_bios_run_init_table(dev, script, NULL, -1); - /* memory: it is *very* important we change this first, the ucode - * we build in pre() now has hardcoded 0xc040 values, which can't - * change before we execute it or the engine clocks may end up - * messed up. - */ - if (info->mclk_hwsq.len) { - /* execute some scripts that do ??? from the vbios.. */ - if (!bit_table(dev, 'M', &M) && M.version == 1) { - if (M.length >= 6) - nouveau_bios_init_exec(dev, ROM16(M.data[5])); - if (M.length >= 8) - nouveau_bios_init_exec(dev, ROM16(M.data[7])); - if (M.length >= 10) - nouveau_bios_init_exec(dev, ROM16(M.data[9])); - nouveau_bios_init_exec(dev, info->mscript); - } - - ret = prog_mclk(dev, &info->mclk_hwsq); - if (ret) - goto resume; + nouveau_bios_run_init_table(dev, perflvl->memscript, NULL, -1); } - /* reclock vdec/dom6 */ - nv_mask(dev, 0x00c040, 0x00000c00, 0x00000000); - switch (dev_priv->chipset) { - case 0x92: - case 0x94: - case 0x96: - nv_mask(dev, 0x004800, 0x00000707, info->pdivs); - break; - default: - nv_mask(dev, 0x004700, 0x00000707, info->pdivs); - break; + if (state->type == PLL_MEMORY) { + nv_wr32(dev, 0x100210, 0); + nv_wr32(dev, 0x1002dc, 1); } - nv_mask(dev, 0x00c040, 0x0c000c00, info->amast); - /* core/shader: make sure sclk/nvclk are disconnected from their - * plls (nvclk to dom6, sclk to hclk), modify the plls, and - * reconnect sclk/nvclk to their new clock source - */ - if (dev_priv->chipset < 0x92) - nv_mask(dev, 0x00c040, 0x001000b0, 0x00100080); /* grrr! */ - else - nv_mask(dev, 0x00c040, 0x000000b3, 0x00000081); - nv_mask(dev, 0x004020, 0xc03f0100, info->sctrl); - nv_wr32(dev, 0x004024, info->scoef); - nv_mask(dev, 0x004028, 0xc03f0100, info->nctrl); - nv_wr32(dev, 0x00402c, info->ncoef); - nv_mask(dev, 0x00c040, 0x00100033, info->emast); - - goto resume; -error: - ret = -EBUSY; -resume: - nv_mask(dev, 0x002504, 0x00000001, 0x00000000); - kfree(info); - return ret; -} + tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; + tmp |= 0x80000000 | (P << 16); + nv_wr32(dev, reg + 0, tmp); + nv_wr32(dev, reg + 4, (N << 8) | M); -static int -pwm_info(struct drm_device *dev, int *line, int *ctrl, int *indx) -{ - if (*line == 0x04) { - *ctrl = 0x00e100; - *line = 4; - *indx = 0; - } else - if (*line == 0x09) { - *ctrl = 0x00e100; - *line = 9; - *indx = 1; - } else - if (*line == 0x10) { - *ctrl = 0x00e28c; - *line = 0; - *indx = 0; - } else { - NV_ERROR(dev, "unknown pwm ctrl for gpio %d\n", *line); - return -ENODEV; - } - - return 0; -} - -int -nv50_pm_pwm_get(struct drm_device *dev, int line, u32 *divs, u32 *duty) -{ - int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); - if (ret) - return ret; - - if (nv_rd32(dev, ctrl) & (1 << line)) { - *divs = nv_rd32(dev, 0x00e114 + (id * 8)); - *duty = nv_rd32(dev, 0x00e118 + (id * 8)); - return 0; + if (state->type == PLL_MEMORY) { + nv_wr32(dev, 0x1002dc, 0); + nv_wr32(dev, 0x100210, 0x80000000); } - return -EINVAL; + kfree(state); } -int -nv50_pm_pwm_set(struct drm_device *dev, int line, u32 divs, u32 duty) -{ - int ctrl, id, ret = pwm_info(dev, &line, &ctrl, &id); - if (ret) - return ret; - - nv_mask(dev, ctrl, 0x00010001 << line, 0x00000001 << line); - nv_wr32(dev, 0x00e114 + (id * 8), divs); - nv_wr32(dev, 0x00e118 + (id * 8), duty | 0x80000000); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_sor.c b/trunk/drivers/gpu/drm/nouveau/nv50_sor.c index c4423ba9c9bf..2633aa8554eb 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_sor.c @@ -60,8 +60,6 @@ nv50_sor_disconnect(struct drm_encoder *encoder) BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1); OUT_RING (evo, 0); - nouveau_hdmi_mode_set(encoder, NULL); - nv_encoder->crtc = NULL; nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; } @@ -174,12 +172,6 @@ nv50_sor_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, static void nv50_sor_prepare(struct drm_encoder *encoder) { - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - nv50_sor_disconnect(encoder); - if (nv_encoder->dcb->type == OUTPUT_DP) { - /* avoid race between link training and supervisor intr */ - nv50_display_sync(encoder->dev); - } } static void @@ -188,8 +180,8 @@ nv50_sor_commit(struct drm_encoder *encoder) } static void -nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, - struct drm_display_mode *mode) +nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) { struct nouveau_channel *evo = nv50_display(encoder->dev)->master; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); @@ -201,27 +193,24 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, NV_DEBUG_KMS(dev, "or %d type %d -> crtc %d\n", nv_encoder->or, nv_encoder->dcb->type, crtc->index); - nv_encoder->crtc = encoder->crtc; switch (nv_encoder->dcb->type) { case OUTPUT_TMDS: if (nv_encoder->dcb->sorconf.link & 1) { - if (mode->clock < 165000) + if (adjusted_mode->clock < 165000) mode_ctl = 0x0100; else mode_ctl = 0x0500; } else mode_ctl = 0x0200; - - nouveau_hdmi_mode_set(encoder, mode); break; case OUTPUT_DP: nv_connector = nouveau_encoder_connector_get(nv_encoder); if (nv_connector && nv_connector->base.display_info.bpc == 6) { - nv_encoder->dp.datarate = mode->clock * 18 / 8; + nv_encoder->dp.datarate = crtc->mode->clock * 18 / 8; mode_ctl |= 0x00020000; } else { - nv_encoder->dp.datarate = mode->clock * 24 / 8; + nv_encoder->dp.datarate = crtc->mode->clock * 24 / 8; mode_ctl |= 0x00050000; } @@ -239,10 +228,10 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, else mode_ctl |= NV50_EVO_SOR_MODE_CTRL_CRTC0; - if (mode->flags & DRM_MODE_FLAG_NHSYNC) + if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NHSYNC; - if (mode->flags & DRM_MODE_FLAG_NVSYNC) + if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC) mode_ctl |= NV50_EVO_SOR_MODE_CTRL_NVSYNC; nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); @@ -250,11 +239,12 @@ nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, ret = RING_SPACE(evo, 2); if (ret) { NV_ERROR(dev, "no space while connecting SOR\n"); - nv_encoder->crtc = NULL; return; } BEGIN_RING(evo, 0, NV50_EVO_SOR(nv_encoder->or, MODE_CTRL), 1); OUT_RING(evo, mode_ctl); + + nv_encoder->crtc = encoder->crtc; } static struct drm_crtc * diff --git a/trunk/drivers/gpu/drm/nouveau/nv50_vm.c b/trunk/drivers/gpu/drm/nouveau/nv50_vm.c index 6f38ceae3aa4..40b84f22d819 100644 --- a/trunk/drivers/gpu/drm/nouveau/nv50_vm.c +++ b/trunk/drivers/gpu/drm/nouveau/nv50_vm.c @@ -48,7 +48,7 @@ nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde, phys |= 0x60; else if (coverage <= 64 * 1024 * 1024) phys |= 0x40; - else if (coverage <= 128 * 1024 * 1024) + else if (coverage < 128 * 1024 * 1024) phys |= 0x20; } diff --git a/trunk/drivers/gpu/drm/nouveau/nv84_bsp.c b/trunk/drivers/gpu/drm/nouveau/nv84_bsp.c deleted file mode 100644 index 74875739bcc0..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nv84_bsp.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include "nouveau_vm.h" -#include "nouveau_ramht.h" - -/*XXX: This stub is currently used on NV98+ also, as soon as this becomes - * more than just an enable/disable stub this needs to be split out to - * nv98_bsp.c... - */ - -struct nv84_bsp_engine { - struct nouveau_exec_engine base; -}; - -static int -nv84_bsp_fini(struct drm_device *dev, int engine, bool suspend) -{ - if (!(nv_rd32(dev, 0x000200) & 0x00008000)) - return 0; - - nv_mask(dev, 0x000200, 0x00008000, 0x00000000); - return 0; -} - -static int -nv84_bsp_init(struct drm_device *dev, int engine) -{ - nv_mask(dev, 0x000200, 0x00008000, 0x00000000); - nv_mask(dev, 0x000200, 0x00008000, 0x00008000); - return 0; -} - -static void -nv84_bsp_destroy(struct drm_device *dev, int engine) -{ - struct nv84_bsp_engine *pbsp = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, BSP); - - kfree(pbsp); -} - -int -nv84_bsp_create(struct drm_device *dev) -{ - struct nv84_bsp_engine *pbsp; - - pbsp = kzalloc(sizeof(*pbsp), GFP_KERNEL); - if (!pbsp) - return -ENOMEM; - - pbsp->base.destroy = nv84_bsp_destroy; - pbsp->base.init = nv84_bsp_init; - pbsp->base.fini = nv84_bsp_fini; - - NVOBJ_ENGINE_ADD(dev, BSP, &pbsp->base); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nv84_vp.c b/trunk/drivers/gpu/drm/nouveau/nv84_vp.c deleted file mode 100644 index 6570d300ab85..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nv84_vp.c +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include "nouveau_vm.h" -#include "nouveau_ramht.h" - -/*XXX: This stub is currently used on NV98+ also, as soon as this becomes - * more than just an enable/disable stub this needs to be split out to - * nv98_vp.c... - */ - -struct nv84_vp_engine { - struct nouveau_exec_engine base; -}; - -static int -nv84_vp_fini(struct drm_device *dev, int engine, bool suspend) -{ - if (!(nv_rd32(dev, 0x000200) & 0x00020000)) - return 0; - - nv_mask(dev, 0x000200, 0x00020000, 0x00000000); - return 0; -} - -static int -nv84_vp_init(struct drm_device *dev, int engine) -{ - nv_mask(dev, 0x000200, 0x00020000, 0x00000000); - nv_mask(dev, 0x000200, 0x00020000, 0x00020000); - return 0; -} - -static void -nv84_vp_destroy(struct drm_device *dev, int engine) -{ - struct nv84_vp_engine *pvp = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, VP); - - kfree(pvp); -} - -int -nv84_vp_create(struct drm_device *dev) -{ - struct nv84_vp_engine *pvp; - - pvp = kzalloc(sizeof(*pvp), GFP_KERNEL); - if (!pvp) - return -ENOMEM; - - pvp->base.destroy = nv84_vp_destroy; - pvp->base.init = nv84_vp_init; - pvp->base.fini = nv84_vp_fini; - - NVOBJ_ENGINE_ADD(dev, VP, &pvp->base); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nv98_crypt.c b/trunk/drivers/gpu/drm/nouveau/nv98_crypt.c deleted file mode 100644 index db94ff0a9fab..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nv98_crypt.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include "nouveau_vm.h" -#include "nouveau_ramht.h" - -struct nv98_crypt_engine { - struct nouveau_exec_engine base; -}; - -static int -nv98_crypt_fini(struct drm_device *dev, int engine, bool suspend) -{ - if (!(nv_rd32(dev, 0x000200) & 0x00004000)) - return 0; - - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); - return 0; -} - -static int -nv98_crypt_init(struct drm_device *dev, int engine) -{ - nv_mask(dev, 0x000200, 0x00004000, 0x00000000); - nv_mask(dev, 0x000200, 0x00004000, 0x00004000); - return 0; -} - -static void -nv98_crypt_destroy(struct drm_device *dev, int engine) -{ - struct nv98_crypt_engine *pcrypt = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, CRYPT); - - kfree(pcrypt); -} - -int -nv98_crypt_create(struct drm_device *dev) -{ - struct nv98_crypt_engine *pcrypt; - - pcrypt = kzalloc(sizeof(*pcrypt), GFP_KERNEL); - if (!pcrypt) - return -ENOMEM; - - pcrypt->base.destroy = nv98_crypt_destroy; - pcrypt->base.init = nv98_crypt_init; - pcrypt->base.fini = nv98_crypt_fini; - - NVOBJ_ENGINE_ADD(dev, CRYPT, &pcrypt->base); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nv98_ppp.c b/trunk/drivers/gpu/drm/nouveau/nv98_ppp.c deleted file mode 100644 index a987dd6e0036..000000000000 --- a/trunk/drivers/gpu/drm/nouveau/nv98_ppp.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2011 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ - -#include "drmP.h" -#include "nouveau_drv.h" -#include "nouveau_util.h" -#include "nouveau_vm.h" -#include "nouveau_ramht.h" - -struct nv98_ppp_engine { - struct nouveau_exec_engine base; -}; - -static int -nv98_ppp_fini(struct drm_device *dev, int engine, bool suspend) -{ - if (!(nv_rd32(dev, 0x000200) & 0x00000002)) - return 0; - - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); - return 0; -} - -static int -nv98_ppp_init(struct drm_device *dev, int engine) -{ - nv_mask(dev, 0x000200, 0x00000002, 0x00000000); - nv_mask(dev, 0x000200, 0x00000002, 0x00000002); - return 0; -} - -static void -nv98_ppp_destroy(struct drm_device *dev, int engine) -{ - struct nv98_ppp_engine *pppp = nv_engine(dev, engine); - - NVOBJ_ENGINE_DEL(dev, PPP); - - kfree(pppp); -} - -int -nv98_ppp_create(struct drm_device *dev) -{ - struct nv98_ppp_engine *pppp; - - pppp = kzalloc(sizeof(*pppp), GFP_KERNEL); - if (!pppp) - return -ENOMEM; - - pppp->base.destroy = nv98_ppp_destroy; - pppp->base.init = nv98_ppp_init; - pppp->base.fini = nv98_ppp_fini; - - NVOBJ_ENGINE_ADD(dev, PPP, &pppp->base); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc index abc36626fef0..eaf35f8321ee 100644 --- a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc +++ b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc @@ -31,9 +31,8 @@ */ ifdef(`NVA3', -.section #nva3_pcopy_data -, -.section #nvc0_pcopy_data +.section nva3_pcopy_data, +.section nvc0_pcopy_data ) ctx_object: .b32 0 @@ -43,7 +42,7 @@ ctx_dma_query: .b32 0 ctx_dma_src: .b32 0 ctx_dma_dst: .b32 0 ,) -.equ #ctx_dma_count 3 +.equ ctx_dma_count 3 ctx_query_address_high: .b32 0 ctx_query_address_low: .b32 0 ctx_query_counter: .b32 0 @@ -79,65 +78,64 @@ ctx_ycnt: .b32 0 dispatch_table: // mthd 0x0000, NAME .b16 0x000 1 -.b32 #ctx_object ~0xffffffff +.b32 ctx_object ~0xffffffff // mthd 0x0100, NOP .b16 0x040 1 -.b32 0x00010000 + #cmd_nop ~0xffffffff +.b32 0x00010000 + cmd_nop ~0xffffffff // mthd 0x0140, PM_TRIGGER .b16 0x050 1 -.b32 0x00010000 + #cmd_pm_trigger ~0xffffffff +.b32 0x00010000 + cmd_pm_trigger ~0xffffffff ifdef(`NVA3', ` // mthd 0x0180-0x018c, DMA_ -.b16 0x060 #ctx_dma_count +.b16 0x060 ctx_dma_count dispatch_dma: -.b32 0x00010000 + #cmd_dma ~0xffffffff -.b32 0x00010000 + #cmd_dma ~0xffffffff -.b32 0x00010000 + #cmd_dma ~0xffffffff +.b32 0x00010000 + cmd_dma ~0xffffffff +.b32 0x00010000 + cmd_dma ~0xffffffff +.b32 0x00010000 + cmd_dma ~0xffffffff ',) // mthd 0x0200-0x0218, SRC_TILE .b16 0x80 7 -.b32 #ctx_src_tile_mode ~0x00000fff -.b32 #ctx_src_xsize ~0x0007ffff -.b32 #ctx_src_ysize ~0x00001fff -.b32 #ctx_src_zsize ~0x000007ff -.b32 #ctx_src_zoff ~0x00000fff -.b32 #ctx_src_xoff ~0x0007ffff -.b32 #ctx_src_yoff ~0x00001fff +.b32 ctx_src_tile_mode ~0x00000fff +.b32 ctx_src_xsize ~0x0007ffff +.b32 ctx_src_ysize ~0x00001fff +.b32 ctx_src_zsize ~0x000007ff +.b32 ctx_src_zoff ~0x00000fff +.b32 ctx_src_xoff ~0x0007ffff +.b32 ctx_src_yoff ~0x00001fff // mthd 0x0220-0x0238, DST_TILE .b16 0x88 7 -.b32 #ctx_dst_tile_mode ~0x00000fff -.b32 #ctx_dst_xsize ~0x0007ffff -.b32 #ctx_dst_ysize ~0x00001fff -.b32 #ctx_dst_zsize ~0x000007ff -.b32 #ctx_dst_zoff ~0x00000fff -.b32 #ctx_dst_xoff ~0x0007ffff -.b32 #ctx_dst_yoff ~0x00001fff +.b32 ctx_dst_tile_mode ~0x00000fff +.b32 ctx_dst_xsize ~0x0007ffff +.b32 ctx_dst_ysize ~0x00001fff +.b32 ctx_dst_zsize ~0x000007ff +.b32 ctx_dst_zoff ~0x00000fff +.b32 ctx_dst_xoff ~0x0007ffff +.b32 ctx_dst_yoff ~0x00001fff // mthd 0x0300-0x0304, EXEC, WRCACHE_FLUSH .b16 0xc0 2 -.b32 0x00010000 + #cmd_exec ~0xffffffff -.b32 0x00010000 + #cmd_wrcache_flush ~0xffffffff +.b32 0x00010000 + cmd_exec ~0xffffffff +.b32 0x00010000 + cmd_wrcache_flush ~0xffffffff // mthd 0x030c-0x0340, various stuff .b16 0xc3 14 -.b32 #ctx_src_address_high ~0x000000ff -.b32 #ctx_src_address_low ~0xfffffff0 -.b32 #ctx_dst_address_high ~0x000000ff -.b32 #ctx_dst_address_low ~0xfffffff0 -.b32 #ctx_src_pitch ~0x0007ffff -.b32 #ctx_dst_pitch ~0x0007ffff -.b32 #ctx_xcnt ~0x0000ffff -.b32 #ctx_ycnt ~0x00001fff -.b32 #ctx_format ~0x0333ffff -.b32 #ctx_swz_const0 ~0xffffffff -.b32 #ctx_swz_const1 ~0xffffffff -.b32 #ctx_query_address_high ~0x000000ff -.b32 #ctx_query_address_low ~0xffffffff -.b32 #ctx_query_counter ~0xffffffff +.b32 ctx_src_address_high ~0x000000ff +.b32 ctx_src_address_low ~0xfffffff0 +.b32 ctx_dst_address_high ~0x000000ff +.b32 ctx_dst_address_low ~0xfffffff0 +.b32 ctx_src_pitch ~0x0007ffff +.b32 ctx_dst_pitch ~0x0007ffff +.b32 ctx_xcnt ~0x0000ffff +.b32 ctx_ycnt ~0x00001fff +.b32 ctx_format ~0x0333ffff +.b32 ctx_swz_const0 ~0xffffffff +.b32 ctx_swz_const1 ~0xffffffff +.b32 ctx_query_address_high ~0x000000ff +.b32 ctx_query_address_low ~0xffffffff +.b32 ctx_query_counter ~0xffffffff .b16 0x800 0 ifdef(`NVA3', -.section #nva3_pcopy_code -, -.section #nvc0_pcopy_code +.section nva3_pcopy_code, +.section nvc0_pcopy_code ) main: @@ -145,12 +143,12 @@ main: mov $sp $r0 // setup i0 handler and route fifo and ctxswitch to it - mov $r1 #ih + mov $r1 ih mov $iv0 $r1 mov $r1 0x400 movw $r2 0xfff3 sethi $r2 0 - iowr I[$r1 + 0x300] $r2 + iowr I[$r2 + 0x300] $r2 // enable interrupts or $r2 0xc @@ -166,19 +164,19 @@ main: bset $flags $p0 spin: sleep $p0 - bra #spin + bra spin // i0 handler ih: iord $r1 I[$r0 + 0x200] and $r2 $r1 0x00000008 - bra e #ih_no_chsw - call #chsw + bra e ih_no_chsw + call chsw ih_no_chsw: and $r2 $r1 0x00000004 - bra e #ih_no_cmd - call #dispatch + bra e ih_no_cmd + call dispatch ih_no_cmd: and $r1 $r1 0x0000000c @@ -237,9 +235,9 @@ ifdef(`NVA3', ` sethi $r4 0x60000 // swap! - bra $p1 #swctx_load + bra $p1 swctx_load xdst $r0 $r4 - bra #swctx_done + bra swctx_done swctx_load: xdld $r0 $r4 swctx_done: @@ -253,9 +251,9 @@ chsw: // if it's active, unload it and return xbit $r15 $r3 0x1e - bra e #chsw_no_unload + bra e chsw_no_unload bclr $flags $p1 - call #swctx + call swctx bclr $r3 0x1e iowr I[$r2] $r3 mov $r4 1 @@ -268,20 +266,20 @@ chsw: // is there a channel waiting to be loaded? xbit $r13 $r3 0x1e - bra e #chsw_finish_load + bra e chsw_finish_load bset $flags $p1 - call #swctx + call swctx ifdef(`NVA3', // load dma objects back into TARGET regs - mov $r5 #ctx_dma - mov $r6 #ctx_dma_count + mov $r5 ctx_dma + mov $r6 ctx_dma_count chsw_load_ctx_dma: ld b32 $r7 D[$r5 + $r6 * 4] add b32 $r8 $r6 0x180 shl b32 $r8 8 iowr I[$r8] $r7 sub b32 $r6 1 - bra nc #chsw_load_ctx_dma + bra nc chsw_load_ctx_dma ,) chsw_finish_load: @@ -299,7 +297,7 @@ dispatch: shl b32 $r2 0x10 // lookup method in the dispatch table, ILLEGAL_MTHD if not found - mov $r5 #dispatch_table + mov $r5 dispatch_table clear b32 $r6 clear b32 $r7 dispatch_loop: @@ -307,14 +305,14 @@ dispatch: ld b16 $r7 D[$r5 + 2] add b32 $r5 4 cmpu b32 $r4 $r6 - bra c #dispatch_illegal_mthd + bra c dispatch_illegal_mthd add b32 $r7 $r6 cmpu b32 $r4 $r7 - bra c #dispatch_valid_mthd + bra c dispatch_valid_mthd sub b32 $r7 $r6 shl b32 $r7 3 add b32 $r5 $r7 - bra #dispatch_loop + bra dispatch_loop // ensure no bits set in reserved fields, INVALID_BITFIELD dispatch_valid_mthd: @@ -324,20 +322,20 @@ dispatch: ld b32 $r5 D[$r4 + 4] and $r5 $r3 cmpu b32 $r5 0 - bra ne #dispatch_invalid_bitfield + bra ne dispatch_invalid_bitfield // depending on dispatch flags: execute method, or save data as state ld b16 $r5 D[$r4 + 0] ld b16 $r6 D[$r4 + 2] cmpu b32 $r6 0 - bra ne #dispatch_cmd + bra ne dispatch_cmd st b32 D[$r5] $r3 - bra #dispatch_done + bra dispatch_done dispatch_cmd: bclr $flags $p1 call $r5 - bra $p1 #dispatch_error - bra #dispatch_done + bra $p1 dispatch_error + bra dispatch_done dispatch_invalid_bitfield: or $r2 2 @@ -355,7 +353,7 @@ dispatch: iord $r2 I[$r0 + 0x200] and $r2 0x40 cmpu b32 $r2 0 - bra ne #hostirq_wait + bra ne hostirq_wait dispatch_done: mov $r2 0x1d00 @@ -411,10 +409,10 @@ ifdef(`NVA3', // $r2: hostirq state // $r3: data cmd_dma: - sub b32 $r4 #dispatch_dma + sub b32 $r4 dispatch_dma shr b32 $r4 1 bset $r3 0x1e - st b32 D[$r4 + #ctx_dma] $r3 + st b32 D[$r4 + ctx_dma] $r3 add b32 $r4 0x600 shl b32 $r4 6 iowr I[$r4] $r3 @@ -432,7 +430,7 @@ cmd_exec_set_format: st b32 D[$sp + 0x0c] $r0 // extract cpp, src_ncomp and dst_ncomp from FORMAT - ld b32 $r4 D[$r0 + #ctx_format] + ld b32 $r4 D[$r0 + ctx_format] extr $r5 $r4 16:17 add b32 $r5 1 extr $r6 $r4 20:21 @@ -450,22 +448,22 @@ cmd_exec_set_format: clear b32 $r11 bpc_loop: cmpu b8 $r10 4 - bra nc #cmp_c0 + bra nc cmp_c0 mulu $r12 $r10 $r5 add b32 $r12 $r11 bset $flags $p2 - bra #bpc_next + bra bpc_next cmp_c0: - bra ne #cmp_c1 + bra ne cmp_c1 mov $r12 0x10 add b32 $r12 $r11 - bra #bpc_next + bra bpc_next cmp_c1: cmpu b8 $r10 6 - bra nc #cmp_zero + bra nc cmp_zero mov $r12 0x14 add b32 $r12 $r11 - bra #bpc_next + bra bpc_next cmp_zero: mov $r12 0x80 bpc_next: @@ -473,22 +471,22 @@ cmd_exec_set_format: add b32 $r8 1 add b32 $r11 1 cmpu b32 $r11 $r5 - bra c #bpc_loop + bra c bpc_loop add b32 $r9 1 cmpu b32 $r9 $r7 - bra c #ncomp_loop + bra c ncomp_loop // SRC_XCNT = (xcnt * src_cpp), or 0 if no src ref in swz (hw will hang) mulu $r6 $r5 - st b32 D[$r0 + #ctx_src_cpp] $r6 - ld b32 $r8 D[$r0 + #ctx_xcnt] + st b32 D[$r0 + ctx_src_cpp] $r6 + ld b32 $r8 D[$r0 + ctx_xcnt] mulu $r6 $r8 - bra $p2 #dst_xcnt + bra $p2 dst_xcnt clear b32 $r6 dst_xcnt: mulu $r7 $r5 - st b32 D[$r0 + #ctx_dst_cpp] $r7 + st b32 D[$r0 + ctx_dst_cpp] $r7 mulu $r7 $r8 mov $r5 0x810 @@ -496,10 +494,10 @@ cmd_exec_set_format: iowr I[$r5 + 0x000] $r6 iowr I[$r5 + 0x100] $r7 add b32 $r5 0x800 - ld b32 $r6 D[$r0 + #ctx_dst_cpp] + ld b32 $r6 D[$r0 + ctx_dst_cpp] sub b32 $r6 1 shl b32 $r6 8 - ld b32 $r7 D[$r0 + #ctx_src_cpp] + ld b32 $r7 D[$r0 + ctx_src_cpp] sub b32 $r7 1 or $r6 $r7 iowr I[$r5 + 0x000] $r6 @@ -513,9 +511,9 @@ cmd_exec_set_format: ld b32 $r6 D[$sp + 0x0c] iowr I[$r5 + 0x300] $r6 add b32 $r5 0x400 - ld b32 $r6 D[$r0 + #ctx_swz_const0] + ld b32 $r6 D[$r0 + ctx_swz_const0] iowr I[$r5 + 0x000] $r6 - ld b32 $r6 D[$r0 + #ctx_swz_const1] + ld b32 $r6 D[$r0 + ctx_swz_const1] iowr I[$r5 + 0x100] $r6 add $sp 0x10 ret @@ -545,7 +543,7 @@ cmd_exec_set_format: // cmd_exec_set_surface_tiled: // translate TILE_MODE into Tp, Th, Td shift values - ld b32 $r7 D[$r5 + #ctx_src_tile_mode] + ld b32 $r7 D[$r5 + ctx_src_tile_mode] extr $r9 $r7 8:11 extr $r8 $r7 4:7 ifdef(`NVA3', @@ -555,9 +553,9 @@ ifdef(`NVA3', ) extr $r7 $r7 0:3 cmp b32 $r7 0xe - bra ne #xtile64 + bra ne xtile64 mov $r7 4 - bra #xtileok + bra xtileok xtile64: xbit $r7 $flags $p2 add b32 $r7 17 @@ -567,8 +565,8 @@ ifdef(`NVA3', // Op = (x * cpp) & ((1 << Tp) - 1) // Tx = (x * cpp) >> Tp - ld b32 $r10 D[$r5 + #ctx_src_xoff] - ld b32 $r11 D[$r5 + #ctx_src_cpp] + ld b32 $r10 D[$r5 + ctx_src_xoff] + ld b32 $r11 D[$r5 + ctx_src_cpp] mulu $r10 $r11 mov $r11 1 shl b32 $r11 $r7 @@ -578,7 +576,7 @@ ifdef(`NVA3', // Tyo = y & ((1 << Th) - 1) // Ty = y >> Th - ld b32 $r13 D[$r5 + #ctx_src_yoff] + ld b32 $r13 D[$r5 + ctx_src_yoff] mov $r14 1 shl b32 $r14 $r8 sub b32 $r14 1 @@ -600,8 +598,8 @@ ifdef(`NVA3', add b32 $r12 $r11 // nTx = ((w * cpp) + ((1 << Tp) - 1) >> Tp) - ld b32 $r15 D[$r5 + #ctx_src_xsize] - ld b32 $r11 D[$r5 + #ctx_src_cpp] + ld b32 $r15 D[$r5 + ctx_src_xsize] + ld b32 $r11 D[$r5 + ctx_src_cpp] mulu $r15 $r11 mov $r11 1 shl b32 $r11 $r7 @@ -611,7 +609,7 @@ ifdef(`NVA3', push $r15 // nTy = (h + ((1 << Th) - 1)) >> Th - ld b32 $r15 D[$r5 + #ctx_src_ysize] + ld b32 $r15 D[$r5 + ctx_src_ysize] mov $r11 1 shl b32 $r11 $r8 sub b32 $r11 1 @@ -631,7 +629,7 @@ ifdef(`NVA3', // Tz = z >> Td // Op += Tzo << Tys // Ts = Tys + Td - ld b32 $r8 D[$r5 + #ctx_src_zoff] + ld b32 $r8 D[$r5 + ctx_src_zoff] mov $r14 1 shl b32 $r14 $r9 sub b32 $r14 1 @@ -658,8 +656,8 @@ ifdef(`NVA3', // SRC_ADDRESS_LOW = (Ot + Op) & 0xffffffff // CFG_ADDRESS_HIGH |= ((Ot + Op) >> 32) << 16 - ld b32 $r7 D[$r5 + #ctx_src_address_low] - ld b32 $r8 D[$r5 + #ctx_src_address_high] + ld b32 $r7 D[$r5 + ctx_src_address_low] + ld b32 $r8 D[$r5 + ctx_src_address_high] add b32 $r10 $r12 add b32 $r7 $r10 adc b32 $r8 0 @@ -679,14 +677,14 @@ cmd_exec_set_surface_linear: xbit $r6 $flags $p2 add b32 $r6 0x202 shl b32 $r6 8 - ld b32 $r7 D[$r5 + #ctx_src_address_low] + ld b32 $r7 D[$r5 + ctx_src_address_low] iowr I[$r6 + 0x000] $r7 add b32 $r6 0x400 - ld b32 $r7 D[$r5 + #ctx_src_address_high] + ld b32 $r7 D[$r5 + ctx_src_address_high] shl b32 $r7 16 iowr I[$r6 + 0x000] $r7 add b32 $r6 0x400 - ld b32 $r7 D[$r5 + #ctx_src_pitch] + ld b32 $r7 D[$r5 + ctx_src_pitch] iowr I[$r6 + 0x000] $r7 ret @@ -699,7 +697,7 @@ cmd_exec_wait: loop: iord $r1 I[$r0] and $r1 1 - bra ne #loop + bra ne loop pop $r1 pop $r0 ret @@ -707,18 +705,18 @@ cmd_exec_wait: cmd_exec_query: // if QUERY_SHORT not set, write out { -, 0, TIME_LO, TIME_HI } xbit $r4 $r3 13 - bra ne #query_counter - call #cmd_exec_wait + bra ne query_counter + call cmd_exec_wait mov $r4 0x80c shl b32 $r4 6 - ld b32 $r5 D[$r0 + #ctx_query_address_low] + ld b32 $r5 D[$r0 + ctx_query_address_low] add b32 $r5 4 iowr I[$r4 + 0x000] $r5 iowr I[$r4 + 0x100] $r0 mov $r5 0xc iowr I[$r4 + 0x200] $r5 add b32 $r4 0x400 - ld b32 $r5 D[$r0 + #ctx_query_address_high] + ld b32 $r5 D[$r0 + ctx_query_address_high] shl b32 $r5 16 iowr I[$r4 + 0x000] $r5 add b32 $r4 0x500 @@ -743,16 +741,16 @@ cmd_exec_query: // write COUNTER query_counter: - call #cmd_exec_wait + call cmd_exec_wait mov $r4 0x80c shl b32 $r4 6 - ld b32 $r5 D[$r0 + #ctx_query_address_low] + ld b32 $r5 D[$r0 + ctx_query_address_low] iowr I[$r4 + 0x000] $r5 iowr I[$r4 + 0x100] $r0 mov $r5 0x4 iowr I[$r4 + 0x200] $r5 add b32 $r4 0x400 - ld b32 $r5 D[$r0 + #ctx_query_address_high] + ld b32 $r5 D[$r0 + ctx_query_address_high] shl b32 $r5 16 iowr I[$r4 + 0x000] $r5 add b32 $r4 0x500 @@ -761,7 +759,7 @@ cmd_exec_query: mov $r5 0x00001110 sethi $r5 0x13120000 iowr I[$r4 + 0x100] $r5 - ld b32 $r5 D[$r0 + #ctx_query_counter] + ld b32 $r5 D[$r0 + ctx_query_counter] add b32 $r4 0x500 iowr I[$r4 + 0x000] $r5 mov $r5 0x00002601 @@ -789,22 +787,22 @@ cmd_exec_query: // $r2: hostirq state // $r3: data cmd_exec: - call #cmd_exec_wait + call cmd_exec_wait // if format requested, call function to calculate it, otherwise // fill in cpp/xcnt for both surfaces as if (cpp == 1) xbit $r15 $r3 0 - bra e #cmd_exec_no_format - call #cmd_exec_set_format + bra e cmd_exec_no_format + call cmd_exec_set_format mov $r4 0x200 - bra #cmd_exec_init_src_surface + bra cmd_exec_init_src_surface cmd_exec_no_format: mov $r6 0x810 shl b32 $r6 6 mov $r7 1 - st b32 D[$r0 + #ctx_src_cpp] $r7 - st b32 D[$r0 + #ctx_dst_cpp] $r7 - ld b32 $r7 D[$r0 + #ctx_xcnt] + st b32 D[$r0 + ctx_src_cpp] $r7 + st b32 D[$r0 + ctx_dst_cpp] $r7 + ld b32 $r7 D[$r0 + ctx_xcnt] iowr I[$r6 + 0x000] $r7 iowr I[$r6 + 0x100] $r7 clear b32 $r4 @@ -813,28 +811,28 @@ cmd_exec: bclr $flags $p2 clear b32 $r5 xbit $r15 $r3 4 - bra e #src_tiled - call #cmd_exec_set_surface_linear - bra #cmd_exec_init_dst_surface + bra e src_tiled + call cmd_exec_set_surface_linear + bra cmd_exec_init_dst_surface src_tiled: - call #cmd_exec_set_surface_tiled + call cmd_exec_set_surface_tiled bset $r4 7 cmd_exec_init_dst_surface: bset $flags $p2 - mov $r5 #ctx_dst_address_high - #ctx_src_address_high + mov $r5 ctx_dst_address_high - ctx_src_address_high xbit $r15 $r3 8 - bra e #dst_tiled - call #cmd_exec_set_surface_linear - bra #cmd_exec_kick + bra e dst_tiled + call cmd_exec_set_surface_linear + bra cmd_exec_kick dst_tiled: - call #cmd_exec_set_surface_tiled + call cmd_exec_set_surface_tiled bset $r4 8 cmd_exec_kick: mov $r5 0x800 shl b32 $r5 6 - ld b32 $r6 D[$r0 + #ctx_ycnt] + ld b32 $r6 D[$r0 + ctx_ycnt] iowr I[$r5 + 0x100] $r6 mov $r6 0x0041 // SRC_TARGET = 1, DST_TARGET = 2 @@ -844,8 +842,8 @@ cmd_exec: // if requested, queue up a QUERY write after the copy has completed xbit $r15 $r3 12 - bra e #cmd_exec_done - call #cmd_exec_query + bra e cmd_exec_done + call cmd_exec_query cmd_exec_done: ret diff --git a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h index 1f33fbdc00be..2731de22ebe9 100644 --- a/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +++ b/trunk/drivers/gpu/drm/nouveau/nva3_copy.fuc.h @@ -152,7 +152,7 @@ uint32_t nva3_pcopy_code[] = { 0xf10010fe, 0xf1040017, 0xf0fff327, - 0x12d00023, + 0x22d00023, 0x0c25f0c0, 0xf40012d0, 0x17f11031, diff --git a/trunk/drivers/gpu/drm/nouveau/nva3_pm.c b/trunk/drivers/gpu/drm/nouveau/nva3_pm.c index 9e636e6ef6d7..618c144b7a30 100644 --- a/trunk/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nva3_pm.c @@ -287,13 +287,12 @@ nva3_pm_grcp_idle(void *data) return false; } -int +void nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nva3_pm_state *info = pre_state; unsigned long flags; - int ret = -EAGAIN; /* prevent any new grctx switches from starting */ spin_lock_irqsave(&dev_priv->context_switch_lock, flags); @@ -329,8 +328,6 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) nv_wr32(dev, 0x100210, 0x80000000); } - ret = 0; - cleanup: /* unfreeze PFIFO */ nv_mask(dev, 0x002504, 0x00000001, 0x00000000); @@ -342,5 +339,4 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) nv_mask(dev, 0x400824, 0x10000000, 0x10000000); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); kfree(info); - return ret; } diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h index a8d17458ced1..419903880e9d 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h @@ -145,7 +145,7 @@ uint32_t nvc0_pcopy_code[] = { 0xf10010fe, 0xf1040017, 0xf0fff327, - 0x12d00023, + 0x22d00023, 0x0c25f0c0, 0xf40012d0, 0x17f11031, diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c index 8ee3963f9030..ecfafd70cf0e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.c @@ -875,16 +875,14 @@ nvc0_graph_create(struct drm_device *dev) case 0xcf: /* 4/0/0/0, 3 */ priv->magic_not_rop_nr = 0x03; break; - case 0xd9: /* 1/0/0/0, 1 */ - priv->magic_not_rop_nr = 0x01; - break; } if (!priv->magic_not_rop_nr) { NV_ERROR(dev, "PGRAPH: unknown config: %d/%d/%d/%d, %d\n", priv->tp_nr[0], priv->tp_nr[1], priv->tp_nr[2], priv->tp_nr[3], priv->rop_nr); - priv->magic_not_rop_nr = 0x00; + /* use 0xc3's values... */ + priv->magic_not_rop_nr = 0x03; } NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */ diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.fuc b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.fuc index e6b228844a32..2a4b6dc8f9de 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.fuc +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.fuc @@ -71,9 +71,9 @@ queue_put: ld b32 $r9 D[$r13 + 0x4] // PUT xor $r8 8 cmpu b32 $r8 $r9 - bra ne #queue_put_next + bra ne queue_put_next mov $r15 E_CMD_OVERFLOW - call #error + call error ret // store cmd/data on queue @@ -104,7 +104,7 @@ queue_get: ld b32 $r8 D[$r13 + 0x0] // GET ld b32 $r9 D[$r13 + 0x4] // PUT cmpu b32 $r8 $r9 - bra e #queue_get_done + bra e queue_get_done // fetch first cmd/data pair and $r9 $r8 7 shl b32 $r9 3 @@ -135,9 +135,9 @@ nv_rd32: nv_rd32_wait: iord $r12 I[$r11 + 0x000] xbit $r12 $r12 31 - bra ne #nv_rd32_wait + bra ne nv_rd32_wait mov $r10 6 // DONE_MMIO_RD - call #wait_doneo + call wait_doneo iord $r15 I[$r11 + 0x100] // MMIO_RDVAL ret @@ -157,7 +157,7 @@ nv_wr32: nv_wr32_wait: iord $r12 I[$r11 + 0x000] xbit $r12 $r12 31 - bra ne #nv_wr32_wait + bra ne nv_wr32_wait ret // (re)set watchdog timer @@ -193,7 +193,7 @@ $1: shl b32 $r8 6 iord $r8 I[$r8 + 0x000] // DONE xbit $r8 $r8 $r10 - bra $2 #wait_done_$1 + bra $2 wait_done_$1 trace_clr(T_WAIT) ret ') @@ -216,7 +216,7 @@ mmctx_size: add b32 $r9 $r8 add b32 $r14 4 cmpu b32 $r14 $r15 - bra ne #nv_mmctx_size_loop + bra ne nv_mmctx_size_loop mov b32 $r15 $r9 ret @@ -238,12 +238,12 @@ mmctx_xfer: shl b32 $r8 6 clear b32 $r9 or $r11 $r11 - bra e #mmctx_base_disabled + bra e mmctx_base_disabled iowr I[$r8 + 0x000] $r11 // MMCTX_BASE bset $r9 0 // BASE_EN mmctx_base_disabled: or $r14 $r14 - bra e #mmctx_multi_disabled + bra e mmctx_multi_disabled iowr I[$r8 + 0x200] $r14 // MMCTX_MULTI_STRIDE iowr I[$r8 + 0x300] $r15 // MMCTX_MULTI_MASK bset $r9 1 // MULTI_EN @@ -264,7 +264,7 @@ mmctx_xfer: mmctx_wait_free: iord $r14 I[$r8 + 0x000] // MMCTX_CTRL and $r14 0x1f - bra e #mmctx_wait_free + bra e mmctx_wait_free // queue up an entry ld b32 $r14 D[$r12] @@ -272,19 +272,19 @@ mmctx_xfer: iowr I[$r8 + 0x300] $r14 add b32 $r12 4 cmpu b32 $r12 $r13 - bra ne #mmctx_exec_loop + bra ne mmctx_exec_loop xbit $r11 $r10 2 - bra ne #mmctx_stop + bra ne mmctx_stop // wait for queue to empty mmctx_fini_wait: iord $r11 I[$r8 + 0x000] // MMCTX_CTRL and $r11 0x1f cmpu b32 $r11 0x10 - bra ne #mmctx_fini_wait + bra ne mmctx_fini_wait mov $r10 2 // DONE_MMCTX - call #wait_donez - bra #mmctx_done + call wait_donez + bra mmctx_done mmctx_stop: xbit $r11 $r10 0 shl b32 $r11 16 // DIR @@ -295,7 +295,7 @@ mmctx_xfer: // wait for STOP_TRIGGER to clear iord $r11 I[$r8 + 0x000] // MMCTX_CTRL xbit $r11 $r11 18 - bra ne #mmctx_stop_wait + bra ne mmctx_stop_wait mmctx_done: trace_clr(T_MMCTX) ret @@ -305,7 +305,7 @@ mmctx_xfer: strand_wait: push $r10 mov $r10 2 - call #wait_donez + call wait_donez pop $r10 ret @@ -316,7 +316,7 @@ strand_pre: sethi $r8 0x20000 mov $r9 0xc iowr I[$r8] $r9 - call #strand_wait + call strand_wait ret // unknown - call after issuing strand commands @@ -326,7 +326,7 @@ strand_post: sethi $r8 0x20000 mov $r9 0xd iowr I[$r8] $r9 - call #strand_wait + call strand_wait ret // Selects strand set?! @@ -341,11 +341,11 @@ strand_set: iowr I[$r10 + 0x000] $r12 // 0x93c = 0xf mov $r12 0xb iowr I[$r11 + 0x000] $r12 // 0x928 = 0xb - call #strand_wait + call strand_wait iowr I[$r10 + 0x000] $r14 // 0x93c = mov $r12 0xa iowr I[$r11 + 0x000] $r12 // 0x928 = 0xa - call #strand_wait + call strand_wait ret // Initialise strand context data @@ -357,22 +357,22 @@ strand_set: // strand_ctx_init: trace_set(T_STRINIT) - call #strand_pre + call strand_pre mov $r14 3 - call #strand_set + call strand_set mov $r10 0x46fc sethi $r10 0x20000 add b32 $r11 $r10 0x400 iowr I[$r10 + 0x100] $r0 // STRAND_FIRST_GENE = 0 mov $r12 1 iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_FIRST_GENE - call #strand_wait + call strand_wait sub b32 $r12 $r0 1 iowr I[$r10 + 0x000] $r12 // STRAND_GENE_CNT = 0xffffffff mov $r12 2 iowr I[$r11 + 0x000] $r12 // STRAND_CMD = LATCH_GENE_CNT - call #strand_wait - call #strand_post + call strand_wait + call strand_post // read the size of each strand, poke the context offset of // each into STRAND_{SAVE,LOAD}_SWBASE now, no need to worry @@ -391,7 +391,7 @@ strand_ctx_init: add b32 $r14 $r10 add b32 $r8 4 sub b32 $r9 1 - bra ne #ctx_init_strand_loop + bra ne ctx_init_strand_loop shl b32 $r14 8 sub b32 $r15 $r14 $r15 diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.h b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.h index 91d44ea662d9..636fe9812f79 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_graph.h +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_graph.h @@ -87,7 +87,6 @@ nvc0_graph_class(struct drm_device *dev) case 0xc1: return 0x9197; case 0xc8: - case 0xd9: return 0x9297; default: return 0; diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_grctx.c b/trunk/drivers/gpu/drm/nouveau/nvc0_grctx.c index de77842b31c0..96b0b93d94ca 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_grctx.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_grctx.c @@ -1268,17 +1268,6 @@ nvc0_grctx_generate_9039(struct drm_device *dev) static void nvc0_grctx_generate_90c0(struct drm_device *dev) { - struct drm_nouveau_private *dev_priv = dev->dev_private; - int i; - - for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { - nv_mthd(dev, 0x90c0, 0x2700 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2720 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2704 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2724 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2708 + (i * 0x40), 0x00000000); - nv_mthd(dev, 0x90c0, 0x2728 + (i * 0x40), 0x00000000); - } nv_mthd(dev, 0x90c0, 0x270c, 0x00000000); nv_mthd(dev, 0x90c0, 0x272c, 0x00000000); nv_mthd(dev, 0x90c0, 0x274c, 0x00000000); @@ -1287,12 +1276,6 @@ nvc0_grctx_generate_90c0(struct drm_device *dev) nv_mthd(dev, 0x90c0, 0x27ac, 0x00000000); nv_mthd(dev, 0x90c0, 0x27cc, 0x00000000); nv_mthd(dev, 0x90c0, 0x27ec, 0x00000000); - for (i = 0; dev_priv->chipset == 0xd9 && i < 4; i++) { - nv_mthd(dev, 0x90c0, 0x2710 + (i * 0x40), 0x00014000); - nv_mthd(dev, 0x90c0, 0x2730 + (i * 0x40), 0x00014000); - nv_mthd(dev, 0x90c0, 0x2714 + (i * 0x40), 0x00000040); - nv_mthd(dev, 0x90c0, 0x2734 + (i * 0x40), 0x00000040); - } nv_mthd(dev, 0x90c0, 0x030c, 0x00000001); nv_mthd(dev, 0x90c0, 0x1944, 0x00000000); nv_mthd(dev, 0x90c0, 0x0758, 0x00000100); @@ -1488,20 +1471,14 @@ nvc0_grctx_generate_shaders(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - if (dev_priv->chipset == 0xd9) { - nv_wr32(dev, 0x405800, 0x0f8000bf); - nv_wr32(dev, 0x405830, 0x02180218); - nv_wr32(dev, 0x405834, 0x08000000); - } else - if (dev_priv->chipset == 0xc1) { - nv_wr32(dev, 0x405800, 0x0f8000bf); - nv_wr32(dev, 0x405830, 0x02180218); - nv_wr32(dev, 0x405834, 0x00000000); - } else { + if (dev_priv->chipset != 0xc1) { nv_wr32(dev, 0x405800, 0x078000bf); nv_wr32(dev, 0x405830, 0x02180000); - nv_wr32(dev, 0x405834, 0x00000000); + } else { + nv_wr32(dev, 0x405800, 0x0f8000bf); + nv_wr32(dev, 0x405830, 0x02180218); } + nv_wr32(dev, 0x405834, 0x00000000); nv_wr32(dev, 0x405838, 0x00000000); nv_wr32(dev, 0x405854, 0x00000000); nv_wr32(dev, 0x405870, 0x00000001); @@ -1532,10 +1509,7 @@ nvc0_grctx_generate_unk64xx(struct drm_device *dev) nv_wr32(dev, 0x4064ac, 0x00003fff); nv_wr32(dev, 0x4064b4, 0x00000000); nv_wr32(dev, 0x4064b8, 0x00000000); - if (dev_priv->chipset == 0xd9) - nv_wr32(dev, 0x4064bc, 0x00000000); - if (dev_priv->chipset == 0xc1 || - dev_priv->chipset == 0xd9) { + if (dev_priv->chipset == 0xc1) { nv_wr32(dev, 0x4064c0, 0x80140078); nv_wr32(dev, 0x4064c4, 0x0086ffff); } @@ -1576,23 +1550,10 @@ nvc0_grctx_generate_rop(struct drm_device *dev) /* ROPC_BROADCAST */ nv_wr32(dev, 0x408800, 0x02802a3c); nv_wr32(dev, 0x408804, 0x00000040); - if (chipset == 0xd9) { - nv_wr32(dev, 0x408808, 0x1043e005); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x1043e005); - nv_wr32(dev, 0x408908, 0x00c8102f); - } else - if (chipset == 0xc1) { - nv_wr32(dev, 0x408808, 0x1003e005); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x62000001); - nv_wr32(dev, 0x408908, 0x00c80929); - } else { - nv_wr32(dev, 0x408808, 0x0003e00d); - nv_wr32(dev, 0x408900, 0x3080b801); - nv_wr32(dev, 0x408904, 0x02000001); - nv_wr32(dev, 0x408908, 0x00c80929); - } + nv_wr32(dev, 0x408808, chipset != 0xc1 ? 0x0003e00d : 0x1003e005); + nv_wr32(dev, 0x408900, 0x3080b801); + nv_wr32(dev, 0x408904, chipset != 0xc1 ? 0x02000001 : 0x62000001); + nv_wr32(dev, 0x408908, 0x00c80929); nv_wr32(dev, 0x40890c, 0x00000000); nv_wr32(dev, 0x408980, 0x0000011d); } @@ -1611,7 +1572,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) nv_wr32(dev, 0x418408, 0x00000000); nv_wr32(dev, 0x41840c, 0x00001008); nv_wr32(dev, 0x418410, 0x0fff0fff); - nv_wr32(dev, 0x418414, chipset != 0xd9 ? 0x00200fff : 0x02200fff); + nv_wr32(dev, 0x418414, 0x00200fff); nv_wr32(dev, 0x418450, 0x00000000); nv_wr32(dev, 0x418454, 0x00000000); nv_wr32(dev, 0x418458, 0x00000000); @@ -1626,17 +1587,14 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) nv_wr32(dev, 0x418700, 0x00000002); nv_wr32(dev, 0x418704, 0x00000080); nv_wr32(dev, 0x418708, 0x00000000); - nv_wr32(dev, 0x41870c, chipset != 0xd9 ? 0x07c80000 : 0x00000000); + nv_wr32(dev, 0x41870c, 0x07c80000); nv_wr32(dev, 0x418710, 0x00000000); - nv_wr32(dev, 0x418800, chipset != 0xd9 ? 0x0006860a : 0x7006860a); + nv_wr32(dev, 0x418800, 0x0006860a); nv_wr32(dev, 0x418808, 0x00000000); nv_wr32(dev, 0x41880c, 0x00000000); nv_wr32(dev, 0x418810, 0x00000000); nv_wr32(dev, 0x418828, 0x00008442); - if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x418830, 0x10000001); - else - nv_wr32(dev, 0x418830, 0x00000001); + nv_wr32(dev, 0x418830, chipset != 0xc1 ? 0x00000001 : 0x10000001); nv_wr32(dev, 0x4188d8, 0x00000008); nv_wr32(dev, 0x4188e0, 0x01000000); nv_wr32(dev, 0x4188e8, 0x00000000); @@ -1644,12 +1602,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) nv_wr32(dev, 0x4188f0, 0x00000000); nv_wr32(dev, 0x4188f4, 0x00000000); nv_wr32(dev, 0x4188f8, 0x00000000); - if (chipset == 0xd9) - nv_wr32(dev, 0x4188fc, 0x20100008); - else if (chipset == 0xc1) - nv_wr32(dev, 0x4188fc, 0x00100018); - else - nv_wr32(dev, 0x4188fc, 0x00100000); + nv_wr32(dev, 0x4188fc, chipset != 0xc1 ? 0x00100000 : 0x00100018); nv_wr32(dev, 0x41891c, 0x00ff00ff); nv_wr32(dev, 0x418924, 0x00000000); nv_wr32(dev, 0x418928, 0x00ffff00); @@ -1663,7 +1616,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) nv_wr32(dev, 0x418a14 + (i * 0x20), 0x00000000); nv_wr32(dev, 0x418a18 + (i * 0x20), 0x00000000); } - nv_wr32(dev, 0x418b00, chipset != 0xd9 ? 0x00000000 : 0x00000006); + nv_wr32(dev, 0x418b00, 0x00000000); nv_wr32(dev, 0x418b08, 0x0a418820); nv_wr32(dev, 0x418b0c, 0x062080e6); nv_wr32(dev, 0x418b10, 0x020398a4); @@ -1680,7 +1633,7 @@ nvc0_grctx_generate_gpc(struct drm_device *dev) nv_wr32(dev, 0x418c24, 0x00000000); nv_wr32(dev, 0x418c28, 0x00000000); nv_wr32(dev, 0x418c2c, 0x00000000); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1) nv_wr32(dev, 0x418c6c, 0x00000001); nv_wr32(dev, 0x418c80, 0x20200004); nv_wr32(dev, 0x418c8c, 0x00000001); @@ -1700,10 +1653,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev) nv_wr32(dev, 0x419818, 0x00000000); nv_wr32(dev, 0x41983c, 0x00038bc7); nv_wr32(dev, 0x419848, 0x00000000); - if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419864, 0x00000129); - else - nv_wr32(dev, 0x419864, 0x0000012a); + nv_wr32(dev, 0x419864, chipset != 0xc1 ? 0x0000012a : 0x00000129); nv_wr32(dev, 0x419888, 0x00000000); nv_wr32(dev, 0x419a00, 0x000001f0); nv_wr32(dev, 0x419a04, 0x00000001); @@ -1713,9 +1663,7 @@ nvc0_grctx_generate_tp(struct drm_device *dev) nv_wr32(dev, 0x419a14, 0x00000200); nv_wr32(dev, 0x419a1c, 0x00000000); nv_wr32(dev, 0x419a20, 0x00000800); - if (chipset == 0xd9) - nv_wr32(dev, 0x00419ac4, 0x0017f440); - else if (chipset != 0xc0 && chipset != 0xc8) + if (chipset != 0xc0 && chipset != 0xc8) nv_wr32(dev, 0x00419ac4, 0x0007f440); nv_wr32(dev, 0x419b00, 0x0a418820); nv_wr32(dev, 0x419b04, 0x062080e6); @@ -1724,33 +1672,21 @@ nvc0_grctx_generate_tp(struct drm_device *dev) nv_wr32(dev, 0x419b10, 0x0a418820); nv_wr32(dev, 0x419b14, 0x000000e6); nv_wr32(dev, 0x419bd0, 0x00900103); - if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419be0, 0x00400001); - else - nv_wr32(dev, 0x419be0, 0x00000001); + nv_wr32(dev, 0x419be0, chipset != 0xc1 ? 0x00000001 : 0x00400001); nv_wr32(dev, 0x419be4, 0x00000000); - nv_wr32(dev, 0x419c00, chipset != 0xd9 ? 0x00000002 : 0x0000000a); + nv_wr32(dev, 0x419c00, 0x00000002); nv_wr32(dev, 0x419c04, 0x00000006); nv_wr32(dev, 0x419c08, 0x00000002); nv_wr32(dev, 0x419c20, 0x00000000); - if (dev_priv->chipset == 0xd9) { - nv_wr32(dev, 0x419c24, 0x00084210); - nv_wr32(dev, 0x419c28, 0x3cf3cf3c); + if (chipset == 0xce || chipset == 0xcf) nv_wr32(dev, 0x419cb0, 0x00020048); - } else - if (chipset == 0xce || chipset == 0xcf) { - nv_wr32(dev, 0x419cb0, 0x00020048); - } else { + else nv_wr32(dev, 0x419cb0, 0x00060048); - } nv_wr32(dev, 0x419ce8, 0x00000000); nv_wr32(dev, 0x419cf4, 0x00000183); - if (chipset == 0xc1 || chipset == 0xd9) - nv_wr32(dev, 0x419d20, 0x12180000); - else - nv_wr32(dev, 0x419d20, 0x02180000); + nv_wr32(dev, 0x419d20, chipset != 0xc1 ? 0x02180000 : 0x12180000); nv_wr32(dev, 0x419d24, 0x00001fff); - if (chipset == 0xc1 || chipset == 0xd9) + if (chipset == 0xc1) nv_wr32(dev, 0x419d44, 0x02180218); nv_wr32(dev, 0x419e04, 0x00000000); nv_wr32(dev, 0x419e08, 0x00000000); @@ -2050,10 +1986,6 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_icmd(dev, 0x00000215, 0x00000040); nv_icmd(dev, 0x00000216, 0x00000040); nv_icmd(dev, 0x00000217, 0x00000040); - if (dev_priv->chipset == 0xd9) { - for (i = 0x0400; i <= 0x0417; i++) - nv_icmd(dev, i, 0x00000040); - } nv_icmd(dev, 0x00000218, 0x0000c080); nv_icmd(dev, 0x00000219, 0x0000c080); nv_icmd(dev, 0x0000021a, 0x0000c080); @@ -2062,10 +1994,6 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_icmd(dev, 0x0000021d, 0x0000c080); nv_icmd(dev, 0x0000021e, 0x0000c080); nv_icmd(dev, 0x0000021f, 0x0000c080); - if (dev_priv->chipset == 0xd9) { - for (i = 0x0440; i <= 0x0457; i++) - nv_icmd(dev, i, 0x0000c080); - } nv_icmd(dev, 0x000000ad, 0x0000013e); nv_icmd(dev, 0x000000e1, 0x00000010); nv_icmd(dev, 0x00000290, 0x00000000); @@ -2628,8 +2556,7 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_icmd(dev, 0x0000053f, 0xffff0000); nv_icmd(dev, 0x00000585, 0x0000003f); nv_icmd(dev, 0x00000576, 0x00000003); - if (dev_priv->chipset == 0xc1 || - dev_priv->chipset == 0xd9) + if (dev_priv->chipset == 0xc1) nv_icmd(dev, 0x0000057b, 0x00000059); nv_icmd(dev, 0x00000586, 0x00000040); nv_icmd(dev, 0x00000582, 0x00000080); @@ -2731,8 +2658,6 @@ nvc0_grctx_generate(struct nouveau_channel *chan) nv_icmd(dev, 0x00000957, 0x00000003); nv_icmd(dev, 0x0000095e, 0x20164010); nv_icmd(dev, 0x0000095f, 0x00000020); - if (dev_priv->chipset == 0xd9) - nv_icmd(dev, 0x0000097d, 0x00000020); nv_icmd(dev, 0x00000683, 0x00000006); nv_icmd(dev, 0x00000685, 0x003fffff); nv_icmd(dev, 0x00000687, 0x00000c48); diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc b/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc index 15272be33b66..06f5e26d1e0f 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc @@ -32,7 +32,7 @@ * - watchdog timer around ctx operations */ -.section #nvc0_grgpc_data +.section nvc0_grgpc_data include(`nvc0_graph.fuc') gpc_id: .b32 0 gpc_mmio_list_head: .b32 0 @@ -48,45 +48,40 @@ cmd_queue: queue_init // chipset descriptions chipsets: .b8 0xc0 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc0_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvc0_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc0_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvc0_tpc_mmio_tail .b8 0xc1 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc1_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvc1_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc1_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvc1_tpc_mmio_tail .b8 0xc3 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc0_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvc3_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc0_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvc3_tpc_mmio_tail .b8 0xc4 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc0_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvc3_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc0_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvc3_tpc_mmio_tail .b8 0xc8 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc0_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvc0_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc0_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvc0_tpc_mmio_tail .b8 0xce 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc0_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvc3_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc0_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvc3_tpc_mmio_tail .b8 0xcf 0 0 0 -.b16 #nvc0_gpc_mmio_head -.b16 #nvc0_gpc_mmio_tail -.b16 #nvc0_tpc_mmio_head -.b16 #nvcf_tpc_mmio_tail -.b8 0xd9 0 0 0 -.b16 #nvd9_gpc_mmio_head -.b16 #nvd9_gpc_mmio_tail -.b16 #nvd9_tpc_mmio_head -.b16 #nvd9_tpc_mmio_tail +.b16 nvc0_gpc_mmio_head +.b16 nvc0_gpc_mmio_tail +.b16 nvc0_tpc_mmio_head +.b16 nvcf_tpc_mmio_tail .b8 0 0 0 0 // GPC mmio lists @@ -119,35 +114,6 @@ nvc0_gpc_mmio_tail: mmctx_data(0x000c6c, 1); nvc1_gpc_mmio_tail: -nvd9_gpc_mmio_head: -mmctx_data(0x000380, 1) -mmctx_data(0x000400, 2) -mmctx_data(0x00040c, 3) -mmctx_data(0x000450, 9) -mmctx_data(0x000600, 1) -mmctx_data(0x000684, 1) -mmctx_data(0x000700, 5) -mmctx_data(0x000800, 1) -mmctx_data(0x000808, 3) -mmctx_data(0x000828, 1) -mmctx_data(0x000830, 1) -mmctx_data(0x0008d8, 1) -mmctx_data(0x0008e0, 1) -mmctx_data(0x0008e8, 6) -mmctx_data(0x00091c, 1) -mmctx_data(0x000924, 3) -mmctx_data(0x000b00, 1) -mmctx_data(0x000b08, 6) -mmctx_data(0x000bb8, 1) -mmctx_data(0x000c08, 1) -mmctx_data(0x000c10, 8) -mmctx_data(0x000c6c, 1) -mmctx_data(0x000c80, 1) -mmctx_data(0x000c8c, 1) -mmctx_data(0x001000, 3) -mmctx_data(0x001014, 1) -nvd9_gpc_mmio_tail: - // TPC mmio lists nvc0_tpc_mmio_head: mmctx_data(0x000018, 1) @@ -180,34 +146,9 @@ nvc3_tpc_mmio_tail: mmctx_data(0x000544, 1) nvc1_tpc_mmio_tail: -nvd9_tpc_mmio_head: -mmctx_data(0x000018, 1) -mmctx_data(0x00003c, 1) -mmctx_data(0x000048, 1) -mmctx_data(0x000064, 1) -mmctx_data(0x000088, 1) -mmctx_data(0x000200, 6) -mmctx_data(0x00021c, 2) -mmctx_data(0x0002c4, 1) -mmctx_data(0x000300, 6) -mmctx_data(0x0003d0, 1) -mmctx_data(0x0003e0, 2) -mmctx_data(0x000400, 3) -mmctx_data(0x000420, 3) -mmctx_data(0x0004b0, 1) -mmctx_data(0x0004e8, 1) -mmctx_data(0x0004f4, 1) -mmctx_data(0x000520, 2) -mmctx_data(0x000544, 1) -mmctx_data(0x000604, 4) -mmctx_data(0x000644, 20) -mmctx_data(0x000698, 1) -mmctx_data(0x0006e0, 1) -mmctx_data(0x000750, 3) -nvd9_tpc_mmio_tail: -.section #nvc0_grgpc_code -bra #init +.section nvc0_grgpc_code +bra init define(`include_code') include(`nvc0_graph.fuc') @@ -219,10 +160,10 @@ error: push $r14 mov $r14 -0x67ec // 0x9814 sethi $r14 0x400000 - call #nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code + call nv_wr32 // HUB_CTXCTL_CC_SCRATCH[5] = error code add b32 $r14 0x41c mov $r15 1 - call #nv_wr32 // HUB_CTXCTL_INTR_UP_SET + call nv_wr32 // HUB_CTXCTL_INTR_UP_SET pop $r14 ret @@ -249,7 +190,7 @@ init: iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE // setup i0 handler, and route all interrupts to it - mov $r1 #ih + mov $r1 ih mov $iv0 $r1 mov $r1 0x400 iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH @@ -269,24 +210,24 @@ init: and $r2 0x1f shl b32 $r3 $r2 sub b32 $r3 1 - st b32 D[$r0 + #tpc_count] $r2 - st b32 D[$r0 + #tpc_mask] $r3 + st b32 D[$r0 + tpc_count] $r2 + st b32 D[$r0 + tpc_mask] $r3 add b32 $r1 0x400 iord $r2 I[$r1 + 0x000] // MYINDEX - st b32 D[$r0 + #gpc_id] $r2 + st b32 D[$r0 + gpc_id] $r2 // find context data for this chipset mov $r2 0x800 shl b32 $r2 6 iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] - mov $r1 #chipsets - 12 + mov $r1 chipsets - 12 init_find_chipset: add b32 $r1 12 ld b32 $r3 D[$r1 + 0x00] cmpu b32 $r3 $r2 - bra e #init_context + bra e init_context cmpu b32 $r3 0 - bra ne #init_find_chipset + bra ne init_find_chipset // unknown chipset ret @@ -312,19 +253,19 @@ init: clear b32 $r15 ld b16 $r14 D[$r1 + 4] ld b16 $r15 D[$r1 + 6] - st b16 D[$r0 + #gpc_mmio_list_head] $r14 - st b16 D[$r0 + #gpc_mmio_list_tail] $r15 - call #mmctx_size + st b16 D[$r0 + gpc_mmio_list_head] $r14 + st b16 D[$r0 + gpc_mmio_list_tail] $r15 + call mmctx_size add b32 $r2 $r15 add b32 $r3 $r15 // calculate per-TPC mmio context size, store the list pointers ld b16 $r14 D[$r1 + 8] ld b16 $r15 D[$r1 + 10] - st b16 D[$r0 + #tpc_mmio_list_head] $r14 - st b16 D[$r0 + #tpc_mmio_list_tail] $r15 - call #mmctx_size - ld b32 $r14 D[$r0 + #tpc_count] + st b16 D[$r0 + tpc_mmio_list_head] $r14 + st b16 D[$r0 + tpc_mmio_list_tail] $r15 + call mmctx_size + ld b32 $r14 D[$r0 + tpc_count] mulu $r14 $r15 add b32 $r2 $r14 add b32 $r3 $r14 @@ -342,7 +283,7 @@ init: // calculate size of strand context data mov b32 $r15 $r2 - call #strand_ctx_init + call strand_ctx_init add b32 $r3 $r15 // save context size, and tell HUB we're done @@ -360,13 +301,13 @@ init: main: bset $flags $p0 sleep $p0 - mov $r13 #cmd_queue - call #queue_get - bra $p1 #main + mov $r13 cmd_queue + call queue_get + bra $p1 main // 0x0000-0x0003 are all context transfers cmpu b32 $r14 0x04 - bra nc #main_not_ctx_xfer + bra nc main_not_ctx_xfer // fetch $flags and mask off $p1/$p2 mov $r1 $flags mov $r2 0x0006 @@ -377,14 +318,14 @@ main: or $r1 $r14 mov $flags $r1 // transfer context data - call #ctx_xfer - bra #main + call ctx_xfer + bra main main_not_ctx_xfer: shl b32 $r15 $r14 16 or $r15 E_BAD_COMMAND - call #error - bra #main + call error + bra main // interrupt handler ih: @@ -401,13 +342,13 @@ ih: // incoming fifo command? iord $r10 I[$r0 + 0x200] // INTR and $r11 $r10 0x00000004 - bra e #ih_no_fifo + bra e ih_no_fifo // queue incoming fifo command for later processing mov $r11 0x1900 - mov $r13 #cmd_queue + mov $r13 cmd_queue iord $r14 I[$r11 + 0x100] // FIFO_CMD iord $r15 I[$r11 + 0x000] // FIFO_DATA - call #queue_put + call queue_put add b32 $r11 0x400 mov $r14 1 iowr I[$r11 + 0x000] $r14 // FIFO_ACK @@ -433,11 +374,11 @@ ih: // hub_barrier_done: mov $r15 1 - ld b32 $r14 D[$r0 + #gpc_id] + ld b32 $r14 D[$r0 + gpc_id] shl b32 $r15 $r14 mov $r14 -0x6be8 // 0x409418 - HUB_BAR_SET sethi $r14 0x400000 - call #nv_wr32 + call nv_wr32 ret // Disables various things, waits a bit, and re-enables them.. @@ -454,7 +395,7 @@ ctx_redswitch: mov $r15 8 ctx_redswitch_delay: sub b32 $r15 1 - bra ne #ctx_redswitch_delay + bra ne ctx_redswitch_delay mov $r15 0xa20 iowr I[$r14] $r15 // GPC_RED_SWITCH = UNK11, ENABLE, POWER ret @@ -472,8 +413,8 @@ ctx_xfer: mov $r1 0xa04 shl b32 $r1 6 iowr I[$r1 + 0x000] $r15// MEM_BASE - bra not $p1 #ctx_xfer_not_load - call #ctx_redswitch + bra not $p1 ctx_xfer_not_load + call ctx_redswitch ctx_xfer_not_load: // strands @@ -481,7 +422,7 @@ ctx_xfer: sethi $r1 0x20000 mov $r2 0xc iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c - call #strand_wait + call strand_wait mov $r2 0x47fc sethi $r2 0x20000 iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 @@ -494,46 +435,46 @@ ctx_xfer: or $r10 2 // first mov $r11 0x0000 sethi $r11 0x500000 - ld b32 $r12 D[$r0 + #gpc_id] + ld b32 $r12 D[$r0 + gpc_id] shl b32 $r12 15 add b32 $r11 $r12 // base = NV_PGRAPH_GPCn - ld b32 $r12 D[$r0 + #gpc_mmio_list_head] - ld b32 $r13 D[$r0 + #gpc_mmio_list_tail] + ld b32 $r12 D[$r0 + gpc_mmio_list_head] + ld b32 $r13 D[$r0 + gpc_mmio_list_tail] mov $r14 0 // not multi - call #mmctx_xfer + call mmctx_xfer // per-TPC mmio context xbit $r10 $flags $p1 // direction or $r10 4 // last mov $r11 0x4000 sethi $r11 0x500000 // base = NV_PGRAPH_GPC0_TPC0 - ld b32 $r12 D[$r0 + #gpc_id] + ld b32 $r12 D[$r0 + gpc_id] shl b32 $r12 15 add b32 $r11 $r12 // base = NV_PGRAPH_GPCn_TPC0 - ld b32 $r12 D[$r0 + #tpc_mmio_list_head] - ld b32 $r13 D[$r0 + #tpc_mmio_list_tail] - ld b32 $r15 D[$r0 + #tpc_mask] + ld b32 $r12 D[$r0 + tpc_mmio_list_head] + ld b32 $r13 D[$r0 + tpc_mmio_list_tail] + ld b32 $r15 D[$r0 + tpc_mask] mov $r14 0x800 // stride = 0x800 - call #mmctx_xfer + call mmctx_xfer // wait for strands to finish - call #strand_wait + call strand_wait // if load, or a save without a load following, do some // unknown stuff that's done after finishing a block of // strand commands - bra $p1 #ctx_xfer_post - bra not $p2 #ctx_xfer_done + bra $p1 ctx_xfer_post + bra not $p2 ctx_xfer_done ctx_xfer_post: mov $r1 0x4afc sethi $r1 0x20000 mov $r2 0xd iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0d - call #strand_wait + call strand_wait // mark completion in HUB's barrier ctx_xfer_done: - call #hub_barrier_done + call hub_barrier_done ret .align 256 diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h b/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h index a988b8ad00ac..6f820324480e 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_grgpc.fuc.h @@ -25,29 +25,26 @@ uint32_t nvc0_grgpc_data[] = { 0x00000000, 0x00000000, 0x000000c0, - 0x012800c8, - 0x01e40194, + 0x011c00bc, + 0x01700120, 0x000000c1, - 0x012c00c8, - 0x01f80194, + 0x012000bc, + 0x01840120, 0x000000c3, - 0x012800c8, - 0x01f40194, + 0x011c00bc, + 0x01800120, 0x000000c4, - 0x012800c8, - 0x01f40194, + 0x011c00bc, + 0x01800120, 0x000000c8, - 0x012800c8, - 0x01e40194, + 0x011c00bc, + 0x01700120, 0x000000ce, - 0x012800c8, - 0x01f40194, + 0x011c00bc, + 0x01800120, 0x000000cf, - 0x012800c8, - 0x01f00194, - 0x000000d9, - 0x0194012c, - 0x025401f8, + 0x011c00bc, + 0x017c0120, 0x00000000, 0x00000380, 0x14000400, @@ -74,32 +71,6 @@ uint32_t nvc0_grgpc_data[] = { 0x08001000, 0x00001014, 0x00000c6c, - 0x00000380, - 0x04000400, - 0x0800040c, - 0x20000450, - 0x00000600, - 0x00000684, - 0x10000700, - 0x00000800, - 0x08000808, - 0x00000828, - 0x00000830, - 0x000008d8, - 0x000008e0, - 0x140008e8, - 0x0000091c, - 0x08000924, - 0x00000b00, - 0x14000b08, - 0x00000bb8, - 0x00000c08, - 0x1c000c10, - 0x00000c6c, - 0x00000c80, - 0x00000c8c, - 0x08001000, - 0x00001014, 0x00000018, 0x0000003c, 0x00000048, @@ -125,29 +96,6 @@ uint32_t nvc0_grgpc_data[] = { 0x000006e0, 0x000004bc, 0x00000544, - 0x00000018, - 0x0000003c, - 0x00000048, - 0x00000064, - 0x00000088, - 0x14000200, - 0x0400021c, - 0x000002c4, - 0x14000300, - 0x000003d0, - 0x040003e0, - 0x08000400, - 0x08000420, - 0x000004b0, - 0x000004e8, - 0x000004f4, - 0x04000520, - 0x00000544, - 0x0c000604, - 0x4c000644, - 0x00000698, - 0x000006e0, - 0x08000750, }; uint32_t nvc0_grgpc_code[] = { diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc b/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc index 98acddb2c5bb..e4f8c7e89ddd 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc @@ -27,7 +27,7 @@ * m4 nvc0_grhub.fuc | envyas -a -w -m fuc -V nva3 -o nvc0_grhub.fuc.h */ -.section #nvc0_grhub_data +.section nvc0_grhub_data include(`nvc0_graph.fuc') gpc_count: .b32 0 rop_count: .b32 0 @@ -39,29 +39,26 @@ ctx_current: .b32 0 chipsets: .b8 0xc0 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc0_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc0_hub_mmio_tail .b8 0xc1 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc1_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc1_hub_mmio_tail .b8 0xc3 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc0_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc0_hub_mmio_tail .b8 0xc4 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc0_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc0_hub_mmio_tail .b8 0xc8 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc0_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc0_hub_mmio_tail .b8 0xce 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc0_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc0_hub_mmio_tail .b8 0xcf 0 0 0 -.b16 #nvc0_hub_mmio_head -.b16 #nvc0_hub_mmio_tail -.b8 0xd9 0 0 0 -.b16 #nvd9_hub_mmio_head -.b16 #nvd9_hub_mmio_tail +.b16 nvc0_hub_mmio_head +.b16 nvc0_hub_mmio_tail .b8 0 0 0 0 nvc0_hub_mmio_head: @@ -108,48 +105,6 @@ nvc0_hub_mmio_tail: mmctx_data(0x4064c0, 2) nvc1_hub_mmio_tail: -nvd9_hub_mmio_head: -mmctx_data(0x17e91c, 2) -mmctx_data(0x400204, 2) -mmctx_data(0x404004, 10) -mmctx_data(0x404044, 1) -mmctx_data(0x404094, 14) -mmctx_data(0x4040d0, 7) -mmctx_data(0x4040f8, 1) -mmctx_data(0x404130, 3) -mmctx_data(0x404150, 3) -mmctx_data(0x404164, 2) -mmctx_data(0x404178, 2) -mmctx_data(0x404200, 8) -mmctx_data(0x404404, 14) -mmctx_data(0x404460, 4) -mmctx_data(0x404480, 1) -mmctx_data(0x404498, 1) -mmctx_data(0x404604, 4) -mmctx_data(0x404618, 32) -mmctx_data(0x404698, 21) -mmctx_data(0x4046f0, 2) -mmctx_data(0x404700, 22) -mmctx_data(0x405800, 1) -mmctx_data(0x405830, 3) -mmctx_data(0x405854, 1) -mmctx_data(0x405870, 4) -mmctx_data(0x405a00, 2) -mmctx_data(0x405a18, 1) -mmctx_data(0x406020, 1) -mmctx_data(0x406028, 4) -mmctx_data(0x4064a8, 2) -mmctx_data(0x4064b4, 5) -mmctx_data(0x407804, 1) -mmctx_data(0x40780c, 6) -mmctx_data(0x4078bc, 1) -mmctx_data(0x408000, 7) -mmctx_data(0x408064, 1) -mmctx_data(0x408800, 3) -mmctx_data(0x408900, 4) -mmctx_data(0x408980, 1) -nvd9_hub_mmio_tail: - .align 256 chan_data: chan_mmio_count: .b32 0 @@ -158,8 +113,8 @@ chan_mmio_address: .b32 0 .align 256 xfer_data: .b32 0 -.section #nvc0_grhub_code -bra #init +.section nvc0_grhub_code +bra init define(`include_code') include(`nvc0_graph.fuc') @@ -202,7 +157,7 @@ init: iowr I[$r1 + 0x000] $r2 // FIFO_ENABLE // setup i0 handler, and route all interrupts to it - mov $r1 #ih + mov $r1 ih mov $iv0 $r1 mov $r1 0x400 iowr I[$r1 + 0x300] $r0 // INTR_DISPATCH @@ -246,11 +201,11 @@ init: // fetch enabled GPC/ROP counts mov $r14 -0x69fc // 0x409604 sethi $r14 0x400000 - call #nv_rd32 + call nv_rd32 extr $r1 $r15 16:20 - st b32 D[$r0 + #rop_count] $r1 + st b32 D[$r0 + rop_count] $r1 and $r15 0x1f - st b32 D[$r0 + #gpc_count] $r15 + st b32 D[$r0 + gpc_count] $r15 // set BAR_REQMASK to GPC mask mov $r1 1 @@ -265,14 +220,14 @@ init: mov $r2 0x800 shl b32 $r2 6 iord $r2 I[$r2 + 0x000] // CC_SCRATCH[0] - mov $r15 #chipsets - 8 + mov $r15 chipsets - 8 init_find_chipset: add b32 $r15 8 ld b32 $r3 D[$r15 + 0x00] cmpu b32 $r3 $r2 - bra e #init_context + bra e init_context cmpu b32 $r3 0 - bra ne #init_find_chipset + bra ne init_find_chipset // unknown chipset ret @@ -284,9 +239,9 @@ init: ld b16 $r14 D[$r15 + 4] ld b16 $r15 D[$r15 + 6] sethi $r14 0 - st b32 D[$r0 + #hub_mmio_list_head] $r14 - st b32 D[$r0 + #hub_mmio_list_tail] $r15 - call #mmctx_size + st b32 D[$r0 + hub_mmio_list_head] $r14 + st b32 D[$r0 + hub_mmio_list_tail] $r15 + call mmctx_size // set mmctx base addresses now so we don't have to do it later, // they don't (currently) ever change @@ -305,7 +260,7 @@ init: add b32 $r1 1 shl b32 $r1 8 mov b32 $r15 $r1 - call #strand_ctx_init + call strand_ctx_init add b32 $r1 $r15 // initialise each GPC in sequence by passing in the offset of its @@ -316,40 +271,40 @@ init: // when it has completed, and return the size of its context data // in GPCn_CC_SCRATCH[1] // - ld b32 $r3 D[$r0 + #gpc_count] + ld b32 $r3 D[$r0 + gpc_count] mov $r4 0x2000 sethi $r4 0x500000 init_gpc: // setup, and start GPC ucode running add b32 $r14 $r4 0x804 mov b32 $r15 $r1 - call #nv_wr32 // CC_SCRATCH[1] = ctx offset + call nv_wr32 // CC_SCRATCH[1] = ctx offset add b32 $r14 $r4 0x800 mov b32 $r15 $r2 - call #nv_wr32 // CC_SCRATCH[0] = chipset + call nv_wr32 // CC_SCRATCH[0] = chipset add b32 $r14 $r4 0x10c clear b32 $r15 - call #nv_wr32 + call nv_wr32 add b32 $r14 $r4 0x104 - call #nv_wr32 // ENTRY + call nv_wr32 // ENTRY add b32 $r14 $r4 0x100 mov $r15 2 // CTRL_START_TRIGGER - call #nv_wr32 // CTRL + call nv_wr32 // CTRL // wait for it to complete, and adjust context size add b32 $r14 $r4 0x800 init_gpc_wait: - call #nv_rd32 + call nv_rd32 xbit $r15 $r15 31 - bra e #init_gpc_wait + bra e init_gpc_wait add b32 $r14 $r4 0x804 - call #nv_rd32 + call nv_rd32 add b32 $r1 $r15 // next! add b32 $r4 0x8000 sub b32 $r3 1 - bra ne #init_gpc + bra ne init_gpc // save context size, and tell host we're ready mov $r2 0x800 @@ -367,13 +322,13 @@ main: // sleep until we have something to do bset $flags $p0 sleep $p0 - mov $r13 #cmd_queue - call #queue_get - bra $p1 #main + mov $r13 cmd_queue + call queue_get + bra $p1 main // context switch, requested by GPU? cmpu b32 $r14 0x4001 - bra ne #main_not_ctx_switch + bra ne main_not_ctx_switch trace_set(T_AUTO) mov $r1 0xb00 shl b32 $r1 6 @@ -381,39 +336,39 @@ main: iord $r1 I[$r1 + 0x000] // CHAN_CUR xbit $r3 $r1 31 - bra e #chsw_no_prev + bra e chsw_no_prev xbit $r3 $r2 31 - bra e #chsw_prev_no_next + bra e chsw_prev_no_next push $r2 mov b32 $r2 $r1 trace_set(T_SAVE) bclr $flags $p1 bset $flags $p2 - call #ctx_xfer + call ctx_xfer trace_clr(T_SAVE); pop $r2 trace_set(T_LOAD); bset $flags $p1 - call #ctx_xfer + call ctx_xfer trace_clr(T_LOAD); - bra #chsw_done + bra chsw_done chsw_prev_no_next: push $r2 mov b32 $r2 $r1 bclr $flags $p1 bclr $flags $p2 - call #ctx_xfer + call ctx_xfer pop $r2 mov $r1 0xb00 shl b32 $r1 6 iowr I[$r1] $r2 - bra #chsw_done + bra chsw_done chsw_no_prev: xbit $r3 $r2 31 - bra e #chsw_done + bra e chsw_done bset $flags $p1 bclr $flags $p2 - call #ctx_xfer + call ctx_xfer // ack the context switch request chsw_done: @@ -422,32 +377,32 @@ main: mov $r2 1 iowr I[$r1 + 0x000] $r2 // 0x409b0c trace_clr(T_AUTO) - bra #main + bra main // request to set current channel? (*not* a context switch) main_not_ctx_switch: cmpu b32 $r14 0x0001 - bra ne #main_not_ctx_chan + bra ne main_not_ctx_chan mov b32 $r2 $r15 - call #ctx_chan - bra #main_done + call ctx_chan + bra main_done // request to store current channel context? main_not_ctx_chan: cmpu b32 $r14 0x0002 - bra ne #main_not_ctx_save + bra ne main_not_ctx_save trace_set(T_SAVE) bclr $flags $p1 bclr $flags $p2 - call #ctx_xfer + call ctx_xfer trace_clr(T_SAVE) - bra #main_done + bra main_done main_not_ctx_save: shl b32 $r15 $r14 16 or $r15 E_BAD_COMMAND - call #error - bra #main + call error + bra main main_done: mov $r1 0x820 @@ -455,7 +410,7 @@ main: clear b32 $r2 bset $r2 31 iowr I[$r1 + 0x000] $r2 // CC_SCRATCH[0] |= 0x80000000 - bra #main + bra main // interrupt handler ih: @@ -472,13 +427,13 @@ ih: // incoming fifo command? iord $r10 I[$r0 + 0x200] // INTR and $r11 $r10 0x00000004 - bra e #ih_no_fifo + bra e ih_no_fifo // queue incoming fifo command for later processing mov $r11 0x1900 - mov $r13 #cmd_queue + mov $r13 cmd_queue iord $r14 I[$r11 + 0x100] // FIFO_CMD iord $r15 I[$r11 + 0x000] // FIFO_DATA - call #queue_put + call queue_put add b32 $r11 0x400 mov $r14 1 iowr I[$r11 + 0x000] $r14 // FIFO_ACK @@ -486,18 +441,18 @@ ih: // context switch request? ih_no_fifo: and $r11 $r10 0x00000100 - bra e #ih_no_ctxsw + bra e ih_no_ctxsw // enqueue a context switch for later processing - mov $r13 #cmd_queue + mov $r13 cmd_queue mov $r14 0x4001 - call #queue_put + call queue_put // anything we didn't handle, bring it to the host's attention ih_no_ctxsw: mov $r11 0x104 not b32 $r11 and $r11 $r10 $r11 - bra e #ih_no_other + bra e ih_no_other mov $r10 0xc1c shl b32 $r10 6 iowr I[$r10] $r11 // INTR_UP_SET @@ -523,11 +478,11 @@ ctx_4160s: mov $r14 0x4160 sethi $r14 0x400000 mov $r15 1 - call #nv_wr32 + call nv_wr32 ctx_4160s_wait: - call #nv_rd32 + call nv_rd32 xbit $r15 $r15 4 - bra e #ctx_4160s_wait + bra e ctx_4160s_wait ret // Without clearing again at end of xfer, some things cause PGRAPH @@ -537,7 +492,7 @@ ctx_4160c: mov $r14 0x4160 sethi $r14 0x400000 clear b32 $r15 - call #nv_wr32 + call nv_wr32 ret // Again, not real sure @@ -548,7 +503,7 @@ ctx_4170s: mov $r14 0x4170 sethi $r14 0x400000 or $r15 0x10 - call #nv_wr32 + call nv_wr32 ret // Waits for a ctx_4170s() call to complete @@ -556,9 +511,9 @@ ctx_4170s: ctx_4170w: mov $r14 0x4170 sethi $r14 0x400000 - call #nv_rd32 + call nv_rd32 and $r15 0x10 - bra ne #ctx_4170w + bra ne ctx_4170w ret // Disables various things, waits a bit, and re-enables them.. @@ -575,7 +530,7 @@ ctx_redswitch: mov $r15 8 ctx_redswitch_delay: sub b32 $r15 1 - bra ne #ctx_redswitch_delay + bra ne ctx_redswitch_delay mov $r15 0x770 iowr I[$r14] $r15 // HUB_RED_SWITCH = ENABLE_ALL, POWER_ALL ret @@ -591,10 +546,10 @@ ctx_86c: iowr I[$r14] $r15 // HUB(0x86c) = val mov $r14 -0x75ec sethi $r14 0x400000 - call #nv_wr32 // ROP(0xa14) = val + call nv_wr32 // ROP(0xa14) = val mov $r14 -0x5794 sethi $r14 0x410000 - call #nv_wr32 // GPC(0x86c) = val + call nv_wr32 // GPC(0x86c) = val ret // ctx_load - load's a channel's ctxctl data, and selects its vm @@ -606,7 +561,7 @@ ctx_load: // switch to channel, somewhat magic in parts.. mov $r10 12 // DONE_UNK12 - call #wait_donez + call wait_donez mov $r1 0xa24 shl b32 $r1 6 iowr I[$r1 + 0x000] $r0 // 0x409a24 @@ -621,7 +576,7 @@ ctx_load: ctx_chan_wait_0: iord $r4 I[$r1 + 0x100] and $r4 0x1f - bra ne #ctx_chan_wait_0 + bra ne ctx_chan_wait_0 iowr I[$r3 + 0x000] $r2 // CHAN_CUR // load channel header, fetch PGRAPH context pointer @@ -640,19 +595,19 @@ ctx_load: sethi $r2 0x80000000 iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vram mov $r1 0x10 // chan + 0x0210 - mov $r2 #xfer_data + mov $r2 xfer_data sethi $r2 0x00020000 // 16 bytes xdld $r1 $r2 xdwait trace_clr(T_LCHAN) // update current context - ld b32 $r1 D[$r0 + #xfer_data + 4] + ld b32 $r1 D[$r0 + xfer_data + 4] shl b32 $r1 24 - ld b32 $r2 D[$r0 + #xfer_data + 0] + ld b32 $r2 D[$r0 + xfer_data + 0] shr b32 $r2 8 or $r1 $r2 - st b32 D[$r0 + #ctx_current] $r1 + st b32 D[$r0 + ctx_current] $r1 // set transfer base to start of context, and fetch context header trace_set(T_LCTXH) @@ -663,7 +618,7 @@ ctx_load: mov $r1 0xa20 shl b32 $r1 6 iowr I[$r1 + 0x000] $r2 // MEM_TARGET = vm - mov $r1 #chan_data + mov $r1 chan_data sethi $r1 0x00060000 // 256 bytes xdld $r0 $r1 xdwait @@ -680,10 +635,10 @@ ctx_load: // In: $r2 channel address // ctx_chan: - call #ctx_4160s - call #ctx_load + call ctx_4160s + call ctx_load mov $r10 12 // DONE_UNK12 - call #wait_donez + call wait_donez mov $r1 0xa10 shl b32 $r1 6 mov $r2 5 @@ -691,8 +646,8 @@ ctx_chan: ctx_chan_wait: iord $r2 I[$r1 + 0x000] or $r2 $r2 - bra ne #ctx_chan_wait - call #ctx_4160c + bra ne ctx_chan_wait + call ctx_4160c ret // Execute per-context state overrides list @@ -706,7 +661,7 @@ ctx_chan: // ctx_mmio_exec: // set transfer base to be the mmio list - ld b32 $r3 D[$r0 + #chan_mmio_address] + ld b32 $r3 D[$r0 + chan_mmio_address] mov $r2 0xa04 shl b32 $r2 6 iowr I[$r2 + 0x000] $r3 // MEM_BASE @@ -715,31 +670,31 @@ ctx_mmio_exec: ctx_mmio_loop: // fetch next 256 bytes of mmio list if necessary and $r4 $r3 0xff - bra ne #ctx_mmio_pull - mov $r5 #xfer_data + bra ne ctx_mmio_pull + mov $r5 xfer_data sethi $r5 0x00060000 // 256 bytes xdld $r3 $r5 xdwait // execute a single list entry ctx_mmio_pull: - ld b32 $r14 D[$r4 + #xfer_data + 0x00] - ld b32 $r15 D[$r4 + #xfer_data + 0x04] - call #nv_wr32 + ld b32 $r14 D[$r4 + xfer_data + 0x00] + ld b32 $r15 D[$r4 + xfer_data + 0x04] + call nv_wr32 // next! add b32 $r3 8 sub b32 $r1 1 - bra ne #ctx_mmio_loop + bra ne ctx_mmio_loop // set transfer base back to the current context ctx_mmio_done: - ld b32 $r3 D[$r0 + #ctx_current] + ld b32 $r3 D[$r0 + ctx_current] iowr I[$r2 + 0x000] $r3 // MEM_BASE // disable the mmio list now, we don't need/want to execute it again - st b32 D[$r0 + #chan_mmio_count] $r0 - mov $r1 #chan_data + st b32 D[$r0 + chan_mmio_count] $r0 + mov $r1 chan_data sethi $r1 0x00060000 // 256 bytes xdst $r0 $r1 xdwait @@ -754,46 +709,46 @@ ctx_mmio_exec: // on load it means: "a save preceeded this load" // ctx_xfer: - bra not $p1 #ctx_xfer_pre - bra $p2 #ctx_xfer_pre_load + bra not $p1 ctx_xfer_pre + bra $p2 ctx_xfer_pre_load ctx_xfer_pre: mov $r15 0x10 - call #ctx_86c - call #ctx_4160s - bra not $p1 #ctx_xfer_exec + call ctx_86c + call ctx_4160s + bra not $p1 ctx_xfer_exec ctx_xfer_pre_load: mov $r15 2 - call #ctx_4170s - call #ctx_4170w - call #ctx_redswitch + call ctx_4170s + call ctx_4170w + call ctx_redswitch clear b32 $r15 - call #ctx_4170s - call #ctx_load + call ctx_4170s + call ctx_load // fetch context pointer, and initiate xfer on all GPCs ctx_xfer_exec: - ld b32 $r1 D[$r0 + #ctx_current] + ld b32 $r1 D[$r0 + ctx_current] mov $r2 0x414 shl b32 $r2 6 iowr I[$r2 + 0x000] $r0 // BAR_STATUS = reset mov $r14 -0x5b00 sethi $r14 0x410000 mov b32 $r15 $r1 - call #nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer + call nv_wr32 // GPC_BCAST_WRCMD_DATA = ctx pointer add b32 $r14 4 xbit $r15 $flags $p1 xbit $r2 $flags $p2 shl b32 $r2 1 or $r15 $r2 - call #nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) + call nv_wr32 // GPC_BCAST_WRCMD_CMD = GPC_XFER(type) // strands mov $r1 0x4afc sethi $r1 0x20000 mov $r2 0xc iowr I[$r1] $r2 // STRAND_CMD(0x3f) = 0x0c - call #strand_wait + call strand_wait mov $r2 0x47fc sethi $r2 0x20000 iowr I[$r2] $r0 // STRAND_FIRST_GENE(0x3f) = 0x00 @@ -805,22 +760,22 @@ ctx_xfer: xbit $r10 $flags $p1 // direction or $r10 6 // first, last mov $r11 0 // base = 0 - ld b32 $r12 D[$r0 + #hub_mmio_list_head] - ld b32 $r13 D[$r0 + #hub_mmio_list_tail] + ld b32 $r12 D[$r0 + hub_mmio_list_head] + ld b32 $r13 D[$r0 + hub_mmio_list_tail] mov $r14 0 // not multi - call #mmctx_xfer + call mmctx_xfer // wait for GPCs to all complete mov $r10 8 // DONE_BAR - call #wait_doneo + call wait_doneo // wait for strand xfer to complete - call #strand_wait + call strand_wait // post-op - bra $p1 #ctx_xfer_post + bra $p1 ctx_xfer_post mov $r10 12 // DONE_UNK12 - call #wait_donez + call wait_donez mov $r1 0xa10 shl b32 $r1 6 mov $r2 5 @@ -828,27 +783,27 @@ ctx_xfer: ctx_xfer_post_save_wait: iord $r2 I[$r1] or $r2 $r2 - bra ne #ctx_xfer_post_save_wait + bra ne ctx_xfer_post_save_wait - bra $p2 #ctx_xfer_done + bra $p2 ctx_xfer_done ctx_xfer_post: mov $r15 2 - call #ctx_4170s + call ctx_4170s clear b32 $r15 - call #ctx_86c - call #strand_post - call #ctx_4170w + call ctx_86c + call strand_post + call ctx_4170w clear b32 $r15 - call #ctx_4170s + call ctx_4170s - bra not $p1 #ctx_xfer_no_post_mmio - ld b32 $r1 D[$r0 + #chan_mmio_count] + bra not $p1 ctx_xfer_no_post_mmio + ld b32 $r1 D[$r0 + chan_mmio_count] or $r1 $r1 - bra e #ctx_xfer_no_post_mmio - call #ctx_mmio_exec + bra e ctx_xfer_no_post_mmio + call ctx_mmio_exec ctx_xfer_no_post_mmio: - call #ctx_4160c + call ctx_4160c ctx_xfer_done: ret diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h b/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h index c5ed307abeb9..241d3263f1e5 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_grhub.fuc.h @@ -23,21 +23,19 @@ uint32_t nvc0_grhub_data[] = { 0x00000000, 0x00000000, 0x000000c0, - 0x013c00a0, + 0x01340098, 0x000000c1, - 0x014000a0, + 0x01380098, 0x000000c3, - 0x013c00a0, + 0x01340098, 0x000000c4, - 0x013c00a0, + 0x01340098, 0x000000c8, - 0x013c00a0, + 0x01340098, 0x000000ce, - 0x013c00a0, + 0x01340098, 0x000000cf, - 0x013c00a0, - 0x000000d9, - 0x01dc0140, + 0x01340098, 0x00000000, 0x0417e91c, 0x04400204, @@ -79,45 +77,47 @@ uint32_t nvc0_grhub_data[] = { 0x0c408900, 0x00408980, 0x044064c0, - 0x0417e91c, - 0x04400204, - 0x24404004, - 0x00404044, - 0x34404094, - 0x184040d0, - 0x004040f8, - 0x08404130, - 0x08404150, - 0x04404164, - 0x04404178, - 0x1c404200, - 0x34404404, - 0x0c404460, - 0x00404480, - 0x00404498, - 0x0c404604, - 0x7c404618, - 0x50404698, - 0x044046f0, - 0x54404700, - 0x00405800, - 0x08405830, - 0x00405854, - 0x0c405870, - 0x04405a00, - 0x00405a18, - 0x00406020, - 0x0c406028, - 0x044064a8, - 0x104064b4, - 0x00407804, - 0x1440780c, - 0x004078bc, - 0x18408000, - 0x00408064, - 0x08408800, - 0x0c408900, - 0x00408980, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, diff --git a/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c b/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c index e9992f62c1c0..929aded35cb5 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c +++ b/trunk/drivers/gpu/drm/nouveau/nvc0_pm.c @@ -153,240 +153,3 @@ nvc0_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) perflvl->vdec = read_clk(dev, 0x0e); return 0; } - -struct nvc0_pm_clock { - u32 freq; - u32 ssel; - u32 mdiv; - u32 dsrc; - u32 ddiv; - u32 coef; -}; - -struct nvc0_pm_state { - struct nvc0_pm_clock eng[16]; -}; - -static u32 -calc_div(struct drm_device *dev, int clk, u32 ref, u32 freq, u32 *ddiv) -{ - u32 div = min((ref * 2) / freq, (u32)65); - if (div < 2) - div = 2; - - *ddiv = div - 2; - return (ref * 2) / div; -} - -static u32 -calc_src(struct drm_device *dev, int clk, u32 freq, u32 *dsrc, u32 *ddiv) -{ - u32 sclk; - - /* use one of the fixed frequencies if possible */ - *ddiv = 0x00000000; - switch (freq) { - case 27000: - case 108000: - *dsrc = 0x00000000; - if (freq == 108000) - *dsrc |= 0x00030000; - return freq; - case 100000: - *dsrc = 0x00000002; - return freq; - default: - *dsrc = 0x00000003; - break; - } - - /* otherwise, calculate the closest divider */ - sclk = read_vco(dev, clk); - if (clk < 7) - sclk = calc_div(dev, clk, sclk, freq, ddiv); - return sclk; -} - -static u32 -calc_pll(struct drm_device *dev, int clk, u32 freq, u32 *coef) -{ - struct pll_lims limits; - int N, M, P, ret; - - ret = get_pll_limits(dev, 0x137000 + (clk * 0x20), &limits); - if (ret) - return 0; - - limits.refclk = read_div(dev, clk, 0x137120, 0x137140); - if (!limits.refclk) - return 0; - - ret = nva3_calc_pll(dev, &limits, freq, &N, NULL, &M, &P); - if (ret <= 0) - return 0; - - *coef = (P << 16) | (N << 8) | M; - return ret; -} - -/* A (likely rather simplified and incomplete) view of the clock tree - * - * Key: - * - * S: source select - * D: divider - * P: pll - * F: switch - * - * Engine clocks: - * - * 137250(D) ---- 137100(F0) ---- 137160(S)/1371d0(D) ------------------- ref - * (F1) ---- 1370X0(P) ---- 137120(S)/137140(D) ---- ref - * - * Not all registers exist for all clocks. For example: clocks >= 8 don't - * have their own PLL (all tied to clock 7's PLL when in PLL mode), nor do - * they have the divider at 1371d0, though the source selection at 137160 - * still exists. You must use the divider at 137250 for these instead. - * - * Memory clock: - * - * TBD, read_mem() above is likely very wrong... - * - */ - -static int -calc_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info, u32 freq) -{ - u32 src0, div0, div1D, div1P = 0; - u32 clk0, clk1 = 0; - - /* invalid clock domain */ - if (!freq) - return 0; - - /* first possible path, using only dividers */ - clk0 = calc_src(dev, clk, freq, &src0, &div0); - clk0 = calc_div(dev, clk, clk0, freq, &div1D); - - /* see if we can get any closer using PLLs */ - if (clk0 != freq) { - if (clk < 7) - clk1 = calc_pll(dev, clk, freq, &info->coef); - else - clk1 = read_pll(dev, 0x1370e0); - clk1 = calc_div(dev, clk, clk1, freq, &div1P); - } - - /* select the method which gets closest to target freq */ - if (abs((int)freq - clk0) <= abs((int)freq - clk1)) { - info->dsrc = src0; - if (div0) { - info->ddiv |= 0x80000000; - info->ddiv |= div0 << 8; - info->ddiv |= div0; - } - if (div1D) { - info->mdiv |= 0x80000000; - info->mdiv |= div1D; - } - info->ssel = 0; - info->freq = clk0; - } else { - if (div1P) { - info->mdiv |= 0x80000000; - info->mdiv |= div1P << 8; - } - info->ssel = (1 << clk); - info->freq = clk1; - } - - return 0; -} - -void * -nvc0_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) -{ - struct drm_nouveau_private *dev_priv = dev->dev_private; - struct nvc0_pm_state *info; - int ret; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return ERR_PTR(-ENOMEM); - - /* NFI why this is still in the performance table, the ROPCs appear - * to get their clock from clock 2 ("hub07", actually hub05 on this - * chip, but, anyway...) as well. nvatiming confirms hub05 and ROP - * are always the same freq with the binary driver even when the - * performance table says they should differ. - */ - if (dev_priv->chipset == 0xd9) - perflvl->rop = 0; - - if ((ret = calc_clk(dev, 0x00, &info->eng[0x00], perflvl->shader)) || - (ret = calc_clk(dev, 0x01, &info->eng[0x01], perflvl->rop)) || - (ret = calc_clk(dev, 0x02, &info->eng[0x02], perflvl->hub07)) || - (ret = calc_clk(dev, 0x07, &info->eng[0x07], perflvl->hub06)) || - (ret = calc_clk(dev, 0x08, &info->eng[0x08], perflvl->hub01)) || - (ret = calc_clk(dev, 0x09, &info->eng[0x09], perflvl->copy)) || - (ret = calc_clk(dev, 0x0c, &info->eng[0x0c], perflvl->daemon)) || - (ret = calc_clk(dev, 0x0e, &info->eng[0x0e], perflvl->vdec))) { - kfree(info); - return ERR_PTR(ret); - } - - return info; -} - -static void -prog_clk(struct drm_device *dev, int clk, struct nvc0_pm_clock *info) -{ - /* program dividers at 137160/1371d0 first */ - if (clk < 7 && !info->ssel) { - nv_mask(dev, 0x1371d0 + (clk * 0x04), 0x80003f3f, info->ddiv); - nv_wr32(dev, 0x137160 + (clk * 0x04), info->dsrc); - } - - /* switch clock to non-pll mode */ - nv_mask(dev, 0x137100, (1 << clk), 0x00000000); - nv_wait(dev, 0x137100, (1 << clk), 0x00000000); - - /* reprogram pll */ - if (clk < 7) { - /* make sure it's disabled first... */ - u32 base = 0x137000 + (clk * 0x20); - u32 ctrl = nv_rd32(dev, base + 0x00); - if (ctrl & 0x00000001) { - nv_mask(dev, base + 0x00, 0x00000004, 0x00000000); - nv_mask(dev, base + 0x00, 0x00000001, 0x00000000); - } - /* program it to new values, if necessary */ - if (info->ssel) { - nv_wr32(dev, base + 0x04, info->coef); - nv_mask(dev, base + 0x00, 0x00000001, 0x00000001); - nv_wait(dev, base + 0x00, 0x00020000, 0x00020000); - nv_mask(dev, base + 0x00, 0x00020004, 0x00000004); - } - } - - /* select pll/non-pll mode, and program final clock divider */ - nv_mask(dev, 0x137100, (1 << clk), info->ssel); - nv_wait(dev, 0x137100, (1 << clk), info->ssel); - nv_mask(dev, 0x137250 + (clk * 0x04), 0x00003f3f, info->mdiv); -} - -int -nvc0_pm_clocks_set(struct drm_device *dev, void *data) -{ - struct nvc0_pm_state *info = data; - int i; - - for (i = 0; i < 16; i++) { - if (!info->eng[i].freq) - continue; - prog_clk(dev, i, &info->eng[i]); - } - - kfree(info); - return 0; -} diff --git a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c index d2ba2f07400b..cb006a718e70 100644 --- a/trunk/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/trunk/drivers/gpu/drm/nouveau/nvd0_display.c @@ -35,34 +35,12 @@ #include "nouveau_fb.h" #include "nv50_display.h" -#define EVO_DMA_NR 9 - -#define EVO_MASTER (0x00) -#define EVO_FLIP(c) (0x01 + (c)) -#define EVO_OVLY(c) (0x05 + (c)) -#define EVO_OIMM(c) (0x09 + (c)) -#define EVO_CURS(c) (0x0d + (c)) - -/* offsets in shared sync bo of various structures */ -#define EVO_SYNC(c, o) ((c) * 0x0100 + (o)) -#define EVO_MAST_NTFY EVO_SYNC( 0, 0x00) -#define EVO_FLIP_SEM0(c) EVO_SYNC((c), 0x00) -#define EVO_FLIP_SEM1(c) EVO_SYNC((c), 0x10) - -struct evo { - int idx; - dma_addr_t handle; - u32 *ptr; - struct { - u32 offset; - u16 value; - } sem; -}; - struct nvd0_display { struct nouveau_gpuobj *mem; - struct nouveau_bo *sync; - struct evo evo[9]; + struct { + dma_addr_t handle; + u32 *ptr; + } evo[1]; struct tasklet_struct tasklet; u32 modeset; @@ -75,15 +53,6 @@ nvd0_display(struct drm_device *dev) return dev_priv->engine.display.priv; } -static struct drm_crtc * -nvd0_display_crtc_get(struct drm_encoder *encoder) -{ - return nouveau_encoder(encoder)->crtc; -} - -/****************************************************************************** - * EVO channel helpers - *****************************************************************************/ static inline int evo_icmd(struct drm_device *dev, int id, u32 mthd, u32 data) { @@ -115,9 +84,6 @@ evo_wait(struct drm_device *dev, int id, int nr) put = 0; } - if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) - NV_INFO(dev, "Evo%d: %p START\n", id, disp->evo[id].ptr + put); - return disp->evo[id].ptr + put; } @@ -125,264 +91,40 @@ static void evo_kick(u32 *push, struct drm_device *dev, int id) { struct nvd0_display *disp = nvd0_display(dev); - - if (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO) { - u32 curp = nv_rd32(dev, 0x640000 + (id * 0x1000)) >> 2; - u32 *cur = disp->evo[id].ptr + curp; - - while (cur < push) - NV_INFO(dev, "Evo%d: 0x%08x\n", id, *cur++); - NV_INFO(dev, "Evo%d: %p KICK!\n", id, push); - } - nv_wr32(dev, 0x640000 + (id * 0x1000), (push - disp->evo[id].ptr) << 2); } #define evo_mthd(p,m,s) *((p)++) = (((s) << 18) | (m)) #define evo_data(p,d) *((p)++) = (d) -static int -evo_init_dma(struct drm_device *dev, int ch) -{ - struct nvd0_display *disp = nvd0_display(dev); - u32 flags; - - flags = 0x00000000; - if (ch == EVO_MASTER) - flags |= 0x01000000; - - nv_wr32(dev, 0x610494 + (ch * 0x0010), (disp->evo[ch].handle >> 8) | 3); - nv_wr32(dev, 0x610498 + (ch * 0x0010), 0x00010000); - nv_wr32(dev, 0x61049c + (ch * 0x0010), 0x00000001); - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); - nv_wr32(dev, 0x640000 + (ch * 0x1000), 0x00000000); - nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000013 | flags); - if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000)) { - NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, - nv_rd32(dev, 0x610490 + (ch * 0x0010))); - return -EBUSY; - } - - nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); - nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); - return 0; -} - -static void -evo_fini_dma(struct drm_device *dev, int ch) -{ - if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000010)) - return; - - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000000); - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000003, 0x00000000); - nv_wait(dev, 0x610490 + (ch * 0x0010), 0x80000000, 0x00000000); - nv_mask(dev, 0x610090, (1 << ch), 0x00000000); - nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); -} - -static inline void -evo_piow(struct drm_device *dev, int ch, u16 mthd, u32 data) -{ - nv_wr32(dev, 0x640000 + (ch * 0x1000) + mthd, data); -} - -static int -evo_init_pio(struct drm_device *dev, int ch) -{ - nv_wr32(dev, 0x610490 + (ch * 0x0010), 0x00000001); - if (!nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00010000)) { - NV_ERROR(dev, "PDISP: ch%d 0x%08x\n", ch, - nv_rd32(dev, 0x610490 + (ch * 0x0010))); - return -EBUSY; - } - - nv_mask(dev, 0x610090, (1 << ch), (1 << ch)); - nv_mask(dev, 0x6100a0, (1 << ch), (1 << ch)); - return 0; -} - -static void -evo_fini_pio(struct drm_device *dev, int ch) -{ - if (!(nv_rd32(dev, 0x610490 + (ch * 0x0010)) & 0x00000001)) - return; - - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000010, 0x00000010); - nv_mask(dev, 0x610490 + (ch * 0x0010), 0x00000001, 0x00000000); - nv_wait(dev, 0x610490 + (ch * 0x0010), 0x00010000, 0x00000000); - nv_mask(dev, 0x610090, (1 << ch), 0x00000000); - nv_mask(dev, 0x6100a0, (1 << ch), 0x00000000); -} - -static bool -evo_sync_wait(void *data) -{ - return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; -} - -static int -evo_sync(struct drm_device *dev, int ch) -{ - struct nvd0_display *disp = nvd0_display(dev); - u32 *push = evo_wait(dev, ch, 8); - if (push) { - nouveau_bo_wr32(disp->sync, EVO_MAST_NTFY, 0x00000000); - evo_mthd(push, 0x0084, 1); - evo_data(push, 0x80000000 | EVO_MAST_NTFY); - evo_mthd(push, 0x0080, 2); - evo_data(push, 0x00000000); - evo_data(push, 0x00000000); - evo_kick(push, dev, ch); - if (nv_wait_cb(dev, evo_sync_wait, disp->sync)) - return 0; - } - - return -EBUSY; -} - -/****************************************************************************** - * Page flipping channel - *****************************************************************************/ -struct nouveau_bo * -nvd0_display_crtc_sema(struct drm_device *dev, int crtc) -{ - return nvd0_display(dev)->sync; -} - -void -nvd0_display_flip_stop(struct drm_crtc *crtc) -{ - struct nvd0_display *disp = nvd0_display(crtc->dev); - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct evo *evo = &disp->evo[EVO_FLIP(nv_crtc->index)]; - u32 *push; - - push = evo_wait(crtc->dev, evo->idx, 8); - if (push) { - evo_mthd(push, 0x0084, 1); - evo_data(push, 0x00000000); - evo_mthd(push, 0x0094, 1); - evo_data(push, 0x00000000); - evo_mthd(push, 0x00c0, 1); - evo_data(push, 0x00000000); - evo_mthd(push, 0x0080, 1); - evo_data(push, 0x00000000); - evo_kick(push, crtc->dev, evo->idx); - } -} - -int -nvd0_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, - struct nouveau_channel *chan, u32 swap_interval) +static struct drm_crtc * +nvd0_display_crtc_get(struct drm_encoder *encoder) { - struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); - struct nvd0_display *disp = nvd0_display(crtc->dev); - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - struct evo *evo = &disp->evo[EVO_FLIP(nv_crtc->index)]; - u64 offset; - u32 *push; - int ret; - - swap_interval <<= 4; - if (swap_interval == 0) - swap_interval |= 0x100; - - push = evo_wait(crtc->dev, evo->idx, 128); - if (unlikely(push == NULL)) - return -EBUSY; - - /* synchronise with the rendering channel, if necessary */ - if (likely(chan)) { - ret = RING_SPACE(chan, 10); - if (ret) - return ret; - - offset = chan->dispc_vma[nv_crtc->index].offset; - offset += evo->sem.offset; - - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset)); - OUT_RING (chan, 0xf00d0000 | evo->sem.value); - OUT_RING (chan, 0x1002); - BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4); - OUT_RING (chan, upper_32_bits(offset)); - OUT_RING (chan, lower_32_bits(offset ^ 0x10)); - OUT_RING (chan, 0x74b1e000); - OUT_RING (chan, 0x1001); - FIRE_RING (chan); - } else { - nouveau_bo_wr32(disp->sync, evo->sem.offset / 4, - 0xf00d0000 | evo->sem.value); - evo_sync(crtc->dev, EVO_MASTER); - } - - /* queue the flip */ - evo_mthd(push, 0x0100, 1); - evo_data(push, 0xfffe0000); - evo_mthd(push, 0x0084, 1); - evo_data(push, swap_interval); - if (!(swap_interval & 0x00000100)) { - evo_mthd(push, 0x00e0, 1); - evo_data(push, 0x40000000); - } - evo_mthd(push, 0x0088, 4); - evo_data(push, evo->sem.offset); - evo_data(push, 0xf00d0000 | evo->sem.value); - evo_data(push, 0x74b1e000); - evo_data(push, NvEvoSync); - evo_mthd(push, 0x00a0, 2); - evo_data(push, 0x00000000); - evo_data(push, 0x00000000); - evo_mthd(push, 0x00c0, 1); - evo_data(push, nv_fb->r_dma); - evo_mthd(push, 0x0110, 2); - evo_data(push, 0x00000000); - evo_data(push, 0x00000000); - evo_mthd(push, 0x0400, 5); - evo_data(push, nv_fb->nvbo->bo.offset >> 8); - evo_data(push, 0); - evo_data(push, (fb->height << 16) | fb->width); - evo_data(push, nv_fb->r_pitch); - evo_data(push, nv_fb->r_format); - evo_mthd(push, 0x0080, 1); - evo_data(push, 0x00000000); - evo_kick(push, crtc->dev, evo->idx); - - evo->sem.offset ^= 0x10; - evo->sem.value++; - return 0; + return nouveau_encoder(encoder)->crtc; } /****************************************************************************** * CRTC *****************************************************************************/ static int -nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) +nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update) { struct drm_device *dev = nv_crtc->base.dev; - struct nouveau_connector *nv_connector; - struct drm_connector *connector; - u32 *push, mode = 0x00; + u32 *push, mode; - nv_connector = nouveau_crtc_connector_get(nv_crtc); - connector = &nv_connector->base; - if (nv_connector->dithering_mode == DITHERING_MODE_AUTO) { - if (nv_crtc->base.fb->depth > connector->display_info.bpc * 3) - mode = DITHERING_MODE_DYNAMIC2X2; - } else { - mode = nv_connector->dithering_mode; - } - - if (nv_connector->dithering_depth == DITHERING_DEPTH_AUTO) { - if (connector->display_info.bpc >= 8) - mode |= DITHERING_DEPTH_8BPC; - } else { - mode |= nv_connector->dithering_depth; + mode = 0x00000000; + if (on) { + /* 0x11: 6bpc dynamic 2x2 + * 0x13: 8bpc dynamic 2x2 + * 0x19: 6bpc static 2x2 + * 0x1b: 8bpc static 2x2 + * 0x21: 6bpc temporal + * 0x23: 8bpc temporal + */ + mode = 0x00000011; } - push = evo_wait(dev, EVO_MASTER, 4); + push = evo_wait(dev, 0, 4); if (push) { evo_mthd(push, 0x0490 + (nv_crtc->index * 0x300), 1); evo_data(push, mode); @@ -390,98 +132,63 @@ nvd0_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool update) evo_mthd(push, 0x0080, 1); evo_data(push, 0x00000000); } - evo_kick(push, dev, EVO_MASTER); + evo_kick(push, dev, 0); } return 0; } static int -nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, bool update) +nvd0_crtc_set_scale(struct nouveau_crtc *nv_crtc, int type, bool update) { - struct drm_display_mode *omode, *umode = &nv_crtc->base.mode; + struct drm_display_mode *mode = &nv_crtc->base.mode; struct drm_device *dev = nv_crtc->base.dev; - struct drm_crtc *crtc = &nv_crtc->base; struct nouveau_connector *nv_connector; - int mode = DRM_MODE_SCALE_NONE; - u32 oX, oY, *push; + u32 *push, outX, outY; - /* start off at the resolution we programmed the crtc for, this - * effectively handles NONE/FULL scaling - */ - nv_connector = nouveau_crtc_connector_get(nv_crtc); - if (nv_connector && nv_connector->native_mode) - mode = nv_connector->scaling_mode; - - if (mode != DRM_MODE_SCALE_NONE) - omode = nv_connector->native_mode; - else - omode = umode; - - oX = omode->hdisplay; - oY = omode->vdisplay; - if (omode->flags & DRM_MODE_FLAG_DBLSCAN) - oY *= 2; - - /* add overscan compensation if necessary, will keep the aspect - * ratio the same as the backend mode unless overridden by the - * user setting both hborder and vborder properties. - */ - if (nv_connector && ( nv_connector->underscan == UNDERSCAN_ON || - (nv_connector->underscan == UNDERSCAN_AUTO && - nv_connector->edid && - drm_detect_hdmi_monitor(nv_connector->edid)))) { - u32 bX = nv_connector->underscan_hborder; - u32 bY = nv_connector->underscan_vborder; - u32 aspect = (oY << 19) / oX; - - if (bX) { - oX -= (bX * 2); - if (bY) oY -= (bY * 2); - else oY = ((oX * aspect) + (aspect / 2)) >> 19; - } else { - oX -= (oX >> 4) + 32; - if (bY) oY -= (bY * 2); - else oY = ((oX * aspect) + (aspect / 2)) >> 19; - } - } + outX = mode->hdisplay; + outY = mode->vdisplay; - /* handle CENTER/ASPECT scaling, taking into account the areas - * removed already for overscan compensation - */ - switch (mode) { - case DRM_MODE_SCALE_CENTER: - oX = min((u32)umode->hdisplay, oX); - oY = min((u32)umode->vdisplay, oY); - /* fall-through */ - case DRM_MODE_SCALE_ASPECT: - if (oY < oX) { - u32 aspect = (umode->hdisplay << 19) / umode->vdisplay; - oX = ((oY * aspect) + (aspect / 2)) >> 19; - } else { - u32 aspect = (umode->vdisplay << 19) / umode->hdisplay; - oY = ((oX * aspect) + (aspect / 2)) >> 19; + nv_connector = nouveau_crtc_connector_get(nv_crtc); + if (nv_connector && nv_connector->native_mode) { + struct drm_display_mode *native = nv_connector->native_mode; + u32 xratio = (native->hdisplay << 19) / mode->hdisplay; + u32 yratio = (native->vdisplay << 19) / mode->vdisplay; + + switch (type) { + case DRM_MODE_SCALE_ASPECT: + if (xratio > yratio) { + outX = (mode->hdisplay * yratio) >> 19; + outY = (mode->vdisplay * yratio) >> 19; + } else { + outX = (mode->hdisplay * xratio) >> 19; + outY = (mode->vdisplay * xratio) >> 19; + } + break; + case DRM_MODE_SCALE_FULLSCREEN: + outX = native->hdisplay; + outY = native->vdisplay; + break; + default: + break; } - break; - default: - break; } - push = evo_wait(dev, EVO_MASTER, 8); + push = evo_wait(dev, 0, 16); if (push) { evo_mthd(push, 0x04c0 + (nv_crtc->index * 0x300), 3); - evo_data(push, (oY << 16) | oX); - evo_data(push, (oY << 16) | oX); - evo_data(push, (oY << 16) | oX); + evo_data(push, (outY << 16) | outX); + evo_data(push, (outY << 16) | outX); + evo_data(push, (outY << 16) | outX); evo_mthd(push, 0x0494 + (nv_crtc->index * 0x300), 1); evo_data(push, 0x00000000); evo_mthd(push, 0x04b8 + (nv_crtc->index * 0x300), 1); - evo_data(push, (umode->vdisplay << 16) | umode->hdisplay); - evo_kick(push, dev, EVO_MASTER); + evo_data(push, (mode->vdisplay << 16) | mode->hdisplay); if (update) { - nvd0_display_flip_stop(crtc); - nvd0_display_flip_next(crtc, crtc->fb, NULL, 1); + evo_mthd(push, 0x0080, 1); + evo_data(push, 0x00000000); } + evo_kick(push, dev, 0); } return 0; @@ -494,7 +201,7 @@ nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, struct nouveau_framebuffer *nvfb = nouveau_framebuffer(fb); u32 *push; - push = evo_wait(fb->dev, EVO_MASTER, 16); + push = evo_wait(fb->dev, 0, 16); if (push) { evo_mthd(push, 0x0460 + (nv_crtc->index * 0x300), 1); evo_data(push, nvfb->nvbo->bo.offset >> 8); @@ -509,7 +216,7 @@ nvd0_crtc_set_image(struct nouveau_crtc *nv_crtc, struct drm_framebuffer *fb, evo_mthd(push, 0x0080, 1); evo_data(push, 0x00000000); } - evo_kick(push, fb->dev, EVO_MASTER); + evo_kick(push, fb->dev, 0); } nv_crtc->fb.tile_flags = nvfb->r_dma; @@ -520,7 +227,7 @@ static void nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) { struct drm_device *dev = nv_crtc->base.dev; - u32 *push = evo_wait(dev, EVO_MASTER, 16); + u32 *push = evo_wait(dev, 0, 16); if (push) { if (show) { evo_mthd(push, 0x0480 + (nv_crtc->index * 0x300), 2); @@ -540,7 +247,7 @@ nvd0_crtc_cursor_show(struct nouveau_crtc *nv_crtc, bool show, bool update) evo_data(push, 0x00000000); } - evo_kick(push, dev, EVO_MASTER); + evo_kick(push, dev, 0); } } @@ -555,9 +262,7 @@ nvd0_crtc_prepare(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); u32 *push; - nvd0_display_flip_stop(crtc); - - push = evo_wait(crtc->dev, EVO_MASTER, 2); + push = evo_wait(crtc->dev, 0, 2); if (push) { evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); evo_data(push, 0x00000000); @@ -565,7 +270,7 @@ nvd0_crtc_prepare(struct drm_crtc *crtc) evo_data(push, 0x03000000); evo_mthd(push, 0x045c + (nv_crtc->index * 0x300), 1); evo_data(push, 0x00000000); - evo_kick(push, crtc->dev, EVO_MASTER); + evo_kick(push, crtc->dev, 0); } nvd0_crtc_cursor_show(nv_crtc, false, false); @@ -577,7 +282,7 @@ nvd0_crtc_commit(struct drm_crtc *crtc) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); u32 *push; - push = evo_wait(crtc->dev, EVO_MASTER, 32); + push = evo_wait(crtc->dev, 0, 32); if (push) { evo_mthd(push, 0x0474 + (nv_crtc->index * 0x300), 1); evo_data(push, nv_crtc->fb.tile_flags); @@ -590,11 +295,10 @@ nvd0_crtc_commit(struct drm_crtc *crtc) evo_data(push, NvEvoVRAM); evo_mthd(push, 0x0430 + (nv_crtc->index * 0x300), 1); evo_data(push, 0xffffff00); - evo_kick(push, crtc->dev, EVO_MASTER); + evo_kick(push, crtc->dev, 0); } - nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, false); - nvd0_display_flip_next(crtc, crtc->fb, NULL, 1); + nvd0_crtc_cursor_show(nv_crtc, nv_crtc->cursor.visible, true); } static bool @@ -629,35 +333,21 @@ nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_connector *nv_connector; - u32 ilace = (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 2 : 1; - u32 vscan = (mode->flags & DRM_MODE_FLAG_DBLSCAN) ? 2 : 1; - u32 hactive, hsynce, hbackp, hfrontp, hblanke, hblanks; - u32 vactive, vsynce, vbackp, vfrontp, vblanke, vblanks; - u32 vblan2e = 0, vblan2s = 1; - u32 magic = 0x31ec6000; + u32 htotal = mode->htotal; + u32 vtotal = mode->vtotal; + u32 hsyncw = mode->hsync_end - mode->hsync_start - 1; + u32 vsyncw = mode->vsync_end - mode->vsync_start - 1; + u32 hfrntp = mode->hsync_start - mode->hdisplay; + u32 vfrntp = mode->vsync_start - mode->vdisplay; + u32 hbackp = mode->htotal - mode->hsync_end; + u32 vbackp = mode->vtotal - mode->vsync_end; + u32 hss2be = hsyncw + hbackp; + u32 vss2be = vsyncw + vbackp; + u32 hss2de = htotal - hfrntp; + u32 vss2de = vtotal - vfrntp; u32 syncs, *push; int ret; - hactive = mode->htotal; - hsynce = mode->hsync_end - mode->hsync_start - 1; - hbackp = mode->htotal - mode->hsync_end; - hblanke = hsynce + hbackp; - hfrontp = mode->hsync_start - mode->hdisplay; - hblanks = mode->htotal - hfrontp - 1; - - vactive = mode->vtotal * vscan / ilace; - vsynce = ((mode->vsync_end - mode->vsync_start) * vscan / ilace) - 1; - vbackp = (mode->vtotal - mode->vsync_end) * vscan / ilace; - vblanke = vsynce + vbackp; - vfrontp = (mode->vsync_start - mode->vdisplay) * vscan / ilace; - vblanks = vactive - vfrontp - 1; - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - vblan2e = vactive + vsynce + vbackp; - vblan2s = vblan2e + (mode->vdisplay * vscan / ilace); - vactive = (vactive * 2) + 1; - magic |= 0x00000001; - } - syncs = 0x00000001; if (mode->flags & DRM_MODE_FLAG_NHSYNC) syncs |= 0x00000008; @@ -668,33 +358,28 @@ nvd0_crtc_mode_set(struct drm_crtc *crtc, struct drm_display_mode *umode, if (ret) return ret; - push = evo_wait(crtc->dev, EVO_MASTER, 64); + push = evo_wait(crtc->dev, 0, 64); if (push) { - evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 6); + evo_mthd(push, 0x0410 + (nv_crtc->index * 0x300), 5); evo_data(push, 0x00000000); - evo_data(push, (vactive << 16) | hactive); - evo_data(push, ( vsynce << 16) | hsynce); - evo_data(push, (vblanke << 16) | hblanke); - evo_data(push, (vblanks << 16) | hblanks); - evo_data(push, (vblan2e << 16) | vblan2s); + evo_data(push, (vtotal << 16) | htotal); + evo_data(push, (vsyncw << 16) | hsyncw); + evo_data(push, (vss2be << 16) | hss2be); + evo_data(push, (vss2de << 16) | hss2de); evo_mthd(push, 0x042c + (nv_crtc->index * 0x300), 1); evo_data(push, 0x00000000); /* ??? */ evo_mthd(push, 0x0450 + (nv_crtc->index * 0x300), 3); evo_data(push, mode->clock * 1000); evo_data(push, 0x00200000); /* ??? */ evo_data(push, mode->clock * 1000); - evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); + evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 1); evo_data(push, syncs); - evo_data(push, magic); - evo_mthd(push, 0x04d0 + (nv_crtc->index * 0x300), 2); - evo_data(push, 0x00000311); - evo_data(push, 0x00000100); - evo_kick(push, crtc->dev, EVO_MASTER); + evo_kick(push, crtc->dev, 0); } nv_connector = nouveau_crtc_connector_get(nv_crtc); - nvd0_crtc_set_dither(nv_crtc, false); - nvd0_crtc_set_scale(nv_crtc, false); + nvd0_crtc_set_dither(nv_crtc, nv_connector->use_dithering, false); + nvd0_crtc_set_scale(nv_crtc, nv_connector->scaling_mode, false); nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, false); return 0; } @@ -715,9 +400,7 @@ nvd0_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, if (ret) return ret; - nvd0_display_flip_stop(crtc); nvd0_crtc_set_image(nv_crtc, crtc->fb, x, y, true); - nvd0_display_flip_next(crtc, crtc->fb, NULL, 1); return 0; } @@ -727,7 +410,6 @@ nvd0_crtc_mode_set_base_atomic(struct drm_crtc *crtc, enum mode_set_atomic state) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - nvd0_display_flip_stop(crtc); nvd0_crtc_set_image(nv_crtc, fb, x, y, true); return 0; } @@ -790,10 +472,10 @@ static int nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - int ch = EVO_CURS(nv_crtc->index); + const u32 data = (y << 16) | x; - evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); - evo_piow(crtc->dev, ch, 0x0080, 0x00000000); + nv_wr32(crtc->dev, 0x64d084 + (nv_crtc->index * 0x1000), data); + nv_wr32(crtc->dev, 0x64d080 + (nv_crtc->index * 0x1000), 0x00000000); return 0; } @@ -843,7 +525,6 @@ static const struct drm_crtc_funcs nvd0_crtc_func = { .gamma_set = nvd0_crtc_gamma_set, .set_config = drm_crtc_helper_set_config, .destroy = nvd0_crtc_destroy, - .page_flip = nouveau_crtc_page_flip, }; static void @@ -978,12 +659,12 @@ nvd0_dac_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, nvd0_dac_dpms(encoder, DRM_MODE_DPMS_ON); - push = evo_wait(encoder->dev, EVO_MASTER, 4); + push = evo_wait(encoder->dev, 0, 4); if (push) { evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 2); evo_data(push, 1 << nv_crtc->index); evo_data(push, 0x00ff); - evo_kick(push, encoder->dev, EVO_MASTER); + evo_kick(push, encoder->dev, 0); } nv_encoder->crtc = encoder->crtc; @@ -999,13 +680,13 @@ nvd0_dac_disconnect(struct drm_encoder *encoder) if (nv_encoder->crtc) { nvd0_crtc_prepare(nv_encoder->crtc); - push = evo_wait(dev, EVO_MASTER, 4); + push = evo_wait(dev, 0, 4); if (push) { evo_mthd(push, 0x0180 + (nv_encoder->or * 0x20), 1); evo_data(push, 0x00000000); evo_mthd(push, 0x0080, 1); evo_data(push, 0x00000000); - evo_kick(push, dev, EVO_MASTER); + evo_kick(push, dev, 0); } nv_encoder->crtc = NULL; @@ -1078,108 +759,6 @@ nvd0_dac_create(struct drm_connector *connector, struct dcb_entry *dcbe) return 0; } -/****************************************************************************** - * Audio - *****************************************************************************/ -static void -nvd0_audio_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_connector *nv_connector; - struct drm_device *dev = encoder->dev; - int i, or = nv_encoder->or * 0x30; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (!drm_detect_monitor_audio(nv_connector->edid)) - return; - - nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000001); - - drm_edid_to_eld(&nv_connector->base, nv_connector->edid); - if (nv_connector->base.eld[0]) { - u8 *eld = nv_connector->base.eld; - - for (i = 0; i < eld[2] * 4; i++) - nv_wr32(dev, 0x10ec00 + or, (i << 8) | eld[i]); - for (i = eld[2] * 4; i < 0x60; i++) - nv_wr32(dev, 0x10ec00 + or, (i << 8) | 0x00); - - nv_mask(dev, 0x10ec10 + or, 0x80000002, 0x80000002); - } -} - -static void -nvd0_audio_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct drm_device *dev = encoder->dev; - int or = nv_encoder->or * 0x30; - - nv_mask(dev, 0x10ec10 + or, 0x80000003, 0x80000000); -} - -/****************************************************************************** - * HDMI - *****************************************************************************/ -static void -nvd0_hdmi_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); - struct nouveau_connector *nv_connector; - struct drm_device *dev = encoder->dev; - int head = nv_crtc->index * 0x800; - u32 rekey = 56; /* binary driver, and tegra constant */ - u32 max_ac_packet; - - nv_connector = nouveau_encoder_connector_get(nv_encoder); - if (!drm_detect_hdmi_monitor(nv_connector->edid)) - return; - - max_ac_packet = mode->htotal - mode->hdisplay; - max_ac_packet -= rekey; - max_ac_packet -= 18; /* constant from tegra */ - max_ac_packet /= 32; - - /* AVI InfoFrame */ - nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); - nv_wr32(dev, 0x61671c + head, 0x000d0282); - nv_wr32(dev, 0x616720 + head, 0x0000006f); - nv_wr32(dev, 0x616724 + head, 0x00000000); - nv_wr32(dev, 0x616728 + head, 0x00000000); - nv_wr32(dev, 0x61672c + head, 0x00000000); - nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000001); - - /* ??? InfoFrame? */ - nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); - nv_wr32(dev, 0x6167ac + head, 0x00000010); - nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000001); - - /* HDMI_CTRL */ - nv_mask(dev, 0x616798 + head, 0x401f007f, 0x40000000 | rekey | - max_ac_packet << 16); - - /* NFI, audio doesn't work without it though.. */ - nv_mask(dev, 0x616548 + head, 0x00000070, 0x00000000); - - nvd0_audio_mode_set(encoder, mode); -} - -static void -nvd0_hdmi_disconnect(struct drm_encoder *encoder) -{ - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); - struct drm_device *dev = encoder->dev; - int head = nv_crtc->index * 0x800; - - nvd0_audio_disconnect(encoder); - - nv_mask(dev, 0x616798 + head, 0x40000000, 0x00000000); - nv_mask(dev, 0x6167a4 + head, 0x00000001, 0x00000000); - nv_mask(dev, 0x616714 + head, 0x00000001, 0x00000000); -} - /****************************************************************************** * SOR *****************************************************************************/ @@ -1250,8 +829,7 @@ static void nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, struct drm_display_mode *mode) { - struct drm_device *dev = encoder->dev; - struct drm_nouveau_private *dev_priv = dev->dev_private; + struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); struct nouveau_connector *nv_connector; @@ -1274,8 +852,6 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, or_config = (mode_ctrl & 0x00000f00) >> 8; if (mode->clock >= 165000) or_config |= 0x0100; - - nvd0_hdmi_mode_set(encoder, mode); break; case OUTPUT_LVDS: or_config = (mode_ctrl & 0x00000f00) >> 8; @@ -1285,7 +861,7 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, if (bios->fp.if_is_24bit) or_config |= 0x0200; } else { - if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) { + if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS_SPWG) { if (((u8 *)nv_connector->edid)[121] == 2) or_config |= 0x0100; } else @@ -1313,12 +889,12 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode, nvd0_sor_dpms(encoder, DRM_MODE_DPMS_ON); - push = evo_wait(dev, EVO_MASTER, 4); + push = evo_wait(encoder->dev, 0, 4); if (push) { evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 2); evo_data(push, mode_ctrl); evo_data(push, or_config); - evo_kick(push, dev, EVO_MASTER); + evo_kick(push, encoder->dev, 0); } nv_encoder->crtc = encoder->crtc; @@ -1334,17 +910,15 @@ nvd0_sor_disconnect(struct drm_encoder *encoder) if (nv_encoder->crtc) { nvd0_crtc_prepare(nv_encoder->crtc); - push = evo_wait(dev, EVO_MASTER, 4); + push = evo_wait(dev, 0, 4); if (push) { evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); evo_data(push, 0x00000000); evo_mthd(push, 0x0080, 1); evo_data(push, 0x00000000); - evo_kick(push, dev, EVO_MASTER); + evo_kick(push, dev, 0); } - nvd0_hdmi_disconnect(encoder); - nv_encoder->crtc = NULL; nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; } @@ -1585,12 +1159,6 @@ nvd0_display_intr(struct drm_device *dev) struct nvd0_display *disp = nvd0_display(dev); u32 intr = nv_rd32(dev, 0x610088); - if (intr & 0x00000001) { - u32 stat = nv_rd32(dev, 0x61008c); - nv_wr32(dev, 0x61008c, stat); - intr &= ~0x00000001; - } - if (intr & 0x00000002) { u32 stat = nv_rd32(dev, 0x61009c); int chid = ffs(stat) - 1; @@ -1647,29 +1215,38 @@ nvd0_display_intr(struct drm_device *dev) /****************************************************************************** * Init *****************************************************************************/ -void +static void nvd0_display_fini(struct drm_device *dev) { int i; - /* fini cursors + overlays + flips */ - for (i = 1; i >= 0; i--) { - evo_fini_pio(dev, EVO_CURS(i)); - evo_fini_pio(dev, EVO_OIMM(i)); - evo_fini_dma(dev, EVO_OVLY(i)); - evo_fini_dma(dev, EVO_FLIP(i)); + /* fini cursors */ + for (i = 14; i >= 13; i--) { + if (!(nv_rd32(dev, 0x610490 + (i * 0x10)) & 0x00000001)) + continue; + + nv_mask(dev, 0x610490 + (i * 0x10), 0x00000001, 0x00000000); + nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00000000); + nv_mask(dev, 0x610090, 1 << i, 0x00000000); + nv_mask(dev, 0x6100a0, 1 << i, 0x00000000); } /* fini master */ - evo_fini_dma(dev, EVO_MASTER); + if (nv_rd32(dev, 0x610490) & 0x00000010) { + nv_mask(dev, 0x610490, 0x00000010, 0x00000000); + nv_mask(dev, 0x610490, 0x00000003, 0x00000000); + nv_wait(dev, 0x610490, 0x80000000, 0x00000000); + nv_mask(dev, 0x610090, 0x00000001, 0x00000000); + nv_mask(dev, 0x6100a0, 0x00000001, 0x00000000); + } } int nvd0_display_init(struct drm_device *dev) { struct nvd0_display *disp = nvd0_display(dev); - int ret, i; u32 *push; + int i; if (nv_rd32(dev, 0x6100ac) & 0x00000100) { nv_wr32(dev, 0x6100ac, 0x00000100); @@ -1694,7 +1271,7 @@ nvd0_display_init(struct drm_device *dev) nv_wr32(dev, 0x6301c4 + (i * 0x800), sor); } - for (i = 0; i < dev->mode_config.num_crtc; i++) { + for (i = 0; i < 2; i++) { u32 crtc0 = nv_rd32(dev, 0x616104 + (i * 0x800)); u32 crtc1 = nv_rd32(dev, 0x616108 + (i * 0x800)); u32 crtc2 = nv_rd32(dev, 0x61610c + (i * 0x800)); @@ -1708,24 +1285,36 @@ nvd0_display_init(struct drm_device *dev) nv_mask(dev, 0x6100b0, 0x00000307, 0x00000307); /* init master */ - ret = evo_init_dma(dev, EVO_MASTER); - if (ret) - goto error; - - /* init flips + overlays + cursors */ - for (i = 0; i < dev->mode_config.num_crtc; i++) { - if ((ret = evo_init_dma(dev, EVO_FLIP(i))) || - (ret = evo_init_dma(dev, EVO_OVLY(i))) || - (ret = evo_init_pio(dev, EVO_OIMM(i))) || - (ret = evo_init_pio(dev, EVO_CURS(i)))) - goto error; + nv_wr32(dev, 0x610494, (disp->evo[0].handle >> 8) | 3); + nv_wr32(dev, 0x610498, 0x00010000); + nv_wr32(dev, 0x61049c, 0x00000001); + nv_mask(dev, 0x610490, 0x00000010, 0x00000010); + nv_wr32(dev, 0x640000, 0x00000000); + nv_wr32(dev, 0x610490, 0x01000013); + if (!nv_wait(dev, 0x610490, 0x80000000, 0x00000000)) { + NV_ERROR(dev, "PDISP: master 0x%08x\n", + nv_rd32(dev, 0x610490)); + return -EBUSY; } + nv_mask(dev, 0x610090, 0x00000001, 0x00000001); + nv_mask(dev, 0x6100a0, 0x00000001, 0x00000001); - push = evo_wait(dev, EVO_MASTER, 32); - if (!push) { - ret = -EBUSY; - goto error; + /* init cursors */ + for (i = 13; i <= 14; i++) { + nv_wr32(dev, 0x610490 + (i * 0x10), 0x00000001); + if (!nv_wait(dev, 0x610490 + (i * 0x10), 0x00010000, 0x00010000)) { + NV_ERROR(dev, "PDISP: curs%d 0x%08x\n", i, + nv_rd32(dev, 0x610490 + (i * 0x10))); + return -EBUSY; + } + + nv_mask(dev, 0x610090, 1 << i, 1 << i); + nv_mask(dev, 0x6100a0, 1 << i, 1 << i); } + + push = evo_wait(dev, 0, 32); + if (!push) + return -EBUSY; evo_mthd(push, 0x0088, 1); evo_data(push, NvEvoSync); evo_mthd(push, 0x0084, 1); @@ -1734,12 +1323,9 @@ nvd0_display_init(struct drm_device *dev) evo_data(push, 0x80000000); evo_mthd(push, 0x008c, 1); evo_data(push, 0x00000000); - evo_kick(push, dev, EVO_MASTER); + evo_kick(push, dev, 0); -error: - if (ret) - nvd0_display_fini(dev); - return ret; + return 0; } void @@ -1748,16 +1334,11 @@ nvd0_display_destroy(struct drm_device *dev) struct drm_nouveau_private *dev_priv = dev->dev_private; struct nvd0_display *disp = nvd0_display(dev); struct pci_dev *pdev = dev->pdev; - int i; - for (i = 0; i < EVO_DMA_NR; i++) { - struct evo *evo = &disp->evo[i]; - pci_free_consistent(pdev, PAGE_SIZE, evo->ptr, evo->handle); - } + nvd0_display_fini(dev); + pci_free_consistent(pdev, PAGE_SIZE, disp->evo[0].ptr, disp->evo[0].handle); nouveau_gpuobj_ref(NULL, &disp->mem); - nouveau_bo_unmap(disp->sync); - nouveau_bo_ref(NULL, &disp->sync); nouveau_irq_unregister(dev, 26); dev_priv->engine.display.priv = NULL; @@ -1829,83 +1410,61 @@ nvd0_display_create(struct drm_device *dev) tasklet_init(&disp->tasklet, nvd0_display_bh, (unsigned long)dev); nouveau_irq_register(dev, 26, nvd0_display_intr); - /* small shared memory area we use for notifiers and semaphores */ - ret = nouveau_bo_new(dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, - 0, 0x0000, &disp->sync); - if (!ret) { - ret = nouveau_bo_pin(disp->sync, TTM_PL_FLAG_VRAM); - if (!ret) - ret = nouveau_bo_map(disp->sync); - if (ret) - nouveau_bo_ref(NULL, &disp->sync); - } - - if (ret) - goto out; - /* hash table and dma objects for the memory areas we care about */ ret = nouveau_gpuobj_new(dev, NULL, 0x4000, 0x10000, NVOBJ_FLAG_ZERO_ALLOC, &disp->mem); if (ret) goto out; - /* create evo dma channels */ - for (i = 0; i < EVO_DMA_NR; i++) { - struct evo *evo = &disp->evo[i]; - u64 offset = disp->sync->bo.offset; - u32 dmao = 0x1000 + (i * 0x100); - u32 hash = 0x0000 + (i * 0x040); - - evo->idx = i; - evo->sem.offset = EVO_SYNC(evo->idx, 0x00); - evo->ptr = pci_alloc_consistent(pdev, PAGE_SIZE, &evo->handle); - if (!evo->ptr) { - ret = -ENOMEM; - goto out; - } + nv_wo32(disp->mem, 0x1000, 0x00000049); + nv_wo32(disp->mem, 0x1004, (disp->mem->vinst + 0x2000) >> 8); + nv_wo32(disp->mem, 0x1008, (disp->mem->vinst + 0x2fff) >> 8); + nv_wo32(disp->mem, 0x100c, 0x00000000); + nv_wo32(disp->mem, 0x1010, 0x00000000); + nv_wo32(disp->mem, 0x1014, 0x00000000); + nv_wo32(disp->mem, 0x0000, NvEvoSync); + nv_wo32(disp->mem, 0x0004, (0x1000 << 9) | 0x00000001); + + nv_wo32(disp->mem, 0x1020, 0x00000049); + nv_wo32(disp->mem, 0x1024, 0x00000000); + nv_wo32(disp->mem, 0x1028, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, 0x102c, 0x00000000); + nv_wo32(disp->mem, 0x1030, 0x00000000); + nv_wo32(disp->mem, 0x1034, 0x00000000); + nv_wo32(disp->mem, 0x0008, NvEvoVRAM); + nv_wo32(disp->mem, 0x000c, (0x1020 << 9) | 0x00000001); + + nv_wo32(disp->mem, 0x1040, 0x00000009); + nv_wo32(disp->mem, 0x1044, 0x00000000); + nv_wo32(disp->mem, 0x1048, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, 0x104c, 0x00000000); + nv_wo32(disp->mem, 0x1050, 0x00000000); + nv_wo32(disp->mem, 0x1054, 0x00000000); + nv_wo32(disp->mem, 0x0010, NvEvoVRAM_LP); + nv_wo32(disp->mem, 0x0014, (0x1040 << 9) | 0x00000001); + + nv_wo32(disp->mem, 0x1060, 0x0fe00009); + nv_wo32(disp->mem, 0x1064, 0x00000000); + nv_wo32(disp->mem, 0x1068, (dev_priv->vram_size - 1) >> 8); + nv_wo32(disp->mem, 0x106c, 0x00000000); + nv_wo32(disp->mem, 0x1070, 0x00000000); + nv_wo32(disp->mem, 0x1074, 0x00000000); + nv_wo32(disp->mem, 0x0018, NvEvoFB32); + nv_wo32(disp->mem, 0x001c, (0x1060 << 9) | 0x00000001); - nv_wo32(disp->mem, dmao + 0x00, 0x00000049); - nv_wo32(disp->mem, dmao + 0x04, (offset + 0x0000) >> 8); - nv_wo32(disp->mem, dmao + 0x08, (offset + 0x0fff) >> 8); - nv_wo32(disp->mem, dmao + 0x0c, 0x00000000); - nv_wo32(disp->mem, dmao + 0x10, 0x00000000); - nv_wo32(disp->mem, dmao + 0x14, 0x00000000); - nv_wo32(disp->mem, hash + 0x00, NvEvoSync); - nv_wo32(disp->mem, hash + 0x04, 0x00000001 | (i << 27) | - ((dmao + 0x00) << 9)); - - nv_wo32(disp->mem, dmao + 0x20, 0x00000049); - nv_wo32(disp->mem, dmao + 0x24, 0x00000000); - nv_wo32(disp->mem, dmao + 0x28, (dev_priv->vram_size - 1) >> 8); - nv_wo32(disp->mem, dmao + 0x2c, 0x00000000); - nv_wo32(disp->mem, dmao + 0x30, 0x00000000); - nv_wo32(disp->mem, dmao + 0x34, 0x00000000); - nv_wo32(disp->mem, hash + 0x08, NvEvoVRAM); - nv_wo32(disp->mem, hash + 0x0c, 0x00000001 | (i << 27) | - ((dmao + 0x20) << 9)); - - nv_wo32(disp->mem, dmao + 0x40, 0x00000009); - nv_wo32(disp->mem, dmao + 0x44, 0x00000000); - nv_wo32(disp->mem, dmao + 0x48, (dev_priv->vram_size - 1) >> 8); - nv_wo32(disp->mem, dmao + 0x4c, 0x00000000); - nv_wo32(disp->mem, dmao + 0x50, 0x00000000); - nv_wo32(disp->mem, dmao + 0x54, 0x00000000); - nv_wo32(disp->mem, hash + 0x10, NvEvoVRAM_LP); - nv_wo32(disp->mem, hash + 0x14, 0x00000001 | (i << 27) | - ((dmao + 0x40) << 9)); - - nv_wo32(disp->mem, dmao + 0x60, 0x0fe00009); - nv_wo32(disp->mem, dmao + 0x64, 0x00000000); - nv_wo32(disp->mem, dmao + 0x68, (dev_priv->vram_size - 1) >> 8); - nv_wo32(disp->mem, dmao + 0x6c, 0x00000000); - nv_wo32(disp->mem, dmao + 0x70, 0x00000000); - nv_wo32(disp->mem, dmao + 0x74, 0x00000000); - nv_wo32(disp->mem, hash + 0x18, NvEvoFB32); - nv_wo32(disp->mem, hash + 0x1c, 0x00000001 | (i << 27) | - ((dmao + 0x60) << 9)); + pinstmem->flush(dev); + + /* push buffers for evo channels */ + disp->evo[0].ptr = + pci_alloc_consistent(pdev, PAGE_SIZE, &disp->evo[0].handle); + if (!disp->evo[0].ptr) { + ret = -ENOMEM; + goto out; } - pinstmem->flush(dev); + ret = nvd0_display_init(dev); + if (ret) + goto out; out: if (ret) diff --git a/trunk/drivers/gpu/drm/sis/sis_drv.c b/trunk/drivers/gpu/drm/sis/sis_drv.c index bda96a8cd939..6ad0b857ba2e 100644 --- a/trunk/drivers/gpu/drm/sis/sis_drv.c +++ b/trunk/drivers/gpu/drm/sis/sis_drv.c @@ -76,10 +76,35 @@ static const struct file_operations sis_driver_fops = { .llseek = noop_llseek, }; +static int sis_driver_open(struct drm_device *dev, struct drm_file *file) +{ + struct sis_file_private *file_priv; + + DRM_DEBUG_DRIVER("\n"); + file_priv = kmalloc(sizeof(*file_priv), GFP_KERNEL); + if (!file_priv) + return -ENOMEM; + + file->driver_priv = file_priv; + + INIT_LIST_HEAD(&file_priv->obj_list); + + return 0; +} + +void sis_driver_postclose(struct drm_device *dev, struct drm_file *file) +{ + struct sis_file_private *file_priv = file->driver_priv; + + kfree(file_priv); +} + static struct drm_driver driver = { .driver_features = DRIVER_USE_AGP | DRIVER_USE_MTRR, .load = sis_driver_load, .unload = sis_driver_unload, + .open = sis_driver_open, + .postclose = sis_driver_postclose, .dma_quiescent = sis_idle, .reclaim_buffers = NULL, .reclaim_buffers_idlelocked = sis_reclaim_buffers_locked, diff --git a/trunk/drivers/gpu/drm/sis/sis_mm.c b/trunk/drivers/gpu/drm/sis/sis_mm.c index 7fe2b63412ce..a70b1bbff2e6 100644 --- a/trunk/drivers/gpu/drm/sis/sis_mm.c +++ b/trunk/drivers/gpu/drm/sis/sis_mm.c @@ -120,13 +120,14 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file return 0; } -static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, +static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file, void *data, int pool) { drm_sis_private_t *dev_priv = dev->dev_private; drm_sis_mem_t *mem = data; int retval = 0; struct drm_memblock_item *item; + struct sis_file_private *file_priv = file->driver_priv; mutex_lock(&dev->struct_mutex); @@ -139,11 +140,10 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, } mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; - item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0, - (unsigned long)file_priv); + item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0, 0); - mutex_unlock(&dev->struct_mutex); if (item) { + list_move(&item->owner_list, &file_priv->obj_list); mem->offset = ((pool == 0) ? dev_priv->vram_offset : dev_priv->agp_offset) + (item->mm-> @@ -156,6 +156,7 @@ static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, mem->free = 0; retval = -ENOMEM; } + mutex_unlock(&dev->struct_mutex); DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, mem->offset); @@ -301,12 +302,13 @@ void sis_lastclose(struct drm_device *dev) } void sis_reclaim_buffers_locked(struct drm_device *dev, - struct drm_file *file_priv) + struct drm_file *file) { - drm_sis_private_t *dev_priv = dev->dev_private; + struct sis_file_private *file_priv = file->driver_priv; + struct drm_memblock_item *entry, *next; mutex_lock(&dev->struct_mutex); - if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { + if (list_empty(&file_priv->obj_list)) { mutex_unlock(&dev->struct_mutex); return; } @@ -314,7 +316,11 @@ void sis_reclaim_buffers_locked(struct drm_device *dev, if (dev->driver->dma_quiescent) dev->driver->dma_quiescent(dev); - drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); + + list_for_each_entry_safe(entry, next, &file_priv->obj_list, + owner_list) { + drm_sman_free(entry); + } mutex_unlock(&dev->struct_mutex); return; } diff --git a/trunk/include/drm/drm_sman.h b/trunk/include/drm/drm_sman.h index 08ecf83ad5d4..3b65ccfd1400 100644 --- a/trunk/include/drm/drm_sman.h +++ b/trunk/include/drm/drm_sman.h @@ -146,6 +146,7 @@ extern struct drm_memblock_item *drm_sman_alloc(struct drm_sman * sman, */ extern int drm_sman_free_key(struct drm_sman * sman, unsigned int key); +extern void drm_sman_free(struct drm_memblock_item *item); /* * returns 1 iff there are no stale memory blocks associated with this owner. diff --git a/trunk/include/drm/sis_drm.h b/trunk/include/drm/sis_drm.h index 30f7b3827466..035b804dda6d 100644 --- a/trunk/include/drm/sis_drm.h +++ b/trunk/include/drm/sis_drm.h @@ -64,4 +64,8 @@ typedef struct { unsigned int offset, size; } drm_sis_fb_t; +struct sis_file_private { + struct list_head obj_list; +}; + #endif /* __SIS_DRM_H__ */