diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau')
29 files changed, 1128 insertions, 221 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index 2405d5ef0ca7..e9b06e4ef2a2 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
@@ -12,12 +12,12 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
12 | nouveau_dp.o \ | 12 | nouveau_dp.o \ |
13 | nv04_timer.o \ | 13 | nv04_timer.o \ |
14 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 14 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o \ | 15 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ |
16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o \ | 16 | nv04_fifo.o nv10_fifo.o nv40_fifo.o nv50_fifo.o nvc0_fifo.o \ |
17 | nv04_graph.o nv10_graph.o nv20_graph.o \ | 17 | nv04_graph.o nv10_graph.o nv20_graph.o \ |
18 | nv40_graph.o nv50_graph.o \ | 18 | nv40_graph.o nv50_graph.o nvc0_graph.o \ |
19 | nv40_grctx.o nv50_grctx.o \ | 19 | nv40_grctx.o nv50_grctx.o \ |
20 | nv04_instmem.o nv50_instmem.o \ | 20 | nv04_instmem.o nv50_instmem.o nvc0_instmem.o \ |
21 | nv50_crtc.o nv50_dac.o nv50_sor.o \ | 21 | nv50_crtc.o nv50_dac.o nv50_sor.o \ |
22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ | 22 | nv50_cursor.o nv50_display.o nv50_fbcon.o \ |
23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ | 23 | nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 7369b5e73649..0b69a9628c95 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -1928,6 +1928,31 @@ init_condition_time(struct nvbios *bios, uint16_t offset, | |||
1928 | } | 1928 | } |
1929 | 1929 | ||
1930 | static int | 1930 | static int |
1931 | init_ltime(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
1932 | { | ||
1933 | /* | ||
1934 | * INIT_LTIME opcode: 0x57 ('V') | ||
1935 | * | ||
1936 | * offset (8 bit): opcode | ||
1937 | * offset + 1 (16 bit): time | ||
1938 | * | ||
1939 | * Sleep for "time" miliseconds. | ||
1940 | */ | ||
1941 | |||
1942 | unsigned time = ROM16(bios->data[offset + 1]); | ||
1943 | |||
1944 | if (!iexec->execute) | ||
1945 | return 3; | ||
1946 | |||
1947 | BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X miliseconds\n", | ||
1948 | offset, time); | ||
1949 | |||
1950 | msleep(time); | ||
1951 | |||
1952 | return 3; | ||
1953 | } | ||
1954 | |||
1955 | static int | ||
1931 | init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, | 1956 | init_zm_reg_sequence(struct nvbios *bios, uint16_t offset, |
1932 | struct init_exec *iexec) | 1957 | struct init_exec *iexec) |
1933 | { | 1958 | { |
@@ -1995,6 +2020,64 @@ init_sub_direct(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
1995 | } | 2020 | } |
1996 | 2021 | ||
1997 | static int | 2022 | static int |
2023 | init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
2024 | { | ||
2025 | /* | ||
2026 | * INIT_I2C_IF opcode: 0x5E ('^') | ||
2027 | * | ||
2028 | * offset (8 bit): opcode | ||
2029 | * offset + 1 (8 bit): DCB I2C table entry index | ||
2030 | * offset + 2 (8 bit): I2C slave address | ||
2031 | * offset + 3 (8 bit): I2C register | ||
2032 | * offset + 4 (8 bit): mask | ||
2033 | * offset + 5 (8 bit): data | ||
2034 | * | ||
2035 | * Read the register given by "I2C register" on the device addressed | ||
2036 | * by "I2C slave address" on the I2C bus given by "DCB I2C table | ||
2037 | * entry index". Compare the result AND "mask" to "data". | ||
2038 | * If they're not equal, skip subsequent opcodes until condition is | ||
2039 | * inverted (INIT_NOT), or we hit INIT_RESUME | ||
2040 | */ | ||
2041 | |||
2042 | uint8_t i2c_index = bios->data[offset + 1]; | ||
2043 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | ||
2044 | uint8_t reg = bios->data[offset + 3]; | ||
2045 | uint8_t mask = bios->data[offset + 4]; | ||
2046 | uint8_t data = bios->data[offset + 5]; | ||
2047 | struct nouveau_i2c_chan *chan; | ||
2048 | union i2c_smbus_data val; | ||
2049 | int ret; | ||
2050 | |||
2051 | /* no execute check by design */ | ||
2052 | |||
2053 | BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", | ||
2054 | offset, i2c_index, i2c_address); | ||
2055 | |||
2056 | chan = init_i2c_device_find(bios->dev, i2c_index); | ||
2057 | if (!chan) | ||
2058 | return -ENODEV; | ||
2059 | |||
2060 | ret = i2c_smbus_xfer(&chan->adapter, i2c_address, 0, | ||
2061 | I2C_SMBUS_READ, reg, | ||
2062 | I2C_SMBUS_BYTE_DATA, &val); | ||
2063 | if (ret < 0) { | ||
2064 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: [no device], " | ||
2065 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
2066 | offset, reg, mask, data); | ||
2067 | iexec->execute = 0; | ||
2068 | return 6; | ||
2069 | } | ||
2070 | |||
2071 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X, Value: 0x%02X, " | ||
2072 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
2073 | offset, reg, val.byte, mask, data); | ||
2074 | |||
2075 | iexec->execute = ((val.byte & mask) == data); | ||
2076 | |||
2077 | return 6; | ||
2078 | } | ||
2079 | |||
2080 | static int | ||
1998 | init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | 2081 | init_copy_nv_reg(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) |
1999 | { | 2082 | { |
2000 | /* | 2083 | /* |
@@ -2083,9 +2166,10 @@ peek_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2083 | uint32_t val = 0; | 2166 | uint32_t val = 0; |
2084 | 2167 | ||
2085 | if (off < pci_resource_len(dev->pdev, 1)) { | 2168 | if (off < pci_resource_len(dev->pdev, 1)) { |
2086 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | 2169 | uint32_t __iomem *p = |
2170 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | ||
2087 | 2171 | ||
2088 | val = ioread32(p); | 2172 | val = ioread32(p + (off & ~PAGE_MASK)); |
2089 | 2173 | ||
2090 | io_mapping_unmap_atomic(p, KM_USER0); | 2174 | io_mapping_unmap_atomic(p, KM_USER0); |
2091 | } | 2175 | } |
@@ -2098,9 +2182,10 @@ poke_fb(struct drm_device *dev, struct io_mapping *fb, | |||
2098 | uint32_t off, uint32_t val) | 2182 | uint32_t off, uint32_t val) |
2099 | { | 2183 | { |
2100 | if (off < pci_resource_len(dev->pdev, 1)) { | 2184 | if (off < pci_resource_len(dev->pdev, 1)) { |
2101 | uint32_t __iomem *p = io_mapping_map_atomic_wc(fb, off, KM_USER0); | 2185 | uint32_t __iomem *p = |
2186 | io_mapping_map_atomic_wc(fb, off & PAGE_MASK, KM_USER0); | ||
2102 | 2187 | ||
2103 | iowrite32(val, p); | 2188 | iowrite32(val, p + (off & ~PAGE_MASK)); |
2104 | wmb(); | 2189 | wmb(); |
2105 | 2190 | ||
2106 | io_mapping_unmap_atomic(p, KM_USER0); | 2191 | io_mapping_unmap_atomic(p, KM_USER0); |
@@ -2165,7 +2250,7 @@ nv04_init_compute_mem(struct nvbios *bios) | |||
2165 | NV04_PFB_BOOT_0_RAM_AMOUNT, | 2250 | NV04_PFB_BOOT_0_RAM_AMOUNT, |
2166 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); | 2251 | NV04_PFB_BOOT_0_RAM_AMOUNT_4MB); |
2167 | 2252 | ||
2168 | } else if (peek_fb(dev, fb, 0) == patt) { | 2253 | } else if (peek_fb(dev, fb, 0) != patt) { |
2169 | if (read_back_fb(dev, fb, 0x800000, patt)) | 2254 | if (read_back_fb(dev, fb, 0x800000, patt)) |
2170 | bios_md32(bios, NV04_PFB_BOOT_0, | 2255 | bios_md32(bios, NV04_PFB_BOOT_0, |
2171 | NV04_PFB_BOOT_0_RAM_AMOUNT, | 2256 | NV04_PFB_BOOT_0_RAM_AMOUNT, |
@@ -2593,7 +2678,7 @@ init_configure_preinit(struct nvbios *bios, uint16_t offset, | |||
2593 | /* no iexec->execute check by design */ | 2678 | /* no iexec->execute check by design */ |
2594 | 2679 | ||
2595 | uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); | 2680 | uint32_t straps = bios_rd32(bios, NV_PEXTDEV_BOOT_0); |
2596 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & (1 << 6)); | 2681 | uint8_t cr3c = ((straps << 2) & 0xf0) | (straps & 0x40) >> 6; |
2597 | 2682 | ||
2598 | if (bios->major_version > 2) | 2683 | if (bios->major_version > 2) |
2599 | return 0; | 2684 | return 0; |
@@ -3140,7 +3225,7 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
3140 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; | 3225 | const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; |
3141 | int i; | 3226 | int i; |
3142 | 3227 | ||
3143 | if (dev_priv->card_type != NV_50) { | 3228 | if (dev_priv->card_type < NV_50) { |
3144 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); | 3229 | NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); |
3145 | return 1; | 3230 | return 1; |
3146 | } | 3231 | } |
@@ -3490,6 +3575,69 @@ init_zm_auxch(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
3490 | return len; | 3575 | return len; |
3491 | } | 3576 | } |
3492 | 3577 | ||
3578 | static int | ||
3579 | init_i2c_long_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | ||
3580 | { | ||
3581 | /* | ||
3582 | * INIT_I2C_LONG_IF opcode: 0x9A ('') | ||
3583 | * | ||
3584 | * offset (8 bit): opcode | ||
3585 | * offset + 1 (8 bit): DCB I2C table entry index | ||
3586 | * offset + 2 (8 bit): I2C slave address | ||
3587 | * offset + 3 (16 bit): I2C register | ||
3588 | * offset + 5 (8 bit): mask | ||
3589 | * offset + 6 (8 bit): data | ||
3590 | * | ||
3591 | * Read the register given by "I2C register" on the device addressed | ||
3592 | * by "I2C slave address" on the I2C bus given by "DCB I2C table | ||
3593 | * entry index". Compare the result AND "mask" to "data". | ||
3594 | * If they're not equal, skip subsequent opcodes until condition is | ||
3595 | * inverted (INIT_NOT), or we hit INIT_RESUME | ||
3596 | */ | ||
3597 | |||
3598 | uint8_t i2c_index = bios->data[offset + 1]; | ||
3599 | uint8_t i2c_address = bios->data[offset + 2] >> 1; | ||
3600 | uint8_t reglo = bios->data[offset + 3]; | ||
3601 | uint8_t reghi = bios->data[offset + 4]; | ||
3602 | uint8_t mask = bios->data[offset + 5]; | ||
3603 | uint8_t data = bios->data[offset + 6]; | ||
3604 | struct nouveau_i2c_chan *chan; | ||
3605 | uint8_t buf0[2] = { reghi, reglo }; | ||
3606 | uint8_t buf1[1]; | ||
3607 | struct i2c_msg msg[2] = { | ||
3608 | { i2c_address, 0, 1, buf0 }, | ||
3609 | { i2c_address, I2C_M_RD, 1, buf1 }, | ||
3610 | }; | ||
3611 | int ret; | ||
3612 | |||
3613 | /* no execute check by design */ | ||
3614 | |||
3615 | BIOSLOG(bios, "0x%04X: DCBI2CIndex: 0x%02X, I2CAddress: 0x%02X\n", | ||
3616 | offset, i2c_index, i2c_address); | ||
3617 | |||
3618 | chan = init_i2c_device_find(bios->dev, i2c_index); | ||
3619 | if (!chan) | ||
3620 | return -ENODEV; | ||
3621 | |||
3622 | |||
3623 | ret = i2c_transfer(&chan->adapter, msg, 2); | ||
3624 | if (ret < 0) { | ||
3625 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: [no device], " | ||
3626 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
3627 | offset, reghi, reglo, mask, data); | ||
3628 | iexec->execute = 0; | ||
3629 | return 7; | ||
3630 | } | ||
3631 | |||
3632 | BIOSLOG(bios, "0x%04X: I2CReg: 0x%02X:0x%02X, Value: 0x%02X, " | ||
3633 | "Mask: 0x%02X, Data: 0x%02X\n", | ||
3634 | offset, reghi, reglo, buf1[0], mask, data); | ||
3635 | |||
3636 | iexec->execute = ((buf1[0] & mask) == data); | ||
3637 | |||
3638 | return 7; | ||
3639 | } | ||
3640 | |||
3493 | static struct init_tbl_entry itbl_entry[] = { | 3641 | static struct init_tbl_entry itbl_entry[] = { |
3494 | /* command name , id , length , offset , mult , command handler */ | 3642 | /* command name , id , length , offset , mult , command handler */ |
3495 | /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ | 3643 | /* INIT_PROG (0x31, 15, 10, 4) removed due to no example of use */ |
@@ -3516,9 +3664,11 @@ static struct init_tbl_entry itbl_entry[] = { | |||
3516 | { "INIT_ZM_CR" , 0x53, init_zm_cr }, | 3664 | { "INIT_ZM_CR" , 0x53, init_zm_cr }, |
3517 | { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, | 3665 | { "INIT_ZM_CR_GROUP" , 0x54, init_zm_cr_group }, |
3518 | { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, | 3666 | { "INIT_CONDITION_TIME" , 0x56, init_condition_time }, |
3667 | { "INIT_LTIME" , 0x57, init_ltime }, | ||
3519 | { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, | 3668 | { "INIT_ZM_REG_SEQUENCE" , 0x58, init_zm_reg_sequence }, |
3520 | /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ | 3669 | /* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */ |
3521 | { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, | 3670 | { "INIT_SUB_DIRECT" , 0x5B, init_sub_direct }, |
3671 | { "INIT_I2C_IF" , 0x5E, init_i2c_if }, | ||
3522 | { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, | 3672 | { "INIT_COPY_NV_REG" , 0x5F, init_copy_nv_reg }, |
3523 | { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, | 3673 | { "INIT_ZM_INDEX_IO" , 0x62, init_zm_index_io }, |
3524 | { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, | 3674 | { "INIT_COMPUTE_MEM" , 0x63, init_compute_mem }, |
@@ -3552,6 +3702,7 @@ static struct init_tbl_entry itbl_entry[] = { | |||
3552 | { "INIT_97" , 0x97, init_97 }, | 3702 | { "INIT_97" , 0x97, init_97 }, |
3553 | { "INIT_AUXCH" , 0x98, init_auxch }, | 3703 | { "INIT_AUXCH" , 0x98, init_auxch }, |
3554 | { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, | 3704 | { "INIT_ZM_AUXCH" , 0x99, init_zm_auxch }, |
3705 | { "INIT_I2C_LONG_IF" , 0x9A, init_i2c_long_if }, | ||
3555 | { NULL , 0 , NULL } | 3706 | { NULL , 0 , NULL } |
3556 | }; | 3707 | }; |
3557 | 3708 | ||
@@ -4410,7 +4561,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4410 | bios->display.script_table_ptr, | 4561 | bios->display.script_table_ptr, |
4411 | table[2], table[3], table[0] >= 0x21); | 4562 | table[2], table[3], table[0] >= 0x21); |
4412 | if (!otable) { | 4563 | if (!otable) { |
4413 | NV_ERROR(dev, "Couldn't find matching output script table\n"); | 4564 | NV_DEBUG_KMS(dev, "failed to match any output table\n"); |
4414 | return 1; | 4565 | return 1; |
4415 | } | 4566 | } |
4416 | 4567 | ||
@@ -4467,7 +4618,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4467 | if (script) | 4618 | if (script) |
4468 | script = clkcmptable(bios, script, pxclk); | 4619 | script = clkcmptable(bios, script, pxclk); |
4469 | if (!script) { | 4620 | if (!script) { |
4470 | NV_ERROR(dev, "clock script 0 not found\n"); | 4621 | NV_DEBUG_KMS(dev, "clock script 0 not found\n"); |
4471 | return 1; | 4622 | return 1; |
4472 | } | 4623 | } |
4473 | 4624 | ||
@@ -4826,7 +4977,7 @@ int get_pll_limits(struct drm_device *dev, uint32_t limit_match, struct pll_lims | |||
4826 | pll_lim->min_p = record[12]; | 4977 | pll_lim->min_p = record[12]; |
4827 | pll_lim->max_p = record[13]; | 4978 | pll_lim->max_p = record[13]; |
4828 | /* where did this go to?? */ | 4979 | /* where did this go to?? */ |
4829 | if (limit_match == 0x00614100 || limit_match == 0x00614900) | 4980 | if ((entry[0] & 0xf0) == 0x80) |
4830 | pll_lim->refclk = 27000; | 4981 | pll_lim->refclk = 27000; |
4831 | else | 4982 | else |
4832 | pll_lim->refclk = 100000; | 4983 | pll_lim->refclk = 100000; |
@@ -5852,7 +6003,7 @@ static void fabricate_vga_output(struct dcb_table *dcb, int i2c, int heads) | |||
5852 | entry->i2c_index = i2c; | 6003 | entry->i2c_index = i2c; |
5853 | entry->heads = heads; | 6004 | entry->heads = heads; |
5854 | entry->location = DCB_LOC_ON_CHIP; | 6005 | entry->location = DCB_LOC_ON_CHIP; |
5855 | /* "or" mostly unused in early gen crt modesetting, 0 is fine */ | 6006 | entry->or = 1; |
5856 | } | 6007 | } |
5857 | 6008 | ||
5858 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) | 6009 | static void fabricate_dvi_i_output(struct dcb_table *dcb, bool twoHeads) |
@@ -5980,7 +6131,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
5980 | } | 6131 | } |
5981 | break; | 6132 | break; |
5982 | case OUTPUT_TMDS: | 6133 | case OUTPUT_TMDS: |
5983 | entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; | 6134 | if (dcb->version >= 0x40) |
6135 | entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; | ||
6136 | else if (dcb->version >= 0x30) | ||
6137 | entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; | ||
6138 | else if (dcb->version >= 0x22) | ||
6139 | entry->tmdsconf.slave_addr = (conf & 0x00000070) >> 4; | ||
6140 | |||
5984 | break; | 6141 | break; |
5985 | case 0xe: | 6142 | case 0xe: |
5986 | /* weird g80 mobile type that "nv" treats as a terminator */ | 6143 | /* weird g80 mobile type that "nv" treats as a terminator */ |
@@ -6270,6 +6427,19 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | |||
6270 | dcb->i2c_table = &bios->data[i2ctabptr]; | 6427 | dcb->i2c_table = &bios->data[i2ctabptr]; |
6271 | if (dcb->version >= 0x30) | 6428 | if (dcb->version >= 0x30) |
6272 | dcb->i2c_default_indices = dcb->i2c_table[4]; | 6429 | dcb->i2c_default_indices = dcb->i2c_table[4]; |
6430 | |||
6431 | /* | ||
6432 | * Parse the "management" I2C bus, used for hardware | ||
6433 | * monitoring and some external TMDS transmitters. | ||
6434 | */ | ||
6435 | if (dcb->version >= 0x22) { | ||
6436 | int idx = (dcb->version >= 0x40 ? | ||
6437 | dcb->i2c_default_indices & 0xf : | ||
6438 | 2); | ||
6439 | |||
6440 | read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, | ||
6441 | idx, &dcb->i2c[idx]); | ||
6442 | } | ||
6273 | } | 6443 | } |
6274 | 6444 | ||
6275 | if (entries > DCB_MAX_NUM_ENTRIES) | 6445 | if (entries > DCB_MAX_NUM_ENTRIES) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index 024458a8d060..fd14dfd3d780 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -131,6 +131,7 @@ struct dcb_entry { | |||
131 | } dpconf; | 131 | } dpconf; |
132 | struct { | 132 | struct { |
133 | struct sor_conf sor; | 133 | struct sor_conf sor; |
134 | int slave_addr; | ||
134 | } tmdsconf; | 135 | } tmdsconf; |
135 | }; | 136 | }; |
136 | bool i2c_upper_default; | 137 | bool i2c_upper_default; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 3ca8343c15df..84f85183d041 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -51,9 +51,6 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) | |||
51 | if (nvbo->tile) | 51 | if (nvbo->tile) |
52 | nv10_mem_expire_tiling(dev, nvbo->tile, NULL); | 52 | nv10_mem_expire_tiling(dev, nvbo->tile, NULL); |
53 | 53 | ||
54 | spin_lock(&dev_priv->ttm.bo_list_lock); | ||
55 | list_del(&nvbo->head); | ||
56 | spin_unlock(&dev_priv->ttm.bo_list_lock); | ||
57 | kfree(nvbo); | 54 | kfree(nvbo); |
58 | } | 55 | } |
59 | 56 | ||
@@ -166,9 +163,6 @@ nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan, | |||
166 | } | 163 | } |
167 | nvbo->channel = NULL; | 164 | nvbo->channel = NULL; |
168 | 165 | ||
169 | spin_lock(&dev_priv->ttm.bo_list_lock); | ||
170 | list_add_tail(&nvbo->head, &dev_priv->ttm.bo_list); | ||
171 | spin_unlock(&dev_priv->ttm.bo_list_lock); | ||
172 | *pnvbo = nvbo; | 166 | *pnvbo = nvbo; |
173 | return 0; | 167 | return 0; |
174 | } | 168 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 734e92635e83..b1b22baf1428 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -37,12 +37,6 @@ | |||
37 | #include "nouveau_connector.h" | 37 | #include "nouveau_connector.h" |
38 | #include "nouveau_hw.h" | 38 | #include "nouveau_hw.h" |
39 | 39 | ||
40 | static inline struct drm_encoder_slave_funcs * | ||
41 | get_slave_funcs(struct nouveau_encoder *enc) | ||
42 | { | ||
43 | return to_encoder_slave(to_drm_encoder(enc))->slave_funcs; | ||
44 | } | ||
45 | |||
46 | static struct nouveau_encoder * | 40 | static struct nouveau_encoder * |
47 | find_encoder_by_type(struct drm_connector *connector, int type) | 41 | find_encoder_by_type(struct drm_connector *connector, int type) |
48 | { | 42 | { |
@@ -360,6 +354,7 @@ nouveau_connector_set_property(struct drm_connector *connector, | |||
360 | { | 354 | { |
361 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 355 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
362 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 356 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
357 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
363 | struct drm_device *dev = connector->dev; | 358 | struct drm_device *dev = connector->dev; |
364 | int ret; | 359 | int ret; |
365 | 360 | ||
@@ -432,8 +427,8 @@ nouveau_connector_set_property(struct drm_connector *connector, | |||
432 | } | 427 | } |
433 | 428 | ||
434 | if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) | 429 | if (nv_encoder && nv_encoder->dcb->type == OUTPUT_TV) |
435 | return get_slave_funcs(nv_encoder)-> | 430 | return get_slave_funcs(encoder)->set_property( |
436 | set_property(to_drm_encoder(nv_encoder), connector, property, value); | 431 | encoder, connector, property, value); |
437 | 432 | ||
438 | return -EINVAL; | 433 | return -EINVAL; |
439 | } | 434 | } |
@@ -545,6 +540,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
545 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 540 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
546 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 541 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
547 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 542 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
543 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
548 | int ret = 0; | 544 | int ret = 0; |
549 | 545 | ||
550 | /* destroy the native mode, the attached monitor could have changed. | 546 | /* destroy the native mode, the attached monitor could have changed. |
@@ -580,8 +576,7 @@ nouveau_connector_get_modes(struct drm_connector *connector) | |||
580 | } | 576 | } |
581 | 577 | ||
582 | if (nv_encoder->dcb->type == OUTPUT_TV) | 578 | if (nv_encoder->dcb->type == OUTPUT_TV) |
583 | ret = get_slave_funcs(nv_encoder)-> | 579 | ret = get_slave_funcs(encoder)->get_modes(encoder, connector); |
584 | get_modes(to_drm_encoder(nv_encoder), connector); | ||
585 | 580 | ||
586 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || | 581 | if (nv_connector->dcb->type == DCB_CONNECTOR_LVDS || |
587 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) | 582 | nv_connector->dcb->type == DCB_CONNECTOR_eDP) |
@@ -597,6 +592,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
597 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; | 592 | struct drm_nouveau_private *dev_priv = connector->dev->dev_private; |
598 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 593 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
599 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; | 594 | struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder; |
595 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | ||
600 | unsigned min_clock = 25000, max_clock = min_clock; | 596 | unsigned min_clock = 25000, max_clock = min_clock; |
601 | unsigned clock = mode->clock; | 597 | unsigned clock = mode->clock; |
602 | 598 | ||
@@ -623,8 +619,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector, | |||
623 | max_clock = 350000; | 619 | max_clock = 350000; |
624 | break; | 620 | break; |
625 | case OUTPUT_TV: | 621 | case OUTPUT_TV: |
626 | return get_slave_funcs(nv_encoder)-> | 622 | return get_slave_funcs(encoder)->mode_valid(encoder, mode); |
627 | mode_valid(to_drm_encoder(nv_encoder), mode); | ||
628 | case OUTPUT_DP: | 623 | case OUTPUT_DP: |
629 | if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) | 624 | if (nv_encoder->dp.link_bw == DP_LINK_BW_2_7) |
630 | max_clock = nv_encoder->dp.link_nr * 270000; | 625 | max_clock = nv_encoder->dp.link_nr * 270000; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 74e6b4ed12c0..2e11fd65b4dd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -84,16 +84,16 @@ nouveau_user_framebuffer_create(struct drm_device *dev, | |||
84 | 84 | ||
85 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); | 85 | gem = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); |
86 | if (!gem) | 86 | if (!gem) |
87 | return NULL; | 87 | return ERR_PTR(-ENOENT); |
88 | 88 | ||
89 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); | 89 | nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL); |
90 | if (!nouveau_fb) | 90 | if (!nouveau_fb) |
91 | return NULL; | 91 | return ERR_PTR(-ENOMEM); |
92 | 92 | ||
93 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); | 93 | ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem)); |
94 | if (ret) { | 94 | if (ret) { |
95 | drm_gem_object_unreference(gem); | 95 | drm_gem_object_unreference(gem); |
96 | return NULL; | 96 | return ERR_PTR(ret); |
97 | } | 97 | } |
98 | 98 | ||
99 | return &nouveau_fb->base; | 99 | return &nouveau_fb->base; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 33742b11188b..8a1b188b4cd1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -572,47 +572,64 @@ out: | |||
572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); | 572 | return ret ? ret : (stat & NV50_AUXCH_STAT_REPLY); |
573 | } | 573 | } |
574 | 574 | ||
575 | int | 575 | static int |
576 | nouveau_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, | 576 | nouveau_dp_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) |
577 | uint8_t write_byte, uint8_t *read_byte) | ||
578 | { | 577 | { |
579 | struct i2c_algo_dp_aux_data *algo_data = adapter->algo_data; | 578 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adap; |
580 | struct nouveau_i2c_chan *auxch = (struct nouveau_i2c_chan *)adapter; | ||
581 | struct drm_device *dev = auxch->dev; | 579 | struct drm_device *dev = auxch->dev; |
582 | int ret = 0, cmd, addr = algo_data->address; | 580 | struct i2c_msg *msg = msgs; |
583 | uint8_t *buf; | 581 | int ret, mcnt = num; |
584 | |||
585 | if (mode == MODE_I2C_READ) { | ||
586 | cmd = AUX_I2C_READ; | ||
587 | buf = read_byte; | ||
588 | } else { | ||
589 | cmd = (mode & MODE_I2C_READ) ? AUX_I2C_READ : AUX_I2C_WRITE; | ||
590 | buf = &write_byte; | ||
591 | } | ||
592 | 582 | ||
593 | if (!(mode & MODE_I2C_STOP)) | 583 | while (mcnt--) { |
594 | cmd |= AUX_I2C_MOT; | 584 | u8 remaining = msg->len; |
585 | u8 *ptr = msg->buf; | ||
595 | 586 | ||
596 | if (mode & MODE_I2C_START) | 587 | while (remaining) { |
597 | return 1; | 588 | u8 cnt = (remaining > 16) ? 16 : remaining; |
589 | u8 cmd; | ||
598 | 590 | ||
599 | for (;;) { | 591 | if (msg->flags & I2C_M_RD) |
600 | ret = nouveau_dp_auxch(auxch, cmd, addr, buf, 1); | 592 | cmd = AUX_I2C_READ; |
601 | if (ret < 0) | 593 | else |
602 | return ret; | 594 | cmd = AUX_I2C_WRITE; |
603 | 595 | ||
604 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { | 596 | if (mcnt || remaining > 16) |
605 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: | 597 | cmd |= AUX_I2C_MOT; |
606 | return 1; | 598 | |
607 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: | 599 | ret = nouveau_dp_auxch(auxch, cmd, msg->addr, ptr, cnt); |
608 | return -EREMOTEIO; | 600 | if (ret < 0) |
609 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | 601 | return ret; |
610 | udelay(100); | 602 | |
611 | break; | 603 | switch (ret & NV50_AUXCH_STAT_REPLY_I2C) { |
612 | default: | 604 | case NV50_AUXCH_STAT_REPLY_I2C_ACK: |
613 | NV_ERROR(dev, "invalid auxch status: 0x%08x\n", ret); | 605 | break; |
614 | return -EREMOTEIO; | 606 | case NV50_AUXCH_STAT_REPLY_I2C_NACK: |
607 | return -EREMOTEIO; | ||
608 | case NV50_AUXCH_STAT_REPLY_I2C_DEFER: | ||
609 | udelay(100); | ||
610 | continue; | ||
611 | default: | ||
612 | NV_ERROR(dev, "bad auxch reply: 0x%08x\n", ret); | ||
613 | return -EREMOTEIO; | ||
614 | } | ||
615 | |||
616 | ptr += cnt; | ||
617 | remaining -= cnt; | ||
615 | } | 618 | } |
619 | |||
620 | msg++; | ||
616 | } | 621 | } |
622 | |||
623 | return num; | ||
624 | } | ||
625 | |||
626 | static u32 | ||
627 | nouveau_dp_i2c_func(struct i2c_adapter *adap) | ||
628 | { | ||
629 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||
617 | } | 630 | } |
618 | 631 | ||
632 | const struct i2c_algorithm nouveau_dp_i2c_algo = { | ||
633 | .master_xfer = nouveau_dp_i2c_xfer, | ||
634 | .functionality = nouveau_dp_i2c_func | ||
635 | }; | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index e15db15dca77..e424bf74d706 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -410,7 +410,7 @@ enum nv04_fp_display_regs { | |||
410 | 410 | ||
411 | struct nv04_crtc_reg { | 411 | struct nv04_crtc_reg { |
412 | unsigned char MiscOutReg; /* */ | 412 | unsigned char MiscOutReg; /* */ |
413 | uint8_t CRTC[0x9f]; | 413 | uint8_t CRTC[0xa0]; |
414 | uint8_t CR58[0x10]; | 414 | uint8_t CR58[0x10]; |
415 | uint8_t Sequencer[5]; | 415 | uint8_t Sequencer[5]; |
416 | uint8_t Graphics[9]; | 416 | uint8_t Graphics[9]; |
@@ -509,6 +509,7 @@ enum nouveau_card_type { | |||
509 | NV_30 = 0x30, | 509 | NV_30 = 0x30, |
510 | NV_40 = 0x40, | 510 | NV_40 = 0x40, |
511 | NV_50 = 0x50, | 511 | NV_50 = 0x50, |
512 | NV_C0 = 0xc0, | ||
512 | }; | 513 | }; |
513 | 514 | ||
514 | struct drm_nouveau_private { | 515 | struct drm_nouveau_private { |
@@ -536,8 +537,6 @@ struct drm_nouveau_private { | |||
536 | struct drm_global_reference mem_global_ref; | 537 | struct drm_global_reference mem_global_ref; |
537 | struct ttm_bo_global_ref bo_global_ref; | 538 | struct ttm_bo_global_ref bo_global_ref; |
538 | struct ttm_bo_device bdev; | 539 | struct ttm_bo_device bdev; |
539 | spinlock_t bo_list_lock; | ||
540 | struct list_head bo_list; | ||
541 | atomic_t validate_sequence; | 540 | atomic_t validate_sequence; |
542 | } ttm; | 541 | } ttm; |
543 | 542 | ||
@@ -931,6 +930,10 @@ extern void nv40_fb_set_region_tiling(struct drm_device *, int, uint32_t, | |||
931 | extern int nv50_fb_init(struct drm_device *); | 930 | extern int nv50_fb_init(struct drm_device *); |
932 | extern void nv50_fb_takedown(struct drm_device *); | 931 | extern void nv50_fb_takedown(struct drm_device *); |
933 | 932 | ||
933 | /* nvc0_fb.c */ | ||
934 | extern int nvc0_fb_init(struct drm_device *); | ||
935 | extern void nvc0_fb_takedown(struct drm_device *); | ||
936 | |||
934 | /* nv04_fifo.c */ | 937 | /* nv04_fifo.c */ |
935 | extern int nv04_fifo_init(struct drm_device *); | 938 | extern int nv04_fifo_init(struct drm_device *); |
936 | extern void nv04_fifo_disable(struct drm_device *); | 939 | extern void nv04_fifo_disable(struct drm_device *); |
@@ -968,6 +971,20 @@ extern void nv50_fifo_destroy_context(struct nouveau_channel *); | |||
968 | extern int nv50_fifo_load_context(struct nouveau_channel *); | 971 | extern int nv50_fifo_load_context(struct nouveau_channel *); |
969 | extern int nv50_fifo_unload_context(struct drm_device *); | 972 | extern int nv50_fifo_unload_context(struct drm_device *); |
970 | 973 | ||
974 | /* nvc0_fifo.c */ | ||
975 | extern int nvc0_fifo_init(struct drm_device *); | ||
976 | extern void nvc0_fifo_takedown(struct drm_device *); | ||
977 | extern void nvc0_fifo_disable(struct drm_device *); | ||
978 | extern void nvc0_fifo_enable(struct drm_device *); | ||
979 | extern bool nvc0_fifo_reassign(struct drm_device *, bool); | ||
980 | extern bool nvc0_fifo_cache_flush(struct drm_device *); | ||
981 | extern bool nvc0_fifo_cache_pull(struct drm_device *, bool); | ||
982 | extern int nvc0_fifo_channel_id(struct drm_device *); | ||
983 | extern int nvc0_fifo_create_context(struct nouveau_channel *); | ||
984 | extern void nvc0_fifo_destroy_context(struct nouveau_channel *); | ||
985 | extern int nvc0_fifo_load_context(struct nouveau_channel *); | ||
986 | extern int nvc0_fifo_unload_context(struct drm_device *); | ||
987 | |||
971 | /* nv04_graph.c */ | 988 | /* nv04_graph.c */ |
972 | extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; | 989 | extern struct nouveau_pgraph_object_class nv04_graph_grclass[]; |
973 | extern int nv04_graph_init(struct drm_device *); | 990 | extern int nv04_graph_init(struct drm_device *); |
@@ -1032,6 +1049,16 @@ extern int nv50_graph_unload_context(struct drm_device *); | |||
1032 | extern void nv50_graph_context_switch(struct drm_device *); | 1049 | extern void nv50_graph_context_switch(struct drm_device *); |
1033 | extern int nv50_grctx_init(struct nouveau_grctx *); | 1050 | extern int nv50_grctx_init(struct nouveau_grctx *); |
1034 | 1051 | ||
1052 | /* nvc0_graph.c */ | ||
1053 | extern int nvc0_graph_init(struct drm_device *); | ||
1054 | extern void nvc0_graph_takedown(struct drm_device *); | ||
1055 | extern void nvc0_graph_fifo_access(struct drm_device *, bool); | ||
1056 | extern struct nouveau_channel *nvc0_graph_channel(struct drm_device *); | ||
1057 | extern int nvc0_graph_create_context(struct nouveau_channel *); | ||
1058 | extern void nvc0_graph_destroy_context(struct nouveau_channel *); | ||
1059 | extern int nvc0_graph_load_context(struct nouveau_channel *); | ||
1060 | extern int nvc0_graph_unload_context(struct drm_device *); | ||
1061 | |||
1035 | /* nv04_instmem.c */ | 1062 | /* nv04_instmem.c */ |
1036 | extern int nv04_instmem_init(struct drm_device *); | 1063 | extern int nv04_instmem_init(struct drm_device *); |
1037 | extern void nv04_instmem_takedown(struct drm_device *); | 1064 | extern void nv04_instmem_takedown(struct drm_device *); |
@@ -1058,6 +1085,18 @@ extern void nv50_instmem_flush(struct drm_device *); | |||
1058 | extern void nv84_instmem_flush(struct drm_device *); | 1085 | extern void nv84_instmem_flush(struct drm_device *); |
1059 | extern void nv50_vm_flush(struct drm_device *, int engine); | 1086 | extern void nv50_vm_flush(struct drm_device *, int engine); |
1060 | 1087 | ||
1088 | /* nvc0_instmem.c */ | ||
1089 | extern int nvc0_instmem_init(struct drm_device *); | ||
1090 | extern void nvc0_instmem_takedown(struct drm_device *); | ||
1091 | extern int nvc0_instmem_suspend(struct drm_device *); | ||
1092 | extern void nvc0_instmem_resume(struct drm_device *); | ||
1093 | extern int nvc0_instmem_populate(struct drm_device *, struct nouveau_gpuobj *, | ||
1094 | uint32_t *size); | ||
1095 | extern void nvc0_instmem_clear(struct drm_device *, struct nouveau_gpuobj *); | ||
1096 | extern int nvc0_instmem_bind(struct drm_device *, struct nouveau_gpuobj *); | ||
1097 | extern int nvc0_instmem_unbind(struct drm_device *, struct nouveau_gpuobj *); | ||
1098 | extern void nvc0_instmem_flush(struct drm_device *); | ||
1099 | |||
1061 | /* nv04_mc.c */ | 1100 | /* nv04_mc.c */ |
1062 | extern int nv04_mc_init(struct drm_device *); | 1101 | extern int nv04_mc_init(struct drm_device *); |
1063 | extern void nv04_mc_takedown(struct drm_device *); | 1102 | extern void nv04_mc_takedown(struct drm_device *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index a1a0d48ae70c..7c82d68bc155 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h | |||
@@ -71,6 +71,12 @@ static inline struct drm_encoder *to_drm_encoder(struct nouveau_encoder *enc) | |||
71 | return &enc->base.base; | 71 | return &enc->base.base; |
72 | } | 72 | } |
73 | 73 | ||
74 | static inline struct drm_encoder_slave_funcs * | ||
75 | get_slave_funcs(struct drm_encoder *enc) | ||
76 | { | ||
77 | return to_encoder_slave(enc)->slave_funcs; | ||
78 | } | ||
79 | |||
74 | struct nouveau_connector * | 80 | struct nouveau_connector * |
75 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); | 81 | nouveau_encoder_connector_get(struct nouveau_encoder *encoder); |
76 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); | 82 | int nv50_sor_create(struct drm_connector *, struct dcb_entry *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 099f637264aa..dbd30b2e43fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c | |||
@@ -281,6 +281,8 @@ nouveau_fbcon_create(struct nouveau_fbdev *nfbdev, | |||
281 | 281 | ||
282 | if (dev_priv->channel && !nouveau_nofbaccel) { | 282 | if (dev_priv->channel && !nouveau_nofbaccel) { |
283 | switch (dev_priv->card_type) { | 283 | switch (dev_priv->card_type) { |
284 | case NV_C0: | ||
285 | break; | ||
284 | case NV_50: | 286 | case NV_50: |
285 | nv50_fbcon_accel_init(info); | 287 | nv50_fbcon_accel_init(info); |
286 | info->fbops = &nv50_fbcon_ops; | 288 | info->fbops = &nv50_fbcon_ops; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 547f2c24c1e7..0f417ac1b696 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -284,7 +284,7 @@ retry: | |||
284 | if (!gem) { | 284 | if (!gem) { |
285 | NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); | 285 | NV_ERROR(dev, "Unknown handle 0x%08x\n", b->handle); |
286 | validate_fini(op, NULL); | 286 | validate_fini(op, NULL); |
287 | return -EINVAL; | 287 | return -ENOENT; |
288 | } | 288 | } |
289 | nvbo = gem->driver_private; | 289 | nvbo = gem->driver_private; |
290 | 290 | ||
@@ -759,7 +759,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, | |||
759 | 759 | ||
760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 760 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
761 | if (!gem) | 761 | if (!gem) |
762 | return ret; | 762 | return -ENOENT; |
763 | nvbo = nouveau_gem_object(gem); | 763 | nvbo = nouveau_gem_object(gem); |
764 | 764 | ||
765 | if (nvbo->cpu_filp) { | 765 | if (nvbo->cpu_filp) { |
@@ -797,7 +797,7 @@ nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, | |||
797 | 797 | ||
798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 798 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
799 | if (!gem) | 799 | if (!gem) |
800 | return ret; | 800 | return -ENOENT; |
801 | nvbo = nouveau_gem_object(gem); | 801 | nvbo = nouveau_gem_object(gem); |
802 | 802 | ||
803 | if (nvbo->cpu_filp != file_priv) | 803 | if (nvbo->cpu_filp != file_priv) |
@@ -822,7 +822,7 @@ nouveau_gem_ioctl_info(struct drm_device *dev, void *data, | |||
822 | 822 | ||
823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); | 823 | gem = drm_gem_object_lookup(dev, file_priv, req->handle); |
824 | if (!gem) | 824 | if (!gem) |
825 | return -EINVAL; | 825 | return -ENOENT; |
826 | 826 | ||
827 | ret = nouveau_gem_info(gem, req); | 827 | ret = nouveau_gem_info(gem, req); |
828 | drm_gem_object_unreference_unlocked(gem); | 828 | drm_gem_object_unreference_unlocked(gem); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_hw.c b/drivers/gpu/drm/nouveau/nouveau_hw.c index 7855b35effc3..7b613682e400 100644 --- a/drivers/gpu/drm/nouveau/nouveau_hw.c +++ b/drivers/gpu/drm/nouveau/nouveau_hw.c | |||
@@ -865,8 +865,12 @@ nv_save_state_ext(struct drm_device *dev, int head, | |||
865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 865 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 866 | rd_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); | 867 | rd_cio_state(dev, head, regp, NV_CIO_CRE_21); |
868 | if (dev_priv->card_type >= NV_30) | 868 | |
869 | if (dev_priv->card_type >= NV_30) { | ||
869 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); | 870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_47); |
871 | rd_cio_state(dev, head, regp, 0x9f); | ||
872 | } | ||
873 | |||
870 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); | 874 | rd_cio_state(dev, head, regp, NV_CIO_CRE_49); |
871 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 875 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
872 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); | 876 | rd_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR1_INDEX); |
@@ -971,8 +975,11 @@ nv_load_state_ext(struct drm_device *dev, int head, | |||
971 | wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); | 975 | wr_cio_state(dev, head, regp, NV_CIO_CRE_ENH_INDEX); |
972 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); | 976 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FF_INDEX); |
973 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); | 977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_FFLWM__INDEX); |
974 | if (dev_priv->card_type >= NV_30) | 978 | |
979 | if (dev_priv->card_type >= NV_30) { | ||
975 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); | 980 | wr_cio_state(dev, head, regp, NV_CIO_CRE_47); |
981 | wr_cio_state(dev, head, regp, 0x9f); | ||
982 | } | ||
976 | 983 | ||
977 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); | 984 | wr_cio_state(dev, head, regp, NV_CIO_CRE_49); |
978 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); | 985 | wr_cio_state(dev, head, regp, NV_CIO_CRE_HCUR_ADDR0_INDEX); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index cb0cb34440c6..0bd407ca3d42 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -163,7 +163,7 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
163 | if (entry->chan) | 163 | if (entry->chan) |
164 | return -EEXIST; | 164 | return -EEXIST; |
165 | 165 | ||
166 | if (dev_priv->card_type == NV_50 && entry->read >= NV50_I2C_PORTS) { | 166 | if (dev_priv->card_type == NV_C0 && entry->read >= NV50_I2C_PORTS) { |
167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); | 167 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); |
168 | return -EINVAL; | 168 | return -EINVAL; |
169 | } | 169 | } |
@@ -174,26 +174,26 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
174 | 174 | ||
175 | switch (entry->port_type) { | 175 | switch (entry->port_type) { |
176 | case 0: | 176 | case 0: |
177 | i2c->algo.bit.setsda = nv04_i2c_setsda; | 177 | i2c->bit.setsda = nv04_i2c_setsda; |
178 | i2c->algo.bit.setscl = nv04_i2c_setscl; | 178 | i2c->bit.setscl = nv04_i2c_setscl; |
179 | i2c->algo.bit.getsda = nv04_i2c_getsda; | 179 | i2c->bit.getsda = nv04_i2c_getsda; |
180 | i2c->algo.bit.getscl = nv04_i2c_getscl; | 180 | i2c->bit.getscl = nv04_i2c_getscl; |
181 | i2c->rd = entry->read; | 181 | i2c->rd = entry->read; |
182 | i2c->wr = entry->write; | 182 | i2c->wr = entry->write; |
183 | break; | 183 | break; |
184 | case 4: | 184 | case 4: |
185 | i2c->algo.bit.setsda = nv4e_i2c_setsda; | 185 | i2c->bit.setsda = nv4e_i2c_setsda; |
186 | i2c->algo.bit.setscl = nv4e_i2c_setscl; | 186 | i2c->bit.setscl = nv4e_i2c_setscl; |
187 | i2c->algo.bit.getsda = nv4e_i2c_getsda; | 187 | i2c->bit.getsda = nv4e_i2c_getsda; |
188 | i2c->algo.bit.getscl = nv4e_i2c_getscl; | 188 | i2c->bit.getscl = nv4e_i2c_getscl; |
189 | i2c->rd = 0x600800 + entry->read; | 189 | i2c->rd = 0x600800 + entry->read; |
190 | i2c->wr = 0x600800 + entry->write; | 190 | i2c->wr = 0x600800 + entry->write; |
191 | break; | 191 | break; |
192 | case 5: | 192 | case 5: |
193 | i2c->algo.bit.setsda = nv50_i2c_setsda; | 193 | i2c->bit.setsda = nv50_i2c_setsda; |
194 | i2c->algo.bit.setscl = nv50_i2c_setscl; | 194 | i2c->bit.setscl = nv50_i2c_setscl; |
195 | i2c->algo.bit.getsda = nv50_i2c_getsda; | 195 | i2c->bit.getsda = nv50_i2c_getsda; |
196 | i2c->algo.bit.getscl = nv50_i2c_getscl; | 196 | i2c->bit.getscl = nv50_i2c_getscl; |
197 | i2c->rd = nv50_i2c_port[entry->read]; | 197 | i2c->rd = nv50_i2c_port[entry->read]; |
198 | i2c->wr = i2c->rd; | 198 | i2c->wr = i2c->rd; |
199 | break; | 199 | break; |
@@ -216,17 +216,14 @@ nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | |||
216 | i2c_set_adapdata(&i2c->adapter, i2c); | 216 | i2c_set_adapdata(&i2c->adapter, i2c); |
217 | 217 | ||
218 | if (entry->port_type < 6) { | 218 | if (entry->port_type < 6) { |
219 | i2c->adapter.algo_data = &i2c->algo.bit; | 219 | i2c->adapter.algo_data = &i2c->bit; |
220 | i2c->algo.bit.udelay = 40; | 220 | i2c->bit.udelay = 40; |
221 | i2c->algo.bit.timeout = usecs_to_jiffies(5000); | 221 | i2c->bit.timeout = usecs_to_jiffies(5000); |
222 | i2c->algo.bit.data = i2c; | 222 | i2c->bit.data = i2c; |
223 | ret = i2c_bit_add_bus(&i2c->adapter); | 223 | ret = i2c_bit_add_bus(&i2c->adapter); |
224 | } else { | 224 | } else { |
225 | i2c->adapter.algo_data = &i2c->algo.dp; | 225 | i2c->adapter.algo = &nouveau_dp_i2c_algo; |
226 | i2c->algo.dp.running = false; | 226 | ret = i2c_add_adapter(&i2c->adapter); |
227 | i2c->algo.dp.address = 0; | ||
228 | i2c->algo.dp.aux_ch = nouveau_dp_i2c_aux_ch; | ||
229 | ret = i2c_dp_aux_add_bus(&i2c->adapter); | ||
230 | } | 227 | } |
231 | 228 | ||
232 | if (ret) { | 229 | if (ret) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index 6dd2f8713cd1..f71cb32f7571 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h | |||
@@ -33,10 +33,7 @@ struct dcb_i2c_entry; | |||
33 | struct nouveau_i2c_chan { | 33 | struct nouveau_i2c_chan { |
34 | struct i2c_adapter adapter; | 34 | struct i2c_adapter adapter; |
35 | struct drm_device *dev; | 35 | struct drm_device *dev; |
36 | union { | 36 | struct i2c_algo_bit_data bit; |
37 | struct i2c_algo_bit_data bit; | ||
38 | struct i2c_algo_dp_aux_data dp; | ||
39 | } algo; | ||
40 | unsigned rd; | 37 | unsigned rd; |
41 | unsigned wr; | 38 | unsigned wr; |
42 | unsigned data; | 39 | unsigned data; |
@@ -49,7 +46,6 @@ bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | |||
49 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | 46 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, |
50 | struct i2c_board_info *info, int index); | 47 | struct i2c_board_info *info, int index); |
51 | 48 | ||
52 | int nouveau_dp_i2c_aux_ch(struct i2c_adapter *, int mode, uint8_t write_byte, | 49 | extern const struct i2c_algorithm nouveau_dp_i2c_algo; |
53 | uint8_t *read_byte); | ||
54 | 50 | ||
55 | #endif /* __NOUVEAU_I2C_H__ */ | 51 | #endif /* __NOUVEAU_I2C_H__ */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 53360f156063..794b0ee30cf6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -49,7 +49,7 @@ nouveau_irq_preinstall(struct drm_device *dev) | |||
49 | /* Master disable */ | 49 | /* Master disable */ |
50 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); | 50 | nv_wr32(dev, NV03_PMC_INTR_EN_0, 0); |
51 | 51 | ||
52 | if (dev_priv->card_type == NV_50) { | 52 | if (dev_priv->card_type >= NV_50) { |
53 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); | 53 | INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh); |
54 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); | 54 | INIT_WORK(&dev_priv->hpd_work, nv50_display_irq_hotplug_bh); |
55 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); | 55 | INIT_LIST_HEAD(&dev_priv->vbl_waiting); |
@@ -586,11 +586,11 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) | |||
586 | } | 586 | } |
587 | 587 | ||
588 | if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { | 588 | if (status & NV_PGRAPH_INTR_CONTEXT_SWITCH) { |
589 | nouveau_pgraph_intr_context_switch(dev); | ||
590 | |||
591 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; | 589 | status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; |
592 | nv_wr32(dev, NV03_PGRAPH_INTR, | 590 | nv_wr32(dev, NV03_PGRAPH_INTR, |
593 | NV_PGRAPH_INTR_CONTEXT_SWITCH); | 591 | NV_PGRAPH_INTR_CONTEXT_SWITCH); |
592 | |||
593 | nouveau_pgraph_intr_context_switch(dev); | ||
594 | } | 594 | } |
595 | 595 | ||
596 | if (status) { | 596 | if (status) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index a9f36ab256b7..9689d4147686 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -320,7 +320,8 @@ nouveau_mem_detect(struct drm_device *dev) | |||
320 | if (dev_priv->card_type < NV_50) { | 320 | if (dev_priv->card_type < NV_50) { |
321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 321 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; | 322 | dev_priv->vram_size &= NV10_PFB_FIFO_DATA_RAM_AMOUNT_MB_MASK; |
323 | } else { | 323 | } else |
324 | if (dev_priv->card_type < NV_C0) { | ||
324 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); | 325 | dev_priv->vram_size = nv_rd32(dev, NV04_PFB_FIFO_DATA); |
325 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; | 326 | dev_priv->vram_size |= (dev_priv->vram_size & 0xff) << 32; |
326 | dev_priv->vram_size &= 0xffffffff00ll; | 327 | dev_priv->vram_size &= 0xffffffff00ll; |
@@ -328,6 +329,9 @@ nouveau_mem_detect(struct drm_device *dev) | |||
328 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); | 329 | dev_priv->vram_sys_base = nv_rd32(dev, 0x100e10); |
329 | dev_priv->vram_sys_base <<= 12; | 330 | dev_priv->vram_sys_base <<= 12; |
330 | } | 331 | } |
332 | } else { | ||
333 | dev_priv->vram_size = nv_rd32(dev, 0x10f20c) << 20; | ||
334 | dev_priv->vram_size *= nv_rd32(dev, 0x121c74); | ||
331 | } | 335 | } |
332 | 336 | ||
333 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); | 337 | NV_INFO(dev, "Detected %dMiB VRAM\n", (int)(dev_priv->vram_size >> 20)); |
@@ -351,7 +355,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
351 | /* First of all, disable fast writes, otherwise if it's | 355 | /* First of all, disable fast writes, otherwise if it's |
352 | * already enabled in the AGP bridge and we disable the card's | 356 | * already enabled in the AGP bridge and we disable the card's |
353 | * AGP controller we might be locking ourselves out of it. */ | 357 | * AGP controller we might be locking ourselves out of it. */ |
354 | if (dev->agp->acquired) { | 358 | if (nv_rd32(dev, NV04_PBUS_PCI_NV_19) & PCI_AGP_COMMAND_FW) { |
355 | struct drm_agp_info info; | 359 | struct drm_agp_info info; |
356 | struct drm_agp_mode mode; | 360 | struct drm_agp_mode mode; |
357 | 361 | ||
@@ -359,7 +363,7 @@ nouveau_mem_reset_agp(struct drm_device *dev) | |||
359 | if (ret) | 363 | if (ret) |
360 | return ret; | 364 | return ret; |
361 | 365 | ||
362 | mode.mode = info.mode & ~0x10; | 366 | mode.mode = info.mode & ~PCI_AGP_COMMAND_FW; |
363 | ret = drm_agp_enable(dev, mode); | 367 | ret = drm_agp_enable(dev, mode); |
364 | if (ret) | 368 | if (ret) |
365 | return ret; | 369 | return ret; |
@@ -405,6 +409,8 @@ nouveau_mem_init_agp(struct drm_device *dev) | |||
405 | } | 409 | } |
406 | } | 410 | } |
407 | 411 | ||
412 | nouveau_mem_reset_agp(dev); | ||
413 | |||
408 | ret = drm_agp_info(dev, &info); | 414 | ret = drm_agp_info(dev, &info); |
409 | if (ret) { | 415 | if (ret) { |
410 | NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); | 416 | NV_ERROR(dev, "Unable to get AGP info: %d\n", ret); |
@@ -459,8 +465,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
459 | return ret; | 465 | return ret; |
460 | } | 466 | } |
461 | 467 | ||
462 | INIT_LIST_HEAD(&dev_priv->ttm.bo_list); | ||
463 | spin_lock_init(&dev_priv->ttm.bo_list_lock); | ||
464 | spin_lock_init(&dev_priv->tile.lock); | 468 | spin_lock_init(&dev_priv->tile.lock); |
465 | 469 | ||
466 | dev_priv->fb_available_size = dev_priv->vram_size; | 470 | dev_priv->fb_available_size = dev_priv->vram_size; |
@@ -494,7 +498,6 @@ nouveau_mem_init(struct drm_device *dev) | |||
494 | /* GART */ | 498 | /* GART */ |
495 | #if !defined(__powerpc__) && !defined(__ia64__) | 499 | #if !defined(__powerpc__) && !defined(__ia64__) |
496 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { | 500 | if (drm_device_is_agp(dev) && dev->agp && !nouveau_noagp) { |
497 | nouveau_mem_reset_agp(dev); | ||
498 | ret = nouveau_mem_init_agp(dev); | 501 | ret = nouveau_mem_init_agp(dev); |
499 | if (ret) | 502 | if (ret) |
500 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); | 503 | NV_ERROR(dev, "Error initialising AGP: %d\n", ret); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_reg.h b/drivers/gpu/drm/nouveau/nouveau_reg.h index 9c1056cb8a90..21a6e453b975 100644 --- a/drivers/gpu/drm/nouveau/nouveau_reg.h +++ b/drivers/gpu/drm/nouveau/nouveau_reg.h | |||
@@ -220,28 +220,21 @@ | |||
220 | # define NV_PGRAPH_INTR_ERROR (1<<20) | 220 | # define NV_PGRAPH_INTR_ERROR (1<<20) |
221 | #define NV10_PGRAPH_CTX_CONTROL 0x00400144 | 221 | #define NV10_PGRAPH_CTX_CONTROL 0x00400144 |
222 | #define NV10_PGRAPH_CTX_USER 0x00400148 | 222 | #define NV10_PGRAPH_CTX_USER 0x00400148 |
223 | #define NV10_PGRAPH_CTX_SWITCH1 0x0040014C | 223 | #define NV10_PGRAPH_CTX_SWITCH(i) (0x0040014C + 0x4*(i)) |
224 | #define NV10_PGRAPH_CTX_SWITCH2 0x00400150 | ||
225 | #define NV10_PGRAPH_CTX_SWITCH3 0x00400154 | ||
226 | #define NV10_PGRAPH_CTX_SWITCH4 0x00400158 | ||
227 | #define NV10_PGRAPH_CTX_SWITCH5 0x0040015C | ||
228 | #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 | 224 | #define NV04_PGRAPH_CTX_SWITCH1 0x00400160 |
229 | #define NV10_PGRAPH_CTX_CACHE1 0x00400160 | 225 | #define NV10_PGRAPH_CTX_CACHE(i, j) (0x00400160 \ |
226 | + 0x4*(i) + 0x20*(j)) | ||
230 | #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 | 227 | #define NV04_PGRAPH_CTX_SWITCH2 0x00400164 |
231 | #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 | 228 | #define NV04_PGRAPH_CTX_SWITCH3 0x00400168 |
232 | #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C | 229 | #define NV04_PGRAPH_CTX_SWITCH4 0x0040016C |
233 | #define NV04_PGRAPH_CTX_CONTROL 0x00400170 | 230 | #define NV04_PGRAPH_CTX_CONTROL 0x00400170 |
234 | #define NV04_PGRAPH_CTX_USER 0x00400174 | 231 | #define NV04_PGRAPH_CTX_USER 0x00400174 |
235 | #define NV04_PGRAPH_CTX_CACHE1 0x00400180 | 232 | #define NV04_PGRAPH_CTX_CACHE1 0x00400180 |
236 | #define NV10_PGRAPH_CTX_CACHE2 0x00400180 | ||
237 | #define NV03_PGRAPH_CTX_CONTROL 0x00400190 | 233 | #define NV03_PGRAPH_CTX_CONTROL 0x00400190 |
238 | #define NV03_PGRAPH_CTX_USER 0x00400194 | 234 | #define NV03_PGRAPH_CTX_USER 0x00400194 |
239 | #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 | 235 | #define NV04_PGRAPH_CTX_CACHE2 0x004001A0 |
240 | #define NV10_PGRAPH_CTX_CACHE3 0x004001A0 | ||
241 | #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 | 236 | #define NV04_PGRAPH_CTX_CACHE3 0x004001C0 |
242 | #define NV10_PGRAPH_CTX_CACHE4 0x004001C0 | ||
243 | #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 | 237 | #define NV04_PGRAPH_CTX_CACHE4 0x004001E0 |
244 | #define NV10_PGRAPH_CTX_CACHE5 0x004001E0 | ||
245 | #define NV40_PGRAPH_CTXCTL_0304 0x00400304 | 238 | #define NV40_PGRAPH_CTXCTL_0304 0x00400304 |
246 | #define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 | 239 | #define NV40_PGRAPH_CTXCTL_0304_XFER_CTX 0x00000001 |
247 | #define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 | 240 | #define NV40_PGRAPH_CTXCTL_UCODE_STAT 0x00400308 |
@@ -356,9 +349,12 @@ | |||
356 | #define NV04_PGRAPH_FFINTFC_ST2 0x00400754 | 349 | #define NV04_PGRAPH_FFINTFC_ST2 0x00400754 |
357 | #define NV10_PGRAPH_RDI_DATA 0x00400754 | 350 | #define NV10_PGRAPH_RDI_DATA 0x00400754 |
358 | #define NV04_PGRAPH_DMA_PITCH 0x00400760 | 351 | #define NV04_PGRAPH_DMA_PITCH 0x00400760 |
359 | #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 | 352 | #define NV10_PGRAPH_FFINTFC_FIFO_PTR 0x00400760 |
360 | #define NV04_PGRAPH_DVD_COLORFMT 0x00400764 | 353 | #define NV04_PGRAPH_DVD_COLORFMT 0x00400764 |
354 | #define NV10_PGRAPH_FFINTFC_ST2 0x00400764 | ||
361 | #define NV04_PGRAPH_SCALED_FORMAT 0x00400768 | 355 | #define NV04_PGRAPH_SCALED_FORMAT 0x00400768 |
356 | #define NV10_PGRAPH_FFINTFC_ST2_DL 0x00400768 | ||
357 | #define NV10_PGRAPH_FFINTFC_ST2_DH 0x0040076c | ||
362 | #define NV10_PGRAPH_DMA_PITCH 0x00400770 | 358 | #define NV10_PGRAPH_DMA_PITCH 0x00400770 |
363 | #define NV10_PGRAPH_DVD_COLORFMT 0x00400774 | 359 | #define NV10_PGRAPH_DVD_COLORFMT 0x00400774 |
364 | #define NV10_PGRAPH_SCALED_FORMAT 0x00400778 | 360 | #define NV10_PGRAPH_SCALED_FORMAT 0x00400778 |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index ee3729e7823b..989322be3728 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -359,6 +359,54 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
359 | engine->gpio.set = nv50_gpio_set; | 359 | engine->gpio.set = nv50_gpio_set; |
360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | 360 | engine->gpio.irq_enable = nv50_gpio_irq_enable; |
361 | break; | 361 | break; |
362 | case 0xC0: | ||
363 | engine->instmem.init = nvc0_instmem_init; | ||
364 | engine->instmem.takedown = nvc0_instmem_takedown; | ||
365 | engine->instmem.suspend = nvc0_instmem_suspend; | ||
366 | engine->instmem.resume = nvc0_instmem_resume; | ||
367 | engine->instmem.populate = nvc0_instmem_populate; | ||
368 | engine->instmem.clear = nvc0_instmem_clear; | ||
369 | engine->instmem.bind = nvc0_instmem_bind; | ||
370 | engine->instmem.unbind = nvc0_instmem_unbind; | ||
371 | engine->instmem.flush = nvc0_instmem_flush; | ||
372 | engine->mc.init = nv50_mc_init; | ||
373 | engine->mc.takedown = nv50_mc_takedown; | ||
374 | engine->timer.init = nv04_timer_init; | ||
375 | engine->timer.read = nv04_timer_read; | ||
376 | engine->timer.takedown = nv04_timer_takedown; | ||
377 | engine->fb.init = nvc0_fb_init; | ||
378 | engine->fb.takedown = nvc0_fb_takedown; | ||
379 | engine->graph.grclass = NULL; //nvc0_graph_grclass; | ||
380 | engine->graph.init = nvc0_graph_init; | ||
381 | engine->graph.takedown = nvc0_graph_takedown; | ||
382 | engine->graph.fifo_access = nvc0_graph_fifo_access; | ||
383 | engine->graph.channel = nvc0_graph_channel; | ||
384 | engine->graph.create_context = nvc0_graph_create_context; | ||
385 | engine->graph.destroy_context = nvc0_graph_destroy_context; | ||
386 | engine->graph.load_context = nvc0_graph_load_context; | ||
387 | engine->graph.unload_context = nvc0_graph_unload_context; | ||
388 | engine->fifo.channels = 128; | ||
389 | engine->fifo.init = nvc0_fifo_init; | ||
390 | engine->fifo.takedown = nvc0_fifo_takedown; | ||
391 | engine->fifo.disable = nvc0_fifo_disable; | ||
392 | engine->fifo.enable = nvc0_fifo_enable; | ||
393 | engine->fifo.reassign = nvc0_fifo_reassign; | ||
394 | engine->fifo.channel_id = nvc0_fifo_channel_id; | ||
395 | engine->fifo.create_context = nvc0_fifo_create_context; | ||
396 | engine->fifo.destroy_context = nvc0_fifo_destroy_context; | ||
397 | engine->fifo.load_context = nvc0_fifo_load_context; | ||
398 | engine->fifo.unload_context = nvc0_fifo_unload_context; | ||
399 | engine->display.early_init = nv50_display_early_init; | ||
400 | engine->display.late_takedown = nv50_display_late_takedown; | ||
401 | engine->display.create = nv50_display_create; | ||
402 | engine->display.init = nv50_display_init; | ||
403 | engine->display.destroy = nv50_display_destroy; | ||
404 | engine->gpio.init = nv50_gpio_init; | ||
405 | engine->gpio.takedown = nouveau_stub_takedown; | ||
406 | engine->gpio.get = nv50_gpio_get; | ||
407 | engine->gpio.set = nv50_gpio_set; | ||
408 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | ||
409 | break; | ||
362 | default: | 410 | default: |
363 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); | 411 | NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); |
364 | return 1; | 412 | return 1; |
@@ -739,8 +787,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
739 | int ret; | 787 | int ret; |
740 | 788 | ||
741 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); | 789 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); |
742 | if (!dev_priv) | 790 | if (!dev_priv) { |
743 | return -ENOMEM; | 791 | ret = -ENOMEM; |
792 | goto err_out; | ||
793 | } | ||
744 | dev->dev_private = dev_priv; | 794 | dev->dev_private = dev_priv; |
745 | dev_priv->dev = dev; | 795 | dev_priv->dev = dev; |
746 | 796 | ||
@@ -750,8 +800,10 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
750 | dev->pci_vendor, dev->pci_device, dev->pdev->class); | 800 | dev->pci_vendor, dev->pci_device, dev->pdev->class); |
751 | 801 | ||
752 | dev_priv->wq = create_workqueue("nouveau"); | 802 | dev_priv->wq = create_workqueue("nouveau"); |
753 | if (!dev_priv->wq) | 803 | if (!dev_priv->wq) { |
754 | return -EINVAL; | 804 | ret = -EINVAL; |
805 | goto err_priv; | ||
806 | } | ||
755 | 807 | ||
756 | /* resource 0 is mmio regs */ | 808 | /* resource 0 is mmio regs */ |
757 | /* resource 1 is linear FB */ | 809 | /* resource 1 is linear FB */ |
@@ -764,7 +816,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
764 | if (!dev_priv->mmio) { | 816 | if (!dev_priv->mmio) { |
765 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " | 817 | NV_ERROR(dev, "Unable to initialize the mmio mapping. " |
766 | "Please report your setup to " DRIVER_EMAIL "\n"); | 818 | "Please report your setup to " DRIVER_EMAIL "\n"); |
767 | return -EINVAL; | 819 | ret = -EINVAL; |
820 | goto err_wq; | ||
768 | } | 821 | } |
769 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", | 822 | NV_DEBUG(dev, "regs mapped ok at 0x%llx\n", |
770 | (unsigned long long)mmio_start_offs); | 823 | (unsigned long long)mmio_start_offs); |
@@ -810,9 +863,13 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
810 | case 0xa0: | 863 | case 0xa0: |
811 | dev_priv->card_type = NV_50; | 864 | dev_priv->card_type = NV_50; |
812 | break; | 865 | break; |
866 | case 0xc0: | ||
867 | dev_priv->card_type = NV_C0; | ||
868 | break; | ||
813 | default: | 869 | default: |
814 | NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); | 870 | NV_INFO(dev, "Unsupported chipset 0x%08x\n", reg0); |
815 | return -EINVAL; | 871 | ret = -EINVAL; |
872 | goto err_mmio; | ||
816 | } | 873 | } |
817 | 874 | ||
818 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", | 875 | NV_INFO(dev, "Detected an NV%2x generation card (0x%08x)\n", |
@@ -820,7 +877,7 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
820 | 877 | ||
821 | ret = nouveau_remove_conflicting_drivers(dev); | 878 | ret = nouveau_remove_conflicting_drivers(dev); |
822 | if (ret) | 879 | if (ret) |
823 | return ret; | 880 | goto err_mmio; |
824 | 881 | ||
825 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ | 882 | /* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */ |
826 | if (dev_priv->card_type >= NV_40) { | 883 | if (dev_priv->card_type >= NV_40) { |
@@ -834,7 +891,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
834 | dev_priv->ramin_size); | 891 | dev_priv->ramin_size); |
835 | if (!dev_priv->ramin) { | 892 | if (!dev_priv->ramin) { |
836 | NV_ERROR(dev, "Failed to PRAMIN BAR"); | 893 | NV_ERROR(dev, "Failed to PRAMIN BAR"); |
837 | return -ENOMEM; | 894 | ret = -ENOMEM; |
895 | goto err_mmio; | ||
838 | } | 896 | } |
839 | } else { | 897 | } else { |
840 | dev_priv->ramin_size = 1 * 1024 * 1024; | 898 | dev_priv->ramin_size = 1 * 1024 * 1024; |
@@ -842,7 +900,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
842 | dev_priv->ramin_size); | 900 | dev_priv->ramin_size); |
843 | if (!dev_priv->ramin) { | 901 | if (!dev_priv->ramin) { |
844 | NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); | 902 | NV_ERROR(dev, "Failed to map BAR0 PRAMIN.\n"); |
845 | return -ENOMEM; | 903 | ret = -ENOMEM; |
904 | goto err_mmio; | ||
846 | } | 905 | } |
847 | } | 906 | } |
848 | 907 | ||
@@ -857,9 +916,21 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) | |||
857 | /* For kernel modesetting, init card now and bring up fbcon */ | 916 | /* For kernel modesetting, init card now and bring up fbcon */ |
858 | ret = nouveau_card_init(dev); | 917 | ret = nouveau_card_init(dev); |
859 | if (ret) | 918 | if (ret) |
860 | return ret; | 919 | goto err_ramin; |
861 | 920 | ||
862 | return 0; | 921 | return 0; |
922 | |||
923 | err_ramin: | ||
924 | iounmap(dev_priv->ramin); | ||
925 | err_mmio: | ||
926 | iounmap(dev_priv->mmio); | ||
927 | err_wq: | ||
928 | destroy_workqueue(dev_priv->wq); | ||
929 | err_priv: | ||
930 | kfree(dev_priv); | ||
931 | dev->dev_private = NULL; | ||
932 | err_out: | ||
933 | return ret; | ||
863 | } | 934 | } |
864 | 935 | ||
865 | void nouveau_lastclose(struct drm_device *dev) | 936 | void nouveau_lastclose(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/nouveau/nv04_crtc.c b/drivers/gpu/drm/nouveau/nv04_crtc.c index 1c20c08ce67c..497df8765f28 100644 --- a/drivers/gpu/drm/nouveau/nv04_crtc.c +++ b/drivers/gpu/drm/nouveau/nv04_crtc.c | |||
@@ -542,6 +542,9 @@ nv_crtc_mode_set_regs(struct drm_crtc *crtc, struct drm_display_mode * mode) | |||
542 | * 1 << 30 on 0x60.830), for no apparent reason */ | 542 | * 1 << 30 on 0x60.830), for no apparent reason */ |
543 | regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; | 543 | regp->CRTC[NV_CIO_CRE_59] = off_chip_digital; |
544 | 544 | ||
545 | if (dev_priv->card_type >= NV_30) | ||
546 | regp->CRTC[0x9f] = off_chip_digital ? 0x11 : 0x1; | ||
547 | |||
545 | regp->crtc_830 = mode->crtc_vdisplay - 3; | 548 | regp->crtc_830 = mode->crtc_vdisplay - 3; |
546 | regp->crtc_834 = mode->crtc_vdisplay - 1; | 549 | regp->crtc_834 = mode->crtc_vdisplay - 1; |
547 | 550 | ||
@@ -739,15 +742,13 @@ nv_crtc_gamma_load(struct drm_crtc *crtc) | |||
739 | } | 742 | } |
740 | 743 | ||
741 | static void | 744 | static void |
742 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t size) | 745 | nv_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, uint32_t start, |
746 | uint32_t size) | ||
743 | { | 747 | { |
748 | int end = (start + size > 256) ? 256 : start + size, i; | ||
744 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 749 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
745 | int i; | ||
746 | 750 | ||
747 | if (size != 256) | 751 | for (i = start; i < end; i++) { |
748 | return; | ||
749 | |||
750 | for (i = 0; i < 256; i++) { | ||
751 | nv_crtc->lut.r[i] = r[i]; | 752 | nv_crtc->lut.r[i] = r[i]; |
752 | nv_crtc->lut.g[i] = g[i]; | 753 | nv_crtc->lut.g[i] = g[i]; |
753 | nv_crtc->lut.b[i] = b[i]; | 754 | nv_crtc->lut.b[i] = b[i]; |
@@ -914,7 +915,7 @@ nv04_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | |||
914 | 915 | ||
915 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); | 916 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); |
916 | if (!gem) | 917 | if (!gem) |
917 | return -EINVAL; | 918 | return -ENOENT; |
918 | cursor = nouveau_gem_object(gem); | 919 | cursor = nouveau_gem_object(gem); |
919 | 920 | ||
920 | ret = nouveau_bo_map(cursor); | 921 | ret = nouveau_bo_map(cursor); |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 3311f3a8c818..a5dcf7685800 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "nouveau_hw.h" | 34 | #include "nouveau_hw.h" |
35 | #include "nvreg.h" | 35 | #include "nvreg.h" |
36 | 36 | ||
37 | #include "i2c/sil164.h" | ||
38 | |||
37 | #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ | 39 | #define FP_TG_CONTROL_ON (NV_PRAMDAC_FP_TG_CONTROL_DISPEN_POS | \ |
38 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ | 40 | NV_PRAMDAC_FP_TG_CONTROL_HSYNC_POS | \ |
39 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) | 41 | NV_PRAMDAC_FP_TG_CONTROL_VSYNC_POS) |
@@ -144,6 +146,36 @@ void nv04_dfp_update_fp_control(struct drm_encoder *encoder, int mode) | |||
144 | } | 146 | } |
145 | } | 147 | } |
146 | 148 | ||
149 | static struct drm_encoder *get_tmds_slave(struct drm_encoder *encoder) | ||
150 | { | ||
151 | struct drm_device *dev = encoder->dev; | ||
152 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
153 | struct drm_encoder *slave; | ||
154 | |||
155 | if (dcb->type != OUTPUT_TMDS || dcb->location == DCB_LOC_ON_CHIP) | ||
156 | return NULL; | ||
157 | |||
158 | /* Some BIOSes (e.g. the one in a Quadro FX1000) report several | ||
159 | * TMDS transmitters at the same I2C address, in the same I2C | ||
160 | * bus. This can still work because in that case one of them is | ||
161 | * always hard-wired to a reasonable configuration using straps, | ||
162 | * and the other one needs to be programmed. | ||
163 | * | ||
164 | * I don't think there's a way to know which is which, even the | ||
165 | * blob programs the one exposed via I2C for *both* heads, so | ||
166 | * let's do the same. | ||
167 | */ | ||
168 | list_for_each_entry(slave, &dev->mode_config.encoder_list, head) { | ||
169 | struct dcb_entry *slave_dcb = nouveau_encoder(slave)->dcb; | ||
170 | |||
171 | if (slave_dcb->type == OUTPUT_TMDS && get_slave_funcs(slave) && | ||
172 | slave_dcb->tmdsconf.slave_addr == dcb->tmdsconf.slave_addr) | ||
173 | return slave; | ||
174 | } | ||
175 | |||
176 | return NULL; | ||
177 | } | ||
178 | |||
147 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, | 179 | static bool nv04_dfp_mode_fixup(struct drm_encoder *encoder, |
148 | struct drm_display_mode *mode, | 180 | struct drm_display_mode *mode, |
149 | struct drm_display_mode *adjusted_mode) | 181 | struct drm_display_mode *adjusted_mode) |
@@ -429,6 +461,11 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) | |||
429 | else | 461 | else |
430 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); | 462 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_TEST_CONTROL + nv04_dac_output_offset(encoder), 0x00100000); |
431 | 463 | ||
464 | /* Init external transmitters */ | ||
465 | if (get_tmds_slave(encoder)) | ||
466 | get_slave_funcs(get_tmds_slave(encoder))->mode_set( | ||
467 | encoder, &nv_encoder->mode, &nv_encoder->mode); | ||
468 | |||
432 | helper->dpms(encoder, DRM_MODE_DPMS_ON); | 469 | helper->dpms(encoder, DRM_MODE_DPMS_ON); |
433 | 470 | ||
434 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", | 471 | NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", |
@@ -550,10 +587,42 @@ static void nv04_dfp_destroy(struct drm_encoder *encoder) | |||
550 | 587 | ||
551 | NV_DEBUG_KMS(encoder->dev, "\n"); | 588 | NV_DEBUG_KMS(encoder->dev, "\n"); |
552 | 589 | ||
590 | if (get_slave_funcs(encoder)) | ||
591 | get_slave_funcs(encoder)->destroy(encoder); | ||
592 | |||
553 | drm_encoder_cleanup(encoder); | 593 | drm_encoder_cleanup(encoder); |
554 | kfree(nv_encoder); | 594 | kfree(nv_encoder); |
555 | } | 595 | } |
556 | 596 | ||
597 | static void nv04_tmds_slave_init(struct drm_encoder *encoder) | ||
598 | { | ||
599 | struct drm_device *dev = encoder->dev; | ||
600 | struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; | ||
601 | struct nouveau_i2c_chan *i2c = nouveau_i2c_find(dev, 2); | ||
602 | struct i2c_board_info info[] = { | ||
603 | { | ||
604 | .type = "sil164", | ||
605 | .addr = (dcb->tmdsconf.slave_addr == 0x7 ? 0x3a : 0x38), | ||
606 | .platform_data = &(struct sil164_encoder_params) { | ||
607 | SIL164_INPUT_EDGE_RISING | ||
608 | } | ||
609 | }, | ||
610 | { } | ||
611 | }; | ||
612 | int type; | ||
613 | |||
614 | if (!nv_gf4_disp_arch(dev) || !i2c || | ||
615 | get_tmds_slave(encoder)) | ||
616 | return; | ||
617 | |||
618 | type = nouveau_i2c_identify(dev, "TMDS transmitter", info, 2); | ||
619 | if (type < 0) | ||
620 | return; | ||
621 | |||
622 | drm_i2c_encoder_init(dev, to_encoder_slave(encoder), | ||
623 | &i2c->adapter, &info[type]); | ||
624 | } | ||
625 | |||
557 | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { | 626 | static const struct drm_encoder_helper_funcs nv04_lvds_helper_funcs = { |
558 | .dpms = nv04_lvds_dpms, | 627 | .dpms = nv04_lvds_dpms, |
559 | .save = nv04_dfp_save, | 628 | .save = nv04_dfp_save, |
@@ -616,6 +685,10 @@ nv04_dfp_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
616 | encoder->possible_crtcs = entry->heads; | 685 | encoder->possible_crtcs = entry->heads; |
617 | encoder->possible_clones = 0; | 686 | encoder->possible_clones = 0; |
618 | 687 | ||
688 | if (entry->type == OUTPUT_TMDS && | ||
689 | entry->location != DCB_LOC_ON_CHIP) | ||
690 | nv04_tmds_slave_init(encoder); | ||
691 | |||
619 | drm_mode_connector_attach_encoder(connector, encoder); | 692 | drm_mode_connector_attach_encoder(connector, encoder); |
620 | return 0; | 693 | return 0; |
621 | } | 694 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 94e299cef0b2..0b5d012d7c28 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c | |||
@@ -89,7 +89,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) | |||
89 | 89 | ||
90 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); | 90 | NVWriteRAMDAC(dev, 0, NV_PRAMDAC_PLL_COEFF_SELECT, state->pllsel); |
91 | 91 | ||
92 | to_encoder_slave(encoder)->slave_funcs->dpms(encoder, mode); | 92 | get_slave_funcs(encoder)->dpms(encoder, mode); |
93 | } | 93 | } |
94 | 94 | ||
95 | static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) | 95 | static void nv04_tv_bind(struct drm_device *dev, int head, bool bind) |
@@ -152,7 +152,7 @@ static void nv04_tv_mode_set(struct drm_encoder *encoder, | |||
152 | regp->tv_vskew = 1; | 152 | regp->tv_vskew = 1; |
153 | regp->tv_vsync_delay = 1; | 153 | regp->tv_vsync_delay = 1; |
154 | 154 | ||
155 | to_encoder_slave(encoder)->slave_funcs->mode_set(encoder, mode, adjusted_mode); | 155 | get_slave_funcs(encoder)->mode_set(encoder, mode, adjusted_mode); |
156 | } | 156 | } |
157 | 157 | ||
158 | static void nv04_tv_commit(struct drm_encoder *encoder) | 158 | static void nv04_tv_commit(struct drm_encoder *encoder) |
@@ -171,8 +171,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) | |||
171 | 171 | ||
172 | static void nv04_tv_destroy(struct drm_encoder *encoder) | 172 | static void nv04_tv_destroy(struct drm_encoder *encoder) |
173 | { | 173 | { |
174 | to_encoder_slave(encoder)->slave_funcs->destroy(encoder); | 174 | get_slave_funcs(encoder)->destroy(encoder); |
175 | |||
176 | drm_encoder_cleanup(encoder); | 175 | drm_encoder_cleanup(encoder); |
177 | 176 | ||
178 | kfree(encoder->helper_private); | 177 | kfree(encoder->helper_private); |
@@ -229,7 +228,7 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
229 | goto fail_cleanup; | 228 | goto fail_cleanup; |
230 | 229 | ||
231 | /* Fill the function pointers */ | 230 | /* Fill the function pointers */ |
232 | sfuncs = to_encoder_slave(encoder)->slave_funcs; | 231 | sfuncs = get_slave_funcs(encoder); |
233 | 232 | ||
234 | *hfuncs = (struct drm_encoder_helper_funcs) { | 233 | *hfuncs = (struct drm_encoder_helper_funcs) { |
235 | .dpms = nv04_tv_dpms, | 234 | .dpms = nv04_tv_dpms, |
@@ -243,7 +242,6 @@ nv04_tv_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
243 | }; | 242 | }; |
244 | 243 | ||
245 | /* Attach it to the specified connector. */ | 244 | /* Attach it to the specified connector. */ |
246 | sfuncs->set_config(encoder, nv04_tv_encoder_info[type].platform_data); | ||
247 | sfuncs->create_resources(encoder, connector); | 245 | sfuncs->create_resources(encoder, connector); |
248 | drm_mode_connector_attach_encoder(connector, encoder); | 246 | drm_mode_connector_attach_encoder(connector, encoder); |
249 | 247 | ||
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index fcf2cdd19493..b2f6a57c0cc5 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
@@ -43,51 +43,51 @@ struct pipe_state { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static int nv10_graph_ctx_regs[] = { | 45 | static int nv10_graph_ctx_regs[] = { |
46 | NV10_PGRAPH_CTX_SWITCH1, | 46 | NV10_PGRAPH_CTX_SWITCH(0), |
47 | NV10_PGRAPH_CTX_SWITCH2, | 47 | NV10_PGRAPH_CTX_SWITCH(1), |
48 | NV10_PGRAPH_CTX_SWITCH3, | 48 | NV10_PGRAPH_CTX_SWITCH(2), |
49 | NV10_PGRAPH_CTX_SWITCH4, | 49 | NV10_PGRAPH_CTX_SWITCH(3), |
50 | NV10_PGRAPH_CTX_SWITCH5, | 50 | NV10_PGRAPH_CTX_SWITCH(4), |
51 | NV10_PGRAPH_CTX_CACHE1, /* 8 values from 0x400160 to 0x40017c */ | 51 | NV10_PGRAPH_CTX_CACHE(0, 0), |
52 | NV10_PGRAPH_CTX_CACHE2, /* 8 values from 0x400180 to 0x40019c */ | 52 | NV10_PGRAPH_CTX_CACHE(0, 1), |
53 | NV10_PGRAPH_CTX_CACHE3, /* 8 values from 0x4001a0 to 0x4001bc */ | 53 | NV10_PGRAPH_CTX_CACHE(0, 2), |
54 | NV10_PGRAPH_CTX_CACHE4, /* 8 values from 0x4001c0 to 0x4001dc */ | 54 | NV10_PGRAPH_CTX_CACHE(0, 3), |
55 | NV10_PGRAPH_CTX_CACHE5, /* 8 values from 0x4001e0 to 0x4001fc */ | 55 | NV10_PGRAPH_CTX_CACHE(0, 4), |
56 | 0x00400164, | 56 | NV10_PGRAPH_CTX_CACHE(1, 0), |
57 | 0x00400184, | 57 | NV10_PGRAPH_CTX_CACHE(1, 1), |
58 | 0x004001a4, | 58 | NV10_PGRAPH_CTX_CACHE(1, 2), |
59 | 0x004001c4, | 59 | NV10_PGRAPH_CTX_CACHE(1, 3), |
60 | 0x004001e4, | 60 | NV10_PGRAPH_CTX_CACHE(1, 4), |
61 | 0x00400168, | 61 | NV10_PGRAPH_CTX_CACHE(2, 0), |
62 | 0x00400188, | 62 | NV10_PGRAPH_CTX_CACHE(2, 1), |
63 | 0x004001a8, | 63 | NV10_PGRAPH_CTX_CACHE(2, 2), |
64 | 0x004001c8, | 64 | NV10_PGRAPH_CTX_CACHE(2, 3), |
65 | 0x004001e8, | 65 | NV10_PGRAPH_CTX_CACHE(2, 4), |
66 | 0x0040016c, | 66 | NV10_PGRAPH_CTX_CACHE(3, 0), |
67 | 0x0040018c, | 67 | NV10_PGRAPH_CTX_CACHE(3, 1), |
68 | 0x004001ac, | 68 | NV10_PGRAPH_CTX_CACHE(3, 2), |
69 | 0x004001cc, | 69 | NV10_PGRAPH_CTX_CACHE(3, 3), |
70 | 0x004001ec, | 70 | NV10_PGRAPH_CTX_CACHE(3, 4), |
71 | 0x00400170, | 71 | NV10_PGRAPH_CTX_CACHE(4, 0), |
72 | 0x00400190, | 72 | NV10_PGRAPH_CTX_CACHE(4, 1), |
73 | 0x004001b0, | 73 | NV10_PGRAPH_CTX_CACHE(4, 2), |
74 | 0x004001d0, | 74 | NV10_PGRAPH_CTX_CACHE(4, 3), |
75 | 0x004001f0, | 75 | NV10_PGRAPH_CTX_CACHE(4, 4), |
76 | 0x00400174, | 76 | NV10_PGRAPH_CTX_CACHE(5, 0), |
77 | 0x00400194, | 77 | NV10_PGRAPH_CTX_CACHE(5, 1), |
78 | 0x004001b4, | 78 | NV10_PGRAPH_CTX_CACHE(5, 2), |
79 | 0x004001d4, | 79 | NV10_PGRAPH_CTX_CACHE(5, 3), |
80 | 0x004001f4, | 80 | NV10_PGRAPH_CTX_CACHE(5, 4), |
81 | 0x00400178, | 81 | NV10_PGRAPH_CTX_CACHE(6, 0), |
82 | 0x00400198, | 82 | NV10_PGRAPH_CTX_CACHE(6, 1), |
83 | 0x004001b8, | 83 | NV10_PGRAPH_CTX_CACHE(6, 2), |
84 | 0x004001d8, | 84 | NV10_PGRAPH_CTX_CACHE(6, 3), |
85 | 0x004001f8, | 85 | NV10_PGRAPH_CTX_CACHE(6, 4), |
86 | 0x0040017c, | 86 | NV10_PGRAPH_CTX_CACHE(7, 0), |
87 | 0x0040019c, | 87 | NV10_PGRAPH_CTX_CACHE(7, 1), |
88 | 0x004001bc, | 88 | NV10_PGRAPH_CTX_CACHE(7, 2), |
89 | 0x004001dc, | 89 | NV10_PGRAPH_CTX_CACHE(7, 3), |
90 | 0x004001fc, | 90 | NV10_PGRAPH_CTX_CACHE(7, 4), |
91 | NV10_PGRAPH_CTX_USER, | 91 | NV10_PGRAPH_CTX_USER, |
92 | NV04_PGRAPH_DMA_START_0, | 92 | NV04_PGRAPH_DMA_START_0, |
93 | NV04_PGRAPH_DMA_START_1, | 93 | NV04_PGRAPH_DMA_START_1, |
@@ -653,6 +653,78 @@ static int nv17_graph_ctx_regs_find_offset(struct drm_device *dev, int reg) | |||
653 | return -1; | 653 | return -1; |
654 | } | 654 | } |
655 | 655 | ||
656 | static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, | ||
657 | uint32_t inst) | ||
658 | { | ||
659 | struct drm_device *dev = chan->dev; | ||
660 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
661 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
662 | uint32_t st2, st2_dl, st2_dh, fifo_ptr, fifo[0x60/4]; | ||
663 | uint32_t ctx_user, ctx_switch[5]; | ||
664 | int i, subchan = -1; | ||
665 | |||
666 | /* NV10TCL_DMA_VTXBUF (method 0x18c) modifies hidden state | ||
667 | * that cannot be restored via MMIO. Do it through the FIFO | ||
668 | * instead. | ||
669 | */ | ||
670 | |||
671 | /* Look for a celsius object */ | ||
672 | for (i = 0; i < 8; i++) { | ||
673 | int class = nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(i, 0)) & 0xfff; | ||
674 | |||
675 | if (class == 0x56 || class == 0x96 || class == 0x99) { | ||
676 | subchan = i; | ||
677 | break; | ||
678 | } | ||
679 | } | ||
680 | |||
681 | if (subchan < 0 || !inst) | ||
682 | return; | ||
683 | |||
684 | /* Save the current ctx object */ | ||
685 | ctx_user = nv_rd32(dev, NV10_PGRAPH_CTX_USER); | ||
686 | for (i = 0; i < 5; i++) | ||
687 | ctx_switch[i] = nv_rd32(dev, NV10_PGRAPH_CTX_SWITCH(i)); | ||
688 | |||
689 | /* Save the FIFO state */ | ||
690 | st2 = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2); | ||
691 | st2_dl = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DL); | ||
692 | st2_dh = nv_rd32(dev, NV10_PGRAPH_FFINTFC_ST2_DH); | ||
693 | fifo_ptr = nv_rd32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR); | ||
694 | |||
695 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | ||
696 | fifo[i] = nv_rd32(dev, 0x4007a0 + 4 * i); | ||
697 | |||
698 | /* Switch to the celsius subchannel */ | ||
699 | for (i = 0; i < 5; i++) | ||
700 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), | ||
701 | nv_rd32(dev, NV10_PGRAPH_CTX_CACHE(subchan, i))); | ||
702 | nv_mask(dev, NV10_PGRAPH_CTX_USER, 0xe000, subchan << 13); | ||
703 | |||
704 | /* Inject NV10TCL_DMA_VTXBUF */ | ||
705 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, 0); | ||
706 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, | ||
707 | 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); | ||
708 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); | ||
709 | nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); | ||
710 | pgraph->fifo_access(dev, true); | ||
711 | pgraph->fifo_access(dev, false); | ||
712 | |||
713 | /* Restore the FIFO state */ | ||
714 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | ||
715 | nv_wr32(dev, 0x4007a0 + 4 * i, fifo[i]); | ||
716 | |||
717 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_FIFO_PTR, fifo_ptr); | ||
718 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2, st2); | ||
719 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, st2_dl); | ||
720 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DH, st2_dh); | ||
721 | |||
722 | /* Restore the current ctx object */ | ||
723 | for (i = 0; i < 5; i++) | ||
724 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(i), ctx_switch[i]); | ||
725 | nv_wr32(dev, NV10_PGRAPH_CTX_USER, ctx_user); | ||
726 | } | ||
727 | |||
656 | int nv10_graph_load_context(struct nouveau_channel *chan) | 728 | int nv10_graph_load_context(struct nouveau_channel *chan) |
657 | { | 729 | { |
658 | struct drm_device *dev = chan->dev; | 730 | struct drm_device *dev = chan->dev; |
@@ -670,6 +742,8 @@ int nv10_graph_load_context(struct nouveau_channel *chan) | |||
670 | } | 742 | } |
671 | 743 | ||
672 | nv10_graph_load_pipe(chan); | 744 | nv10_graph_load_pipe(chan); |
745 | nv10_graph_load_dma_vtxbuf(chan, (nv_rd32(dev, NV10_PGRAPH_GLOBALSTATE1) | ||
746 | & 0xffff)); | ||
673 | 747 | ||
674 | nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); | 748 | nv_wr32(dev, NV10_PGRAPH_CTX_CONTROL, 0x10010100); |
675 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); | 749 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER); |
@@ -856,11 +930,12 @@ int nv10_graph_init(struct drm_device *dev) | |||
856 | for (i = 0; i < NV10_PFB_TILE__SIZE; i++) | 930 | for (i = 0; i < NV10_PFB_TILE__SIZE; i++) |
857 | nv10_graph_set_region_tiling(dev, i, 0, 0, 0); | 931 | nv10_graph_set_region_tiling(dev, i, 0, 0, 0); |
858 | 932 | ||
859 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH1, 0x00000000); | 933 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(0), 0x00000000); |
860 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH2, 0x00000000); | 934 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(1), 0x00000000); |
861 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH3, 0x00000000); | 935 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(2), 0x00000000); |
862 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH4, 0x00000000); | 936 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(3), 0x00000000); |
863 | nv_wr32(dev, NV10_PGRAPH_STATE , 0xFFFFFFFF); | 937 | nv_wr32(dev, NV10_PGRAPH_CTX_SWITCH(4), 0x00000000); |
938 | nv_wr32(dev, NV10_PGRAPH_STATE, 0xFFFFFFFF); | ||
864 | 939 | ||
865 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; | 940 | tmp = nv_rd32(dev, NV10_PGRAPH_CTX_USER) & 0x00ffffff; |
866 | tmp |= (dev_priv->engine.fifo.channels - 1) << 24; | 941 | tmp |= (dev_priv->engine.fifo.channels - 1) << 24; |
diff --git a/drivers/gpu/drm/nouveau/nv30_fb.c b/drivers/gpu/drm/nouveau/nv30_fb.c index 9d35c8b3b839..4a3f2f095128 100644 --- a/drivers/gpu/drm/nouveau/nv30_fb.c +++ b/drivers/gpu/drm/nouveau/nv30_fb.c | |||
@@ -30,15 +30,25 @@ | |||
30 | #include "nouveau_drm.h" | 30 | #include "nouveau_drm.h" |
31 | 31 | ||
32 | static int | 32 | static int |
33 | calc_ref(int b, int l, int i) | 33 | calc_bias(struct drm_device *dev, int k, int i, int j) |
34 | { | ||
35 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
36 | int b = (dev_priv->chipset > 0x30 ? | ||
37 | nv_rd32(dev, 0x122c + 0x10 * k + 0x4 * j) >> (4 * (i ^ 1)) : | ||
38 | 0) & 0xf; | ||
39 | |||
40 | return 2 * (b & 0x8 ? b - 0x10 : b); | ||
41 | } | ||
42 | |||
43 | static int | ||
44 | calc_ref(struct drm_device *dev, int l, int k, int i) | ||
34 | { | 45 | { |
35 | int j, x = 0; | 46 | int j, x = 0; |
36 | 47 | ||
37 | for (j = 0; j < 4; j++) { | 48 | for (j = 0; j < 4; j++) { |
38 | int n = (b >> (8 * j) & 0xf); | 49 | int m = (l >> (8 * i) & 0xff) + calc_bias(dev, k, i, j); |
39 | int m = (l >> (8 * i) & 0xff) + 2 * (n & 0x8 ? n - 0x10 : n); | ||
40 | 50 | ||
41 | x |= (0x80 | (m & 0x1f)) << (8 * j); | 51 | x |= (0x80 | clamp(m, 0, 0x1f)) << (8 * j); |
42 | } | 52 | } |
43 | 53 | ||
44 | return x; | 54 | return x; |
@@ -63,18 +73,16 @@ nv30_fb_init(struct drm_device *dev) | |||
63 | dev_priv->chipset == 0x35) { | 73 | dev_priv->chipset == 0x35) { |
64 | /* Related to ROP count */ | 74 | /* Related to ROP count */ |
65 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); | 75 | int n = (dev_priv->chipset == 0x31 ? 2 : 4); |
66 | int b = (dev_priv->chipset > 0x30 ? | ||
67 | nv_rd32(dev, 0x122c) & 0xf : 0); | ||
68 | int l = nv_rd32(dev, 0x1003d0); | 76 | int l = nv_rd32(dev, 0x1003d0); |
69 | 77 | ||
70 | for (i = 0; i < n; i++) { | 78 | for (i = 0; i < n; i++) { |
71 | for (j = 0; j < 3; j++) | 79 | for (j = 0; j < 3; j++) |
72 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, | 80 | nv_wr32(dev, 0x10037c + 0xc * i + 0x4 * j, |
73 | calc_ref(b, l, j)); | 81 | calc_ref(dev, l, 0, j)); |
74 | 82 | ||
75 | for (j = 0; j < 2; j++) | 83 | for (j = 0; j < 2; j++) |
76 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, | 84 | nv_wr32(dev, 0x1003ac + 0x8 * i + 0x4 * j, |
77 | calc_ref(b, l, j)); | 85 | calc_ref(dev, l, 1, j)); |
78 | } | 86 | } |
79 | } | 87 | } |
80 | 88 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 5d11ea101666..bfd4ca2fe7ef 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -264,11 +264,16 @@ nv50_crtc_set_scale(struct nouveau_crtc *nv_crtc, int scaling_mode, bool update) | |||
264 | int | 264 | int |
265 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | 265 | nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) |
266 | { | 266 | { |
267 | uint32_t reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | 267 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
268 | struct pll_lims pll; | 268 | struct pll_lims pll; |
269 | uint32_t reg1, reg2; | 269 | uint32_t reg, reg1, reg2; |
270 | int ret, N1, M1, N2, M2, P; | 270 | int ret, N1, M1, N2, M2, P; |
271 | 271 | ||
272 | if (dev_priv->chipset < NV_C0) | ||
273 | reg = NV50_PDISPLAY_CRTC_CLK_CTRL1(head); | ||
274 | else | ||
275 | reg = 0x614140 + (head * 0x800); | ||
276 | |||
272 | ret = get_pll_limits(dev, reg, &pll); | 277 | ret = get_pll_limits(dev, reg, &pll); |
273 | if (ret) | 278 | if (ret) |
274 | return ret; | 279 | return ret; |
@@ -286,7 +291,8 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
286 | nv_wr32(dev, reg, 0x10000611); | 291 | nv_wr32(dev, reg, 0x10000611); |
287 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); | 292 | nv_wr32(dev, reg + 4, reg1 | (M1 << 16) | N1); |
288 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); | 293 | nv_wr32(dev, reg + 8, reg2 | (P << 28) | (M2 << 16) | N2); |
289 | } else { | 294 | } else |
295 | if (dev_priv->chipset < NV_C0) { | ||
290 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | 296 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); |
291 | if (ret <= 0) | 297 | if (ret <= 0) |
292 | return 0; | 298 | return 0; |
@@ -298,6 +304,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) | |||
298 | nv_wr32(dev, reg, 0x50000610); | 304 | nv_wr32(dev, reg, 0x50000610); |
299 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); | 305 | nv_wr32(dev, reg + 4, reg1 | (P << 16) | (M1 << 8) | N1); |
300 | nv_wr32(dev, reg + 8, N2); | 306 | nv_wr32(dev, reg + 8, N2); |
307 | } else { | ||
308 | ret = nv50_calc_pll2(dev, &pll, pclk, &N1, &N2, &M1, &P); | ||
309 | if (ret <= 0) | ||
310 | return 0; | ||
311 | |||
312 | NV_DEBUG(dev, "pclk %d out %d N %d fN 0x%04x M %d P %d\n", | ||
313 | pclk, ret, N1, N2, M1, P); | ||
314 | |||
315 | nv_mask(dev, reg + 0x0c, 0x00000000, 0x00000100); | ||
316 | nv_wr32(dev, reg + 0x04, (P << 16) | (N1 << 8) | M1); | ||
317 | nv_wr32(dev, reg + 0x10, N2 << 16); | ||
301 | } | 318 | } |
302 | 319 | ||
303 | return 0; | 320 | return 0; |
@@ -348,7 +365,7 @@ nv50_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv, | |||
348 | 365 | ||
349 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); | 366 | gem = drm_gem_object_lookup(dev, file_priv, buffer_handle); |
350 | if (!gem) | 367 | if (!gem) |
351 | return -EINVAL; | 368 | return -ENOENT; |
352 | cursor = nouveau_gem_object(gem); | 369 | cursor = nouveau_gem_object(gem); |
353 | 370 | ||
354 | ret = nouveau_bo_map(cursor); | 371 | ret = nouveau_bo_map(cursor); |
@@ -381,15 +398,12 @@ nv50_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | |||
381 | 398 | ||
382 | static void | 399 | static void |
383 | nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, | 400 | nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, |
384 | uint32_t size) | 401 | uint32_t start, uint32_t size) |
385 | { | 402 | { |
403 | int end = (start + size > 256) ? 256 : start + size, i; | ||
386 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 404 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
387 | int i; | ||
388 | |||
389 | if (size != 256) | ||
390 | return; | ||
391 | 405 | ||
392 | for (i = 0; i < 256; i++) { | 406 | for (i = start; i < end; i++) { |
393 | nv_crtc->lut.r[i] = r[i]; | 407 | nv_crtc->lut.r[i] = r[i]; |
394 | nv_crtc->lut.g[i] = g[i]; | 408 | nv_crtc->lut.g[i] = g[i]; |
395 | nv_crtc->lut.b[i] = b[i]; | 409 | nv_crtc->lut.b[i] = b[i]; |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f13ad0de9c8f..612fa6d6a0cb 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -76,7 +76,10 @@ nv50_evo_dmaobj_new(struct nouveau_channel *evo, uint32_t class, uint32_t name, | |||
76 | nv_wo32(dev, obj, 2, offset); | 76 | nv_wo32(dev, obj, 2, offset); |
77 | nv_wo32(dev, obj, 3, 0x00000000); | 77 | nv_wo32(dev, obj, 3, 0x00000000); |
78 | nv_wo32(dev, obj, 4, 0x00000000); | 78 | nv_wo32(dev, obj, 4, 0x00000000); |
79 | nv_wo32(dev, obj, 5, 0x00010000); | 79 | if (dev_priv->card_type < NV_C0) |
80 | nv_wo32(dev, obj, 5, 0x00010000); | ||
81 | else | ||
82 | nv_wo32(dev, obj, 5, 0x00020000); | ||
80 | dev_priv->engine.instmem.flush(dev); | 83 | dev_priv->engine.instmem.flush(dev); |
81 | 84 | ||
82 | return 0; | 85 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nvc0_fb.c b/drivers/gpu/drm/nouveau/nvc0_fb.c new file mode 100644 index 000000000000..26a996025dd2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_fb.c | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | int | ||
30 | nvc0_fb_init(struct drm_device *dev) | ||
31 | { | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | void | ||
36 | nvc0_fb_takedown(struct drm_device *dev) | ||
37 | { | ||
38 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvc0_fifo.c b/drivers/gpu/drm/nouveau/nvc0_fifo.c new file mode 100644 index 000000000000..d64375871979 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_fifo.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | void | ||
30 | nvc0_fifo_disable(struct drm_device *dev) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | void | ||
35 | nvc0_fifo_enable(struct drm_device *dev) | ||
36 | { | ||
37 | } | ||
38 | |||
39 | bool | ||
40 | nvc0_fifo_reassign(struct drm_device *dev, bool enable) | ||
41 | { | ||
42 | return false; | ||
43 | } | ||
44 | |||
45 | bool | ||
46 | nvc0_fifo_cache_flush(struct drm_device *dev) | ||
47 | { | ||
48 | return true; | ||
49 | } | ||
50 | |||
51 | bool | ||
52 | nvc0_fifo_cache_pull(struct drm_device *dev, bool enable) | ||
53 | { | ||
54 | return false; | ||
55 | } | ||
56 | |||
57 | int | ||
58 | nvc0_fifo_channel_id(struct drm_device *dev) | ||
59 | { | ||
60 | return 127; | ||
61 | } | ||
62 | |||
63 | int | ||
64 | nvc0_fifo_create_context(struct nouveau_channel *chan) | ||
65 | { | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | void | ||
70 | nvc0_fifo_destroy_context(struct nouveau_channel *chan) | ||
71 | { | ||
72 | } | ||
73 | |||
74 | int | ||
75 | nvc0_fifo_load_context(struct nouveau_channel *chan) | ||
76 | { | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | int | ||
81 | nvc0_fifo_unload_context(struct drm_device *dev) | ||
82 | { | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | void | ||
87 | nvc0_fifo_takedown(struct drm_device *dev) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | int | ||
92 | nvc0_fifo_init(struct drm_device *dev) | ||
93 | { | ||
94 | return 0; | ||
95 | } | ||
96 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c new file mode 100644 index 000000000000..717a5177a8d8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | void | ||
30 | nvc0_graph_fifo_access(struct drm_device *dev, bool enabled) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | struct nouveau_channel * | ||
35 | nvc0_graph_channel(struct drm_device *dev) | ||
36 | { | ||
37 | return NULL; | ||
38 | } | ||
39 | |||
40 | int | ||
41 | nvc0_graph_create_context(struct nouveau_channel *chan) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | void | ||
47 | nvc0_graph_destroy_context(struct nouveau_channel *chan) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | int | ||
52 | nvc0_graph_load_context(struct nouveau_channel *chan) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int | ||
58 | nvc0_graph_unload_context(struct drm_device *dev) | ||
59 | { | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | void | ||
64 | nvc0_graph_takedown(struct drm_device *dev) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | int | ||
69 | nvc0_graph_init(struct drm_device *dev) | ||
70 | { | ||
71 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
72 | dev_priv->engine.graph.accel_blocked = true; | ||
73 | return 0; | ||
74 | } | ||
75 | |||
diff --git a/drivers/gpu/drm/nouveau/nvc0_instmem.c b/drivers/gpu/drm/nouveau/nvc0_instmem.c new file mode 100644 index 000000000000..3ab3cdc42173 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvc0_instmem.c | |||
@@ -0,0 +1,232 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Red Hat Inc. | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice shall be included in | ||
12 | * all copies or substantial portions of the Software. | ||
13 | * | ||
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
21 | * | ||
22 | * Authors: Ben Skeggs | ||
23 | */ | ||
24 | |||
25 | #include "drmP.h" | ||
26 | |||
27 | #include "nouveau_drv.h" | ||
28 | |||
29 | int | ||
30 | nvc0_instmem_populate(struct drm_device *dev, struct nouveau_gpuobj *gpuobj, | ||
31 | uint32_t *size) | ||
32 | { | ||
33 | int ret; | ||
34 | |||
35 | *size = ALIGN(*size, 4096); | ||
36 | if (*size == 0) | ||
37 | return -EINVAL; | ||
38 | |||
39 | ret = nouveau_bo_new(dev, NULL, *size, 0, TTM_PL_FLAG_VRAM, 0, 0x0000, | ||
40 | true, false, &gpuobj->im_backing); | ||
41 | if (ret) { | ||
42 | NV_ERROR(dev, "error getting PRAMIN backing pages: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | |||
46 | ret = nouveau_bo_pin(gpuobj->im_backing, TTM_PL_FLAG_VRAM); | ||
47 | if (ret) { | ||
48 | NV_ERROR(dev, "error pinning PRAMIN backing VRAM: %d\n", ret); | ||
49 | nouveau_bo_ref(NULL, &gpuobj->im_backing); | ||
50 | return ret; | ||
51 | } | ||
52 | |||
53 | gpuobj->im_backing_start = gpuobj->im_backing->bo.mem.mm_node->start; | ||
54 | gpuobj->im_backing_start <<= PAGE_SHIFT; | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | nvc0_instmem_clear(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
60 | { | ||
61 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
62 | |||
63 | if (gpuobj && gpuobj->im_backing) { | ||
64 | if (gpuobj->im_bound) | ||
65 | dev_priv->engine.instmem.unbind(dev, gpuobj); | ||
66 | nouveau_bo_unpin(gpuobj->im_backing); | ||
67 | nouveau_bo_ref(NULL, &gpuobj->im_backing); | ||
68 | gpuobj->im_backing = NULL; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | int | ||
73 | nvc0_instmem_bind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
74 | { | ||
75 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
76 | uint32_t pte, pte_end; | ||
77 | uint64_t vram; | ||
78 | |||
79 | if (!gpuobj->im_backing || !gpuobj->im_pramin || gpuobj->im_bound) | ||
80 | return -EINVAL; | ||
81 | |||
82 | NV_DEBUG(dev, "st=0x%lx sz=0x%lx\n", | ||
83 | gpuobj->im_pramin->start, gpuobj->im_pramin->size); | ||
84 | |||
85 | pte = gpuobj->im_pramin->start >> 12; | ||
86 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | ||
87 | vram = gpuobj->im_backing_start; | ||
88 | |||
89 | NV_DEBUG(dev, "pramin=0x%lx, pte=%d, pte_end=%d\n", | ||
90 | gpuobj->im_pramin->start, pte, pte_end); | ||
91 | NV_DEBUG(dev, "first vram page: 0x%08x\n", gpuobj->im_backing_start); | ||
92 | |||
93 | while (pte < pte_end) { | ||
94 | nv_wr32(dev, 0x702000 + (pte * 8), (vram >> 8) | 1); | ||
95 | nv_wr32(dev, 0x702004 + (pte * 8), 0); | ||
96 | vram += 4096; | ||
97 | pte++; | ||
98 | } | ||
99 | dev_priv->engine.instmem.flush(dev); | ||
100 | |||
101 | if (1) { | ||
102 | u32 chan = nv_rd32(dev, 0x1700) << 16; | ||
103 | nv_wr32(dev, 0x100cb8, (chan + 0x1000) >> 8); | ||
104 | nv_wr32(dev, 0x100cbc, 0x80000005); | ||
105 | } | ||
106 | |||
107 | gpuobj->im_bound = 1; | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int | ||
112 | nvc0_instmem_unbind(struct drm_device *dev, struct nouveau_gpuobj *gpuobj) | ||
113 | { | ||
114 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
115 | uint32_t pte, pte_end; | ||
116 | |||
117 | if (gpuobj->im_bound == 0) | ||
118 | return -EINVAL; | ||
119 | |||
120 | pte = gpuobj->im_pramin->start >> 12; | ||
121 | pte_end = (gpuobj->im_pramin->size >> 12) + pte; | ||
122 | while (pte < pte_end) { | ||
123 | nv_wr32(dev, 0x702000 + (pte * 8), 0); | ||
124 | nv_wr32(dev, 0x702004 + (pte * 8), 0); | ||
125 | pte++; | ||
126 | } | ||
127 | dev_priv->engine.instmem.flush(dev); | ||
128 | |||
129 | gpuobj->im_bound = 0; | ||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | void | ||
134 | nvc0_instmem_flush(struct drm_device *dev) | ||
135 | { | ||
136 | nv_wr32(dev, 0x070000, 1); | ||
137 | if (!nv_wait(0x070000, 0x00000002, 0x00000000)) | ||
138 | NV_ERROR(dev, "PRAMIN flush timeout\n"); | ||
139 | } | ||
140 | |||
141 | int | ||
142 | nvc0_instmem_suspend(struct drm_device *dev) | ||
143 | { | ||
144 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
145 | int i; | ||
146 | |||
147 | dev_priv->susres.ramin_copy = vmalloc(65536); | ||
148 | if (!dev_priv->susres.ramin_copy) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | for (i = 0x700000; i < 0x710000; i += 4) | ||
152 | dev_priv->susres.ramin_copy[i/4] = nv_rd32(dev, i); | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | void | ||
157 | nvc0_instmem_resume(struct drm_device *dev) | ||
158 | { | ||
159 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
160 | u64 chan; | ||
161 | int i; | ||
162 | |||
163 | chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
164 | nv_wr32(dev, 0x001700, chan >> 16); | ||
165 | |||
166 | for (i = 0x700000; i < 0x710000; i += 4) | ||
167 | nv_wr32(dev, i, dev_priv->susres.ramin_copy[i/4]); | ||
168 | vfree(dev_priv->susres.ramin_copy); | ||
169 | dev_priv->susres.ramin_copy = NULL; | ||
170 | |||
171 | nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); | ||
172 | } | ||
173 | |||
174 | int | ||
175 | nvc0_instmem_init(struct drm_device *dev) | ||
176 | { | ||
177 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
178 | u64 chan, pgt3, imem, lim3 = dev_priv->ramin_size - 1; | ||
179 | int ret, i; | ||
180 | |||
181 | dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024; | ||
182 | chan = dev_priv->vram_size - dev_priv->ramin_rsvd_vram; | ||
183 | imem = 4096 + 4096 + 32768; | ||
184 | |||
185 | nv_wr32(dev, 0x001700, chan >> 16); | ||
186 | |||
187 | /* channel setup */ | ||
188 | nv_wr32(dev, 0x700200, lower_32_bits(chan + 0x1000)); | ||
189 | nv_wr32(dev, 0x700204, upper_32_bits(chan + 0x1000)); | ||
190 | nv_wr32(dev, 0x700208, lower_32_bits(lim3)); | ||
191 | nv_wr32(dev, 0x70020c, upper_32_bits(lim3)); | ||
192 | |||
193 | /* point pgd -> pgt */ | ||
194 | nv_wr32(dev, 0x701000, 0); | ||
195 | nv_wr32(dev, 0x701004, ((chan + 0x2000) >> 8) | 1); | ||
196 | |||
197 | /* point pgt -> physical vram for channel */ | ||
198 | pgt3 = 0x2000; | ||
199 | for (i = 0; i < dev_priv->ramin_rsvd_vram; i += 4096, pgt3 += 8) { | ||
200 | nv_wr32(dev, 0x700000 + pgt3, ((chan + i) >> 8) | 1); | ||
201 | nv_wr32(dev, 0x700004 + pgt3, 0); | ||
202 | } | ||
203 | |||
204 | /* clear rest of pgt */ | ||
205 | for (; i < dev_priv->ramin_size; i += 4096, pgt3 += 8) { | ||
206 | nv_wr32(dev, 0x700000 + pgt3, 0); | ||
207 | nv_wr32(dev, 0x700004 + pgt3, 0); | ||
208 | } | ||
209 | |||
210 | /* point bar3 at the channel */ | ||
211 | nv_wr32(dev, 0x001714, 0xc0000000 | (chan >> 12)); | ||
212 | |||
213 | /* Global PRAMIN heap */ | ||
214 | ret = drm_mm_init(&dev_priv->ramin_heap, imem, | ||
215 | dev_priv->ramin_size - imem); | ||
216 | if (ret) { | ||
217 | NV_ERROR(dev, "Failed to init RAMIN heap\n"); | ||
218 | return -ENOMEM; | ||
219 | } | ||
220 | |||
221 | /*XXX: incorrect, but needed to make hash func "work" */ | ||
222 | dev_priv->ramht_offset = 0x10000; | ||
223 | dev_priv->ramht_bits = 9; | ||
224 | dev_priv->ramht_size = (1 << dev_priv->ramht_bits); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | void | ||
229 | nvc0_instmem_takedown(struct drm_device *dev) | ||
230 | { | ||
231 | } | ||
232 | |||