diff options
author | Dave Airlie <airlied@redhat.com> | 2015-11-03 00:42:59 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-11-03 00:42:59 -0500 |
commit | 1c431cb4615334fb81c0d1c0ede21aa4354c1187 (patch) | |
tree | 00ae8990f0b97e5842c11c73ec7a91505ffbcf54 /drivers/gpu | |
parent | b4590047966ba35a626f947c3fee2c4ed7081685 (diff) | |
parent | 79ef5dca5e5cd5a33662d64c927c1b9786d4edee (diff) |
Merge branch 'linux-4.4' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
- Vast improvements to gk20a instmem handling.
- Improved PGOB detection + GK107 support.
- Compatibility between old/new interfaces added, final missing piece to
finally enabling userspace to start using them.
- Kepler GDDR5 PLL stability improvements
- Support for non-GPIO (PWM) voltage controllers
- G8x/GT2xx memory clock improvements
- Misc other fixes
* 'linux-4.4' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (45 commits)
drm/nouveau: bump patchlevel to indicate availability of abi16/nvif interop
drm/nouveau/abi16: implement limited interoperability with usif/nvif
drm/nouveau/abi16: introduce locked variant of nouveau_abi16_get()
drm/nouveau/abi16: remove unused argument from nouveau_abi16_get()
drm/nouveau/pci: enable c800 magic for Medion Erazer X7827
drm/nouveau/pci: enable c800 magic for Lenovo Y510P
drm/nouveau/pll/gk104: fix PLL instability due to bad configuration with gddr5
drm/nouveau/clk/g84: Enable reclocking for GDDR3 G94-G200
drm/nouveau/bus/hwsq: Implement VBLANK waiting heuristic
drm/nouveau/fb/ramnv50: Script changes for G94 and up
drm/nouveau/fb/ramnv50: Deal with cards without timing entries
drm/nouveau/fb/ramnv50: Voltage GPIOs
drm/nouveau/fb/ramgt215: Restructure r111100 calculation for DDR2
drm/nouveau/fb/ramgt215: Change FBVDD/Q when BIOS asks for it
drm/nouveau/fb/ramgt215: Transform GPIO ramfuc method from FBVREF-specific to generic
drm/nouveau/bios/rammap: Identify DLLoff for >= GF100
drm/nouveau/pci: Handle 5-bit and 8-bit tag field
drm/nouveau/disp,pm: constify nvkm_object_func structures
drm/nouveau/gr: add FERMI_COMPUTE_B class to GF110+
drm/nouveau/gr: document mp error 0x10
...
Diffstat (limited to 'drivers/gpu')
73 files changed, 1312 insertions, 373 deletions
diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h index 3accc99d8e0b..9fcab67c8557 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/os.h +++ b/drivers/gpu/drm/nouveau/include/nvif/os.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/agp_backend.h> | 27 | #include <linux/agp_backend.h> |
28 | #include <linux/reset.h> | 28 | #include <linux/reset.h> |
29 | #include <linux/iommu.h> | 29 | #include <linux/iommu.h> |
30 | #include <linux/of_device.h> | ||
30 | 31 | ||
31 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
32 | 33 | ||
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h index 5aa2480da25f..16641cec18a2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <core/mm.h> | 4 | #include <core/mm.h> |
5 | 5 | ||
6 | struct nvkm_device_tegra { | 6 | struct nvkm_device_tegra { |
7 | const struct nvkm_device_tegra_func *func; | ||
7 | struct nvkm_device device; | 8 | struct nvkm_device device; |
8 | struct platform_device *pdev; | 9 | struct platform_device *pdev; |
9 | int irq; | 10 | int irq; |
@@ -28,7 +29,17 @@ struct nvkm_device_tegra { | |||
28 | int gpu_speedo; | 29 | int gpu_speedo; |
29 | }; | 30 | }; |
30 | 31 | ||
31 | int nvkm_device_tegra_new(struct platform_device *, | 32 | struct nvkm_device_tegra_func { |
33 | /* | ||
34 | * If an IOMMU is used, indicates which address bit will trigger a | ||
35 | * IOMMU translation when set (when this bit is not set, IOMMU is | ||
36 | * bypassed). A value of 0 means an IOMMU is never used. | ||
37 | */ | ||
38 | u8 iommu_bit; | ||
39 | }; | ||
40 | |||
41 | int nvkm_device_tegra_new(const struct nvkm_device_tegra_func *, | ||
42 | struct platform_device *, | ||
32 | const char *cfg, const char *dbg, | 43 | const char *cfg, const char *dbg, |
33 | bool detect, bool mmio, u64 subdev_mask, | 44 | bool detect, bool mmio, u64 subdev_mask, |
34 | struct nvkm_device **); | 45 | struct nvkm_device **); |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h index 33be260ddd38..a47d46dda704 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/gpio.h | |||
@@ -15,6 +15,7 @@ enum dcb_gpio_func_name { | |||
15 | DCB_GPIO_VID5 = 0x74, | 15 | DCB_GPIO_VID5 = 0x74, |
16 | DCB_GPIO_VID6 = 0x75, | 16 | DCB_GPIO_VID6 = 0x75, |
17 | DCB_GPIO_VID7 = 0x76, | 17 | DCB_GPIO_VID7 = 0x76, |
18 | DCB_GPIO_VID_PWM = 0x81, | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | #define DCB_GPIO_LOG_DIR 0x02 | 21 | #define DCB_GPIO_LOG_DIR 0x02 |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h index d606875c125a..3a643df6de04 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/pmu.h | |||
@@ -4,8 +4,6 @@ struct nvbios_pmuT { | |||
4 | }; | 4 | }; |
5 | 5 | ||
6 | u32 nvbios_pmuTe(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | 6 | u32 nvbios_pmuTe(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); |
7 | u32 nvbios_pmuTp(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
8 | struct nvbios_pmuT *); | ||
9 | 7 | ||
10 | struct nvbios_pmuE { | 8 | struct nvbios_pmuE { |
11 | u8 type; | 9 | u8 type; |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h index 3a9abd38aca8..dca6c060a24f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/ramcfg.h | |||
@@ -39,6 +39,7 @@ struct nvbios_ramcfg { | |||
39 | unsigned ramcfg_timing; | 39 | unsigned ramcfg_timing; |
40 | unsigned ramcfg_DLLoff; | 40 | unsigned ramcfg_DLLoff; |
41 | unsigned ramcfg_RON; | 41 | unsigned ramcfg_RON; |
42 | unsigned ramcfg_FBVDDQ; | ||
42 | union { | 43 | union { |
43 | struct { | 44 | struct { |
44 | unsigned ramcfg_00_03_01:1; | 45 | unsigned ramcfg_00_03_01:1; |
@@ -78,7 +79,6 @@ struct nvbios_ramcfg { | |||
78 | unsigned ramcfg_11_01_04:1; | 79 | unsigned ramcfg_11_01_04:1; |
79 | unsigned ramcfg_11_01_08:1; | 80 | unsigned ramcfg_11_01_08:1; |
80 | unsigned ramcfg_11_01_10:1; | 81 | unsigned ramcfg_11_01_10:1; |
81 | unsigned ramcfg_11_01_20:1; | ||
82 | unsigned ramcfg_11_01_40:1; | 82 | unsigned ramcfg_11_01_40:1; |
83 | unsigned ramcfg_11_01_80:1; | 83 | unsigned ramcfg_11_01_80:1; |
84 | unsigned ramcfg_11_02_03:2; | 84 | unsigned ramcfg_11_02_03:2; |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h index eb2de4b85bbd..b0df610cec2b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/volt.h | |||
@@ -1,11 +1,24 @@ | |||
1 | #ifndef __NVBIOS_VOLT_H__ | 1 | #ifndef __NVBIOS_VOLT_H__ |
2 | #define __NVBIOS_VOLT_H__ | 2 | #define __NVBIOS_VOLT_H__ |
3 | |||
4 | enum nvbios_volt_type { | ||
5 | NVBIOS_VOLT_GPIO = 0, | ||
6 | NVBIOS_VOLT_PWM, | ||
7 | }; | ||
8 | |||
3 | struct nvbios_volt { | 9 | struct nvbios_volt { |
4 | u8 vidmask; | 10 | enum nvbios_volt_type type; |
5 | u32 min; | 11 | u32 min; |
6 | u32 max; | 12 | u32 max; |
7 | u32 base; | 13 | u32 base; |
14 | |||
15 | /* GPIO mode */ | ||
16 | u8 vidmask; | ||
8 | s16 step; | 17 | s16 step; |
18 | |||
19 | /* PWM mode */ | ||
20 | u32 pwm_freq; | ||
21 | u32 pwm_range; | ||
9 | }; | 22 | }; |
10 | 23 | ||
11 | u16 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); | 24 | u16 nvbios_volt_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h index 6a04d9c07944..33a057c334f2 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bus.h | |||
@@ -14,6 +14,7 @@ int nvkm_hwsq_fini(struct nvkm_hwsq **, bool exec); | |||
14 | void nvkm_hwsq_wr32(struct nvkm_hwsq *, u32 addr, u32 data); | 14 | void nvkm_hwsq_wr32(struct nvkm_hwsq *, u32 addr, u32 data); |
15 | void nvkm_hwsq_setf(struct nvkm_hwsq *, u8 flag, int data); | 15 | void nvkm_hwsq_setf(struct nvkm_hwsq *, u8 flag, int data); |
16 | void nvkm_hwsq_wait(struct nvkm_hwsq *, u8 flag, u8 data); | 16 | void nvkm_hwsq_wait(struct nvkm_hwsq *, u8 flag, u8 data); |
17 | void nvkm_hwsq_wait_vblank(struct nvkm_hwsq *); | ||
17 | void nvkm_hwsq_nsec(struct nvkm_hwsq *, u32 nsec); | 18 | void nvkm_hwsq_nsec(struct nvkm_hwsq *, u32 nsec); |
18 | 19 | ||
19 | int nv04_bus_new(struct nvkm_device *, int, struct nvkm_bus **); | 20 | int nv04_bus_new(struct nvkm_device *, int, struct nvkm_bus **); |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h index 9d512cd5a0a7..c4dcd2680fe1 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ibus.h | |||
@@ -3,6 +3,7 @@ | |||
3 | #include <core/subdev.h> | 3 | #include <core/subdev.h> |
4 | 4 | ||
5 | int gf100_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); | 5 | int gf100_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); |
6 | int gf117_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); | ||
6 | int gk104_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); | 7 | int gk104_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); |
7 | int gk20a_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); | 8 | int gk20a_ibus_new(struct nvkm_device *, int, struct nvkm_subdev **); |
8 | #endif | 9 | #endif |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h index c773b5e958b4..3d4dbbf9aab3 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h | |||
@@ -30,7 +30,11 @@ void nvkm_ltc_tags_clear(struct nvkm_ltc *, u32 first, u32 count); | |||
30 | int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); | 30 | int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); |
31 | int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32); | 31 | int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32); |
32 | 32 | ||
33 | void nvkm_ltc_invalidate(struct nvkm_ltc *); | ||
34 | void nvkm_ltc_flush(struct nvkm_ltc *); | ||
35 | |||
33 | int gf100_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); | 36 | int gf100_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); |
34 | int gk104_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); | 37 | int gk104_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); |
38 | int gk20a_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); | ||
35 | int gm107_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); | 39 | int gm107_ltc_new(struct nvkm_device *, int, struct nvkm_ltc **); |
36 | #endif | 40 | #endif |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h index 5b3c054f3b55..fee0a97c44c5 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h | |||
@@ -24,11 +24,14 @@ struct nvkm_pci { | |||
24 | u32 nvkm_pci_rd32(struct nvkm_pci *, u16 addr); | 24 | u32 nvkm_pci_rd32(struct nvkm_pci *, u16 addr); |
25 | void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data); | 25 | void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data); |
26 | void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data); | 26 | void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data); |
27 | u32 nvkm_pci_mask(struct nvkm_pci *, u16 addr, u32 mask, u32 value); | ||
27 | void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow); | 28 | void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow); |
28 | 29 | ||
29 | int nv04_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | 30 | int nv04_pci_new(struct nvkm_device *, int, struct nvkm_pci **); |
30 | int nv40_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | 31 | int nv40_pci_new(struct nvkm_device *, int, struct nvkm_pci **); |
32 | int nv46_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | ||
31 | int nv4c_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | 33 | int nv4c_pci_new(struct nvkm_device *, int, struct nvkm_pci **); |
32 | int nv50_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | 34 | int g84_pci_new(struct nvkm_device *, int, struct nvkm_pci **); |
35 | int g94_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | ||
33 | int gf100_pci_new(struct nvkm_device *, int, struct nvkm_pci **); | 36 | int gf100_pci_new(struct nvkm_device *, int, struct nvkm_pci **); |
34 | #endif | 37 | #endif |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h index 62ed0880b0e1..82d3e28918fd 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/timer.h | |||
@@ -59,6 +59,16 @@ void nvkm_timer_alarm_cancel(struct nvkm_timer *, struct nvkm_alarm *); | |||
59 | #define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond) | 59 | #define nvkm_usec(d,u,cond...) nvkm_nsec((d), (u) * 1000, ##cond) |
60 | #define nvkm_msec(d,m,cond...) nvkm_usec((d), (m) * 1000, ##cond) | 60 | #define nvkm_msec(d,m,cond...) nvkm_usec((d), (m) * 1000, ##cond) |
61 | 61 | ||
62 | #define nvkm_wait_nsec(d,n,addr,mask,data) \ | ||
63 | nvkm_nsec(d, n, \ | ||
64 | if ((nvkm_rd32(d, (addr)) & (mask)) == (data)) \ | ||
65 | break; \ | ||
66 | ) | ||
67 | #define nvkm_wait_usec(d,u,addr,mask,data) \ | ||
68 | nvkm_wait_nsec((d), (u) * 1000, (addr), (mask), (data)) | ||
69 | #define nvkm_wait_msec(d,m,addr,mask,data) \ | ||
70 | nvkm_wait_usec((d), (m) * 1000, (addr), (mask), (data)) | ||
71 | |||
62 | int nv04_timer_new(struct nvkm_device *, int, struct nvkm_timer **); | 72 | int nv04_timer_new(struct nvkm_device *, int, struct nvkm_timer **); |
63 | int nv40_timer_new(struct nvkm_device *, int, struct nvkm_timer **); | 73 | int nv40_timer_new(struct nvkm_device *, int, struct nvkm_timer **); |
64 | int nv41_timer_new(struct nvkm_device *, int, struct nvkm_timer **); | 74 | int nv41_timer_new(struct nvkm_device *, int, struct nvkm_timer **); |
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h index 5c8a3f1196de..b458d046dba7 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/volt.h | |||
@@ -18,5 +18,6 @@ int nvkm_volt_get(struct nvkm_volt *); | |||
18 | int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition); | 18 | int nvkm_volt_set_id(struct nvkm_volt *, u8 id, int condition); |
19 | 19 | ||
20 | int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); | 20 | int nv40_volt_new(struct nvkm_device *, int, struct nvkm_volt **); |
21 | int gk104_volt_new(struct nvkm_device *, int, struct nvkm_volt **); | ||
21 | int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **); | 22 | int gk20a_volt_new(struct nvkm_device *, int, struct nvkm_volt **); |
22 | #endif | 23 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index d336c2247d6a..7f50cf5f929e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <nvif/driver.h> | 25 | #include <nvif/driver.h> |
26 | #include <nvif/ioctl.h> | 26 | #include <nvif/ioctl.h> |
27 | #include <nvif/class.h> | 27 | #include <nvif/class.h> |
28 | #include <nvif/unpack.h> | ||
28 | 29 | ||
29 | #include "nouveau_drm.h" | 30 | #include "nouveau_drm.h" |
30 | #include "nouveau_dma.h" | 31 | #include "nouveau_dma.h" |
@@ -32,11 +33,10 @@ | |||
32 | #include "nouveau_chan.h" | 33 | #include "nouveau_chan.h" |
33 | #include "nouveau_abi16.h" | 34 | #include "nouveau_abi16.h" |
34 | 35 | ||
35 | struct nouveau_abi16 * | 36 | static struct nouveau_abi16 * |
36 | nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) | 37 | nouveau_abi16(struct drm_file *file_priv) |
37 | { | 38 | { |
38 | struct nouveau_cli *cli = nouveau_cli(file_priv); | 39 | struct nouveau_cli *cli = nouveau_cli(file_priv); |
39 | mutex_lock(&cli->mutex); | ||
40 | if (!cli->abi16) { | 40 | if (!cli->abi16) { |
41 | struct nouveau_abi16 *abi16; | 41 | struct nouveau_abi16 *abi16; |
42 | cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL); | 42 | cli->abi16 = abi16 = kzalloc(sizeof(*abi16), GFP_KERNEL); |
@@ -51,8 +51,7 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) | |||
51 | * device (ie. the one that belongs to the fd it | 51 | * device (ie. the one that belongs to the fd it |
52 | * opened) | 52 | * opened) |
53 | */ | 53 | */ |
54 | if (nvif_device_init(&cli->base.object, | 54 | if (nvif_device_init(&cli->base.object, 0, NV_DEVICE, |
55 | NOUVEAU_ABI16_DEVICE, NV_DEVICE, | ||
56 | &args, sizeof(args), | 55 | &args, sizeof(args), |
57 | &abi16->device) == 0) | 56 | &abi16->device) == 0) |
58 | return cli->abi16; | 57 | return cli->abi16; |
@@ -60,12 +59,21 @@ nouveau_abi16_get(struct drm_file *file_priv, struct drm_device *dev) | |||
60 | kfree(cli->abi16); | 59 | kfree(cli->abi16); |
61 | cli->abi16 = NULL; | 60 | cli->abi16 = NULL; |
62 | } | 61 | } |
63 | |||
64 | mutex_unlock(&cli->mutex); | ||
65 | } | 62 | } |
66 | return cli->abi16; | 63 | return cli->abi16; |
67 | } | 64 | } |
68 | 65 | ||
66 | struct nouveau_abi16 * | ||
67 | nouveau_abi16_get(struct drm_file *file_priv) | ||
68 | { | ||
69 | struct nouveau_cli *cli = nouveau_cli(file_priv); | ||
70 | mutex_lock(&cli->mutex); | ||
71 | if (nouveau_abi16(file_priv)) | ||
72 | return cli->abi16; | ||
73 | mutex_unlock(&cli->mutex); | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
69 | int | 77 | int |
70 | nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret) | 78 | nouveau_abi16_put(struct nouveau_abi16 *abi16, int ret) |
71 | { | 79 | { |
@@ -133,7 +141,6 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, | |||
133 | 141 | ||
134 | /* destroy channel object, all children will be killed too */ | 142 | /* destroy channel object, all children will be killed too */ |
135 | if (chan->chan) { | 143 | if (chan->chan) { |
136 | abi16->handles &= ~(1ULL << (chan->chan->user.handle & 0xffff)); | ||
137 | nouveau_channel_idle(chan->chan); | 144 | nouveau_channel_idle(chan->chan); |
138 | nouveau_channel_del(&chan->chan); | 145 | nouveau_channel_del(&chan->chan); |
139 | } | 146 | } |
@@ -238,7 +245,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) | |||
238 | struct drm_nouveau_channel_alloc *init = data; | 245 | struct drm_nouveau_channel_alloc *init = data; |
239 | struct nouveau_cli *cli = nouveau_cli(file_priv); | 246 | struct nouveau_cli *cli = nouveau_cli(file_priv); |
240 | struct nouveau_drm *drm = nouveau_drm(dev); | 247 | struct nouveau_drm *drm = nouveau_drm(dev); |
241 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); | 248 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); |
242 | struct nouveau_abi16_chan *chan; | 249 | struct nouveau_abi16_chan *chan; |
243 | struct nvif_device *device; | 250 | struct nvif_device *device; |
244 | int ret; | 251 | int ret; |
@@ -268,26 +275,21 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) | |||
268 | return nouveau_abi16_put(abi16, -EINVAL); | 275 | return nouveau_abi16_put(abi16, -EINVAL); |
269 | 276 | ||
270 | /* allocate "abi16 channel" data and make up a handle for it */ | 277 | /* allocate "abi16 channel" data and make up a handle for it */ |
271 | init->channel = __ffs64(~abi16->handles); | ||
272 | if (~abi16->handles == 0) | ||
273 | return nouveau_abi16_put(abi16, -ENOSPC); | ||
274 | |||
275 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); | 278 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); |
276 | if (!chan) | 279 | if (!chan) |
277 | return nouveau_abi16_put(abi16, -ENOMEM); | 280 | return nouveau_abi16_put(abi16, -ENOMEM); |
278 | 281 | ||
279 | INIT_LIST_HEAD(&chan->notifiers); | 282 | INIT_LIST_HEAD(&chan->notifiers); |
280 | list_add(&chan->head, &abi16->channels); | 283 | list_add(&chan->head, &abi16->channels); |
281 | abi16->handles |= (1ULL << init->channel); | ||
282 | 284 | ||
283 | /* create channel object and initialise dma and fence management */ | 285 | /* create channel object and initialise dma and fence management */ |
284 | ret = nouveau_channel_new(drm, device, | 286 | ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle, |
285 | NOUVEAU_ABI16_CHAN(init->channel), | ||
286 | init->fb_ctxdma_handle, | ||
287 | init->tt_ctxdma_handle, &chan->chan); | 287 | init->tt_ctxdma_handle, &chan->chan); |
288 | if (ret) | 288 | if (ret) |
289 | goto done; | 289 | goto done; |
290 | 290 | ||
291 | init->channel = chan->chan->chid; | ||
292 | |||
291 | if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) | 293 | if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) |
292 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | | 294 | init->pushbuf_domains = NOUVEAU_GEM_DOMAIN_VRAM | |
293 | NOUVEAU_GEM_DOMAIN_GART; | 295 | NOUVEAU_GEM_DOMAIN_GART; |
@@ -338,7 +340,7 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel) | |||
338 | struct nouveau_abi16_chan *chan; | 340 | struct nouveau_abi16_chan *chan; |
339 | 341 | ||
340 | list_for_each_entry(chan, &abi16->channels, head) { | 342 | list_for_each_entry(chan, &abi16->channels, head) { |
341 | if (chan->chan->user.handle == NOUVEAU_ABI16_CHAN(channel)) | 343 | if (chan->chan->chid == channel) |
342 | return chan; | 344 | return chan; |
343 | } | 345 | } |
344 | 346 | ||
@@ -346,10 +348,48 @@ nouveau_abi16_chan(struct nouveau_abi16 *abi16, int channel) | |||
346 | } | 348 | } |
347 | 349 | ||
348 | int | 350 | int |
351 | nouveau_abi16_usif(struct drm_file *file_priv, void *data, u32 size) | ||
352 | { | ||
353 | union { | ||
354 | struct nvif_ioctl_v0 v0; | ||
355 | } *args = data; | ||
356 | struct nouveau_abi16_chan *chan; | ||
357 | struct nouveau_abi16 *abi16; | ||
358 | int ret; | ||
359 | |||
360 | if (nvif_unpack(args->v0, 0, 0, true)) { | ||
361 | switch (args->v0.type) { | ||
362 | case NVIF_IOCTL_V0_NEW: | ||
363 | case NVIF_IOCTL_V0_MTHD: | ||
364 | case NVIF_IOCTL_V0_SCLASS: | ||
365 | break; | ||
366 | default: | ||
367 | return -EACCES; | ||
368 | } | ||
369 | } else | ||
370 | return ret; | ||
371 | |||
372 | if (!(abi16 = nouveau_abi16(file_priv))) | ||
373 | return -ENOMEM; | ||
374 | |||
375 | if (args->v0.token != ~0ULL) { | ||
376 | if (!(chan = nouveau_abi16_chan(abi16, args->v0.token))) | ||
377 | return -EINVAL; | ||
378 | args->v0.object = nvif_handle(&chan->chan->user); | ||
379 | args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | args->v0.object = nvif_handle(&abi16->device.object); | ||
384 | args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | int | ||
349 | nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS) | 389 | nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS) |
350 | { | 390 | { |
351 | struct drm_nouveau_channel_free *req = data; | 391 | struct drm_nouveau_channel_free *req = data; |
352 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); | 392 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); |
353 | struct nouveau_abi16_chan *chan; | 393 | struct nouveau_abi16_chan *chan; |
354 | 394 | ||
355 | if (unlikely(!abi16)) | 395 | if (unlikely(!abi16)) |
@@ -366,7 +406,7 @@ int | |||
366 | nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) | 406 | nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS) |
367 | { | 407 | { |
368 | struct drm_nouveau_grobj_alloc *init = data; | 408 | struct drm_nouveau_grobj_alloc *init = data; |
369 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); | 409 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); |
370 | struct nouveau_abi16_chan *chan; | 410 | struct nouveau_abi16_chan *chan; |
371 | struct nouveau_abi16_ntfy *ntfy; | 411 | struct nouveau_abi16_ntfy *ntfy; |
372 | struct nvif_client *client; | 412 | struct nvif_client *client; |
@@ -459,7 +499,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) | |||
459 | { | 499 | { |
460 | struct drm_nouveau_notifierobj_alloc *info = data; | 500 | struct drm_nouveau_notifierobj_alloc *info = data; |
461 | struct nouveau_drm *drm = nouveau_drm(dev); | 501 | struct nouveau_drm *drm = nouveau_drm(dev); |
462 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); | 502 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); |
463 | struct nouveau_abi16_chan *chan; | 503 | struct nouveau_abi16_chan *chan; |
464 | struct nouveau_abi16_ntfy *ntfy; | 504 | struct nouveau_abi16_ntfy *ntfy; |
465 | struct nvif_device *device = &abi16->device; | 505 | struct nvif_device *device = &abi16->device; |
@@ -531,7 +571,7 @@ int | |||
531 | nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS) | 571 | nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS) |
532 | { | 572 | { |
533 | struct drm_nouveau_gpuobj_free *fini = data; | 573 | struct drm_nouveau_gpuobj_free *fini = data; |
534 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); | 574 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); |
535 | struct nouveau_abi16_chan *chan; | 575 | struct nouveau_abi16_chan *chan; |
536 | struct nouveau_abi16_ntfy *ntfy; | 576 | struct nouveau_abi16_ntfy *ntfy; |
537 | int ret = -ENOENT; | 577 | int ret = -ENOENT; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 6584557afa40..841cc556fad8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h | |||
@@ -33,11 +33,11 @@ struct nouveau_abi16 { | |||
33 | u64 handles; | 33 | u64 handles; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | struct nouveau_drm; | 36 | struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *); |
37 | struct nouveau_abi16 *nouveau_abi16_get(struct drm_file *, struct drm_device *); | ||
38 | int nouveau_abi16_put(struct nouveau_abi16 *, int); | 37 | int nouveau_abi16_put(struct nouveau_abi16 *, int); |
39 | void nouveau_abi16_fini(struct nouveau_abi16 *); | 38 | void nouveau_abi16_fini(struct nouveau_abi16 *); |
40 | s32 nouveau_abi16_swclass(struct nouveau_drm *); | 39 | s32 nouveau_abi16_swclass(struct nouveau_drm *); |
40 | int nouveau_abi16_usif(struct drm_file *, void *data, u32 size); | ||
41 | 41 | ||
42 | #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) | 42 | #define NOUVEAU_GEM_DOMAIN_VRAM (1 << 1) |
43 | #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) | 43 | #define NOUVEAU_GEM_DOMAIN_GART (1 << 2) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index ff5e59db49db..1860f389f21f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c | |||
@@ -55,10 +55,8 @@ nouveau_channel_idle(struct nouveau_channel *chan) | |||
55 | } | 55 | } |
56 | 56 | ||
57 | if (ret) { | 57 | if (ret) { |
58 | NV_PRINTK(err, cli, "failed to idle channel " | 58 | NV_PRINTK(err, cli, "failed to idle channel %d [%s]\n", |
59 | "0x%08x [%s]\n", | 59 | chan->chid, nvxx_client(&cli->base)->name); |
60 | chan->user.handle, | ||
61 | nvxx_client(&cli->base)->name); | ||
62 | return ret; | 60 | return ret; |
63 | } | 61 | } |
64 | } | 62 | } |
@@ -89,7 +87,7 @@ nouveau_channel_del(struct nouveau_channel **pchan) | |||
89 | 87 | ||
90 | static int | 88 | static int |
91 | nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, | 89 | nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, |
92 | u32 handle, u32 size, struct nouveau_channel **pchan) | 90 | u32 size, struct nouveau_channel **pchan) |
93 | { | 91 | { |
94 | struct nouveau_cli *cli = (void *)device->object.client; | 92 | struct nouveau_cli *cli = (void *)device->object.client; |
95 | struct nvkm_mmu *mmu = nvxx_mmu(device); | 93 | struct nvkm_mmu *mmu = nvxx_mmu(device); |
@@ -174,8 +172,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, | |||
174 | } | 172 | } |
175 | } | 173 | } |
176 | 174 | ||
177 | ret = nvif_object_init(&device->object, NVDRM_PUSH | | 175 | ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY, |
178 | (handle & 0xffff), NV_DMA_FROM_MEMORY, | ||
179 | &args, sizeof(args), &chan->push.ctxdma); | 176 | &args, sizeof(args), &chan->push.ctxdma); |
180 | if (ret) { | 177 | if (ret) { |
181 | nouveau_channel_del(pchan); | 178 | nouveau_channel_del(pchan); |
@@ -187,7 +184,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, | |||
187 | 184 | ||
188 | static int | 185 | static int |
189 | nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, | 186 | nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, |
190 | u32 handle, u32 engine, struct nouveau_channel **pchan) | 187 | u32 engine, struct nouveau_channel **pchan) |
191 | { | 188 | { |
192 | static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A, | 189 | static const u16 oclasses[] = { MAXWELL_CHANNEL_GPFIFO_A, |
193 | KEPLER_CHANNEL_GPFIFO_A, | 190 | KEPLER_CHANNEL_GPFIFO_A, |
@@ -206,7 +203,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, | |||
206 | int ret; | 203 | int ret; |
207 | 204 | ||
208 | /* allocate dma push buffer */ | 205 | /* allocate dma push buffer */ |
209 | ret = nouveau_channel_prep(drm, device, handle, 0x12000, &chan); | 206 | ret = nouveau_channel_prep(drm, device, 0x12000, &chan); |
210 | *pchan = chan; | 207 | *pchan = chan; |
211 | if (ret) | 208 | if (ret) |
212 | return ret; | 209 | return ret; |
@@ -236,7 +233,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, | |||
236 | size = sizeof(args.nv50); | 233 | size = sizeof(args.nv50); |
237 | } | 234 | } |
238 | 235 | ||
239 | ret = nvif_object_init(&device->object, handle, *oclass++, | 236 | ret = nvif_object_init(&device->object, 0, *oclass++, |
240 | &args, size, &chan->user); | 237 | &args, size, &chan->user); |
241 | if (ret == 0) { | 238 | if (ret == 0) { |
242 | if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) | 239 | if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) |
@@ -256,7 +253,7 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, | |||
256 | 253 | ||
257 | static int | 254 | static int |
258 | nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, | 255 | nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, |
259 | u32 handle, struct nouveau_channel **pchan) | 256 | struct nouveau_channel **pchan) |
260 | { | 257 | { |
261 | static const u16 oclasses[] = { NV40_CHANNEL_DMA, | 258 | static const u16 oclasses[] = { NV40_CHANNEL_DMA, |
262 | NV17_CHANNEL_DMA, | 259 | NV17_CHANNEL_DMA, |
@@ -269,7 +266,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, | |||
269 | int ret; | 266 | int ret; |
270 | 267 | ||
271 | /* allocate dma push buffer */ | 268 | /* allocate dma push buffer */ |
272 | ret = nouveau_channel_prep(drm, device, handle, 0x10000, &chan); | 269 | ret = nouveau_channel_prep(drm, device, 0x10000, &chan); |
273 | *pchan = chan; | 270 | *pchan = chan; |
274 | if (ret) | 271 | if (ret) |
275 | return ret; | 272 | return ret; |
@@ -280,7 +277,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, | |||
280 | args.offset = chan->push.vma.offset; | 277 | args.offset = chan->push.vma.offset; |
281 | 278 | ||
282 | do { | 279 | do { |
283 | ret = nvif_object_init(&device->object, handle, *oclass++, | 280 | ret = nvif_object_init(&device->object, 0, *oclass++, |
284 | &args, sizeof(args), &chan->user); | 281 | &args, sizeof(args), &chan->user); |
285 | if (ret == 0) { | 282 | if (ret == 0) { |
286 | chan->chid = args.chid; | 283 | chan->chid = args.chid; |
@@ -401,8 +398,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) | |||
401 | 398 | ||
402 | int | 399 | int |
403 | nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, | 400 | nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, |
404 | u32 handle, u32 arg0, u32 arg1, | 401 | u32 arg0, u32 arg1, struct nouveau_channel **pchan) |
405 | struct nouveau_channel **pchan) | ||
406 | { | 402 | { |
407 | struct nouveau_cli *cli = (void *)device->object.client; | 403 | struct nouveau_cli *cli = (void *)device->object.client; |
408 | bool super; | 404 | bool super; |
@@ -412,10 +408,10 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device, | |||
412 | super = cli->base.super; | 408 | super = cli->base.super; |
413 | cli->base.super = true; | 409 | cli->base.super = true; |
414 | 410 | ||
415 | ret = nouveau_channel_ind(drm, device, handle, arg0, pchan); | 411 | ret = nouveau_channel_ind(drm, device, arg0, pchan); |
416 | if (ret) { | 412 | if (ret) { |
417 | NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); | 413 | NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret); |
418 | ret = nouveau_channel_dma(drm, device, handle, pchan); | 414 | ret = nouveau_channel_dma(drm, device, pchan); |
419 | if (ret) { | 415 | if (ret) { |
420 | NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret); | 416 | NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret); |
421 | goto done; | 417 | goto done; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 2ed32414cb69..48062c94f36d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h | |||
@@ -42,8 +42,7 @@ struct nouveau_channel { | |||
42 | 42 | ||
43 | 43 | ||
44 | int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, | 44 | int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, |
45 | u32 handle, u32 arg0, u32 arg1, | 45 | u32 arg0, u32 arg1, struct nouveau_channel **); |
46 | struct nouveau_channel **); | ||
47 | void nouveau_channel_del(struct nouveau_channel **); | 46 | void nouveau_channel_del(struct nouveau_channel **); |
48 | int nouveau_channel_idle(struct nouveau_channel *); | 47 | int nouveau_channel_idle(struct nouveau_channel *); |
49 | 48 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 614b32e6381c..db6bc6760545 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -509,9 +509,8 @@ nouveau_display_create(struct drm_device *dev) | |||
509 | int i; | 509 | int i; |
510 | 510 | ||
511 | for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) { | 511 | for (i = 0, ret = -ENODEV; ret && i < ARRAY_SIZE(oclass); i++) { |
512 | ret = nvif_object_init(&drm->device.object, | 512 | ret = nvif_object_init(&drm->device.object, 0, |
513 | NVDRM_DISPLAY, oclass[i], | 513 | oclass[i], NULL, 0, &disp->disp); |
514 | NULL, 0, &disp->disp); | ||
515 | } | 514 | } |
516 | 515 | ||
517 | if (ret == 0) { | 516 | if (ret == 0) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 45ba67819199..1d3ee5179ab8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -208,7 +208,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
208 | } | 208 | } |
209 | 209 | ||
210 | if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { | 210 | if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) { |
211 | ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, | 211 | ret = nouveau_channel_new(drm, &drm->device, |
212 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| | 212 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE0| |
213 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, | 213 | KEPLER_CHANNEL_GPFIFO_A_V0_ENGINE_CE1, |
214 | 0, &drm->cechan); | 214 | 0, &drm->cechan); |
@@ -221,7 +221,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
221 | if (device->info.chipset >= 0xa3 && | 221 | if (device->info.chipset >= 0xa3 && |
222 | device->info.chipset != 0xaa && | 222 | device->info.chipset != 0xaa && |
223 | device->info.chipset != 0xac) { | 223 | device->info.chipset != 0xac) { |
224 | ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN + 1, | 224 | ret = nouveau_channel_new(drm, &drm->device, |
225 | NvDmaFB, NvDmaTT, &drm->cechan); | 225 | NvDmaFB, NvDmaTT, &drm->cechan); |
226 | if (ret) | 226 | if (ret) |
227 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); | 227 | NV_ERROR(drm, "failed to create ce channel, %d\n", ret); |
@@ -233,8 +233,7 @@ nouveau_accel_init(struct nouveau_drm *drm) | |||
233 | arg1 = NvDmaTT; | 233 | arg1 = NvDmaTT; |
234 | } | 234 | } |
235 | 235 | ||
236 | ret = nouveau_channel_new(drm, &drm->device, NVDRM_CHAN, arg0, arg1, | 236 | ret = nouveau_channel_new(drm, &drm->device, arg0, arg1, &drm->channel); |
237 | &drm->channel); | ||
238 | if (ret) { | 237 | if (ret) { |
239 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); | 238 | NV_ERROR(drm, "failed to create kernel channel, %d\n", ret); |
240 | nouveau_accel_fini(drm); | 239 | nouveau_accel_fini(drm); |
@@ -403,8 +402,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | |||
403 | 402 | ||
404 | nouveau_get_hdmi_dev(drm); | 403 | nouveau_get_hdmi_dev(drm); |
405 | 404 | ||
406 | ret = nvif_device_init(&drm->client.base.object, | 405 | ret = nvif_device_init(&drm->client.base.object, 0, NV_DEVICE, |
407 | NVDRM_DEVICE, NV_DEVICE, | ||
408 | &(struct nv_device_v0) { | 406 | &(struct nv_device_v0) { |
409 | .device = ~0, | 407 | .device = ~0, |
410 | }, sizeof(struct nv_device_v0), | 408 | }, sizeof(struct nv_device_v0), |
@@ -1030,13 +1028,14 @@ nouveau_drm_pci_driver = { | |||
1030 | }; | 1028 | }; |
1031 | 1029 | ||
1032 | struct drm_device * | 1030 | struct drm_device * |
1033 | nouveau_platform_device_create(struct platform_device *pdev, | 1031 | nouveau_platform_device_create(const struct nvkm_device_tegra_func *func, |
1032 | struct platform_device *pdev, | ||
1034 | struct nvkm_device **pdevice) | 1033 | struct nvkm_device **pdevice) |
1035 | { | 1034 | { |
1036 | struct drm_device *drm; | 1035 | struct drm_device *drm; |
1037 | int err; | 1036 | int err; |
1038 | 1037 | ||
1039 | err = nvkm_device_tegra_new(pdev, nouveau_config, nouveau_debug, | 1038 | err = nvkm_device_tegra_new(func, pdev, nouveau_config, nouveau_debug, |
1040 | true, true, ~0ULL, pdevice); | 1039 | true, true, ~0ULL, pdevice); |
1041 | if (err) | 1040 | if (err) |
1042 | goto err_free; | 1041 | goto err_free; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 3c902c24a8dd..3050042e6c6d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h | |||
@@ -10,7 +10,7 @@ | |||
10 | 10 | ||
11 | #define DRIVER_MAJOR 1 | 11 | #define DRIVER_MAJOR 1 |
12 | #define DRIVER_MINOR 3 | 12 | #define DRIVER_MINOR 3 |
13 | #define DRIVER_PATCHLEVEL 0 | 13 | #define DRIVER_PATCHLEVEL 1 |
14 | 14 | ||
15 | /* | 15 | /* |
16 | * 1.1.1: | 16 | * 1.1.1: |
@@ -33,6 +33,8 @@ | |||
33 | * 1.3.0: | 33 | * 1.3.0: |
34 | * - NVIF ABI modified, safe because only (current) users are test | 34 | * - NVIF ABI modified, safe because only (current) users are test |
35 | * programs that get directly linked with NVKM. | 35 | * programs that get directly linked with NVKM. |
36 | * 1.3.1: | ||
37 | * - implemented limited ABI16/NVIF interop | ||
36 | */ | 38 | */ |
37 | 39 | ||
38 | #include <nvif/client.h> | 40 | #include <nvif/client.h> |
@@ -74,11 +76,6 @@ enum nouveau_drm_notify_route { | |||
74 | }; | 76 | }; |
75 | 77 | ||
76 | enum nouveau_drm_handle { | 78 | enum nouveau_drm_handle { |
77 | NVDRM_CLIENT = 0xffffffff, | ||
78 | NVDRM_DEVICE = 0xdddddddd, | ||
79 | NVDRM_CONTROL = 0xdddddddc, | ||
80 | NVDRM_DISPLAY = 0xd1500000, | ||
81 | NVDRM_PUSH = 0xbbbb0000, /* |= client chid */ | ||
82 | NVDRM_CHAN = 0xcccc0000, /* |= client chid */ | 79 | NVDRM_CHAN = 0xcccc0000, /* |= client chid */ |
83 | NVDRM_NVSW = 0x55550000, | 80 | NVDRM_NVSW = 0x55550000, |
84 | }; | 81 | }; |
@@ -183,8 +180,11 @@ nouveau_drm(struct drm_device *dev) | |||
183 | int nouveau_pmops_suspend(struct device *); | 180 | int nouveau_pmops_suspend(struct device *); |
184 | int nouveau_pmops_resume(struct device *); | 181 | int nouveau_pmops_resume(struct device *); |
185 | 182 | ||
183 | #include <nvkm/core/tegra.h> | ||
184 | |||
186 | struct drm_device * | 185 | struct drm_device * |
187 | nouveau_platform_device_create(struct platform_device *, struct nvkm_device **); | 186 | nouveau_platform_device_create(const struct nvkm_device_tegra_func *, |
187 | struct platform_device *, struct nvkm_device **); | ||
188 | void nouveau_drm_device_remove(struct drm_device *dev); | 188 | void nouveau_drm_device_remove(struct drm_device *dev); |
189 | 189 | ||
190 | #define NV_PRINTK(l,c,f,a...) do { \ | 190 | #define NV_PRINTK(l,c,f,a...) do { \ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2c9981512d27..a0865c49ec83 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -84,8 +84,10 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | ret = pm_runtime_get_sync(dev); | 86 | ret = pm_runtime_get_sync(dev); |
87 | if (ret < 0 && ret != -EACCES) | 87 | if (ret < 0 && ret != -EACCES) { |
88 | kfree(vma); | ||
88 | goto out; | 89 | goto out; |
90 | } | ||
89 | 91 | ||
90 | ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); | 92 | ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); |
91 | if (ret) | 93 | if (ret) |
@@ -227,11 +229,12 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, | |||
227 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); | 229 | struct nouveau_bo *nvbo = nouveau_gem_object(gem); |
228 | struct nvkm_vma *vma; | 230 | struct nvkm_vma *vma; |
229 | 231 | ||
230 | if (nvbo->bo.mem.mem_type == TTM_PL_TT) | 232 | if (is_power_of_2(nvbo->valid_domains)) |
233 | rep->domain = nvbo->valid_domains; | ||
234 | else if (nvbo->bo.mem.mem_type == TTM_PL_TT) | ||
231 | rep->domain = NOUVEAU_GEM_DOMAIN_GART; | 235 | rep->domain = NOUVEAU_GEM_DOMAIN_GART; |
232 | else | 236 | else |
233 | rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; | 237 | rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; |
234 | |||
235 | rep->offset = nvbo->bo.offset; | 238 | rep->offset = nvbo->bo.offset; |
236 | if (cli->vm) { | 239 | if (cli->vm) { |
237 | vma = nouveau_bo_vma_find(nvbo, cli->vm); | 240 | vma = nouveau_bo_vma_find(nvbo, cli->vm); |
@@ -665,7 +668,7 @@ int | |||
665 | nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | 668 | nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, |
666 | struct drm_file *file_priv) | 669 | struct drm_file *file_priv) |
667 | { | 670 | { |
668 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); | 671 | struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); |
669 | struct nouveau_cli *cli = nouveau_cli(file_priv); | 672 | struct nouveau_cli *cli = nouveau_cli(file_priv); |
670 | struct nouveau_abi16_chan *temp; | 673 | struct nouveau_abi16_chan *temp; |
671 | struct nouveau_drm *drm = nouveau_drm(dev); | 674 | struct nouveau_drm *drm = nouveau_drm(dev); |
@@ -681,7 +684,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
681 | return -ENOMEM; | 684 | return -ENOMEM; |
682 | 685 | ||
683 | list_for_each_entry(temp, &abi16->channels, head) { | 686 | list_for_each_entry(temp, &abi16->channels, head) { |
684 | if (temp->chan->user.handle == (NVDRM_CHAN | req->channel)) { | 687 | if (temp->chan->chid == req->channel) { |
685 | chan = temp->chan; | 688 | chan = temp->chan; |
686 | break; | 689 | break; |
687 | } | 690 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c index 3eb665453165..60e32c4e4e49 100644 --- a/drivers/gpu/drm/nouveau/nouveau_platform.c +++ b/drivers/gpu/drm/nouveau/nouveau_platform.c | |||
@@ -23,11 +23,14 @@ | |||
23 | 23 | ||
24 | static int nouveau_platform_probe(struct platform_device *pdev) | 24 | static int nouveau_platform_probe(struct platform_device *pdev) |
25 | { | 25 | { |
26 | const struct nvkm_device_tegra_func *func; | ||
26 | struct nvkm_device *device; | 27 | struct nvkm_device *device; |
27 | struct drm_device *drm; | 28 | struct drm_device *drm; |
28 | int ret; | 29 | int ret; |
29 | 30 | ||
30 | drm = nouveau_platform_device_create(pdev, &device); | 31 | func = of_device_get_match_data(&pdev->dev); |
32 | |||
33 | drm = nouveau_platform_device_create(func, pdev, &device); | ||
31 | if (IS_ERR(drm)) | 34 | if (IS_ERR(drm)) |
32 | return PTR_ERR(drm); | 35 | return PTR_ERR(drm); |
33 | 36 | ||
@@ -48,9 +51,19 @@ static int nouveau_platform_remove(struct platform_device *pdev) | |||
48 | } | 51 | } |
49 | 52 | ||
50 | #if IS_ENABLED(CONFIG_OF) | 53 | #if IS_ENABLED(CONFIG_OF) |
54 | static const struct nvkm_device_tegra_func gk20a_platform_data = { | ||
55 | .iommu_bit = 34, | ||
56 | }; | ||
57 | |||
51 | static const struct of_device_id nouveau_platform_match[] = { | 58 | static const struct of_device_id nouveau_platform_match[] = { |
52 | { .compatible = "nvidia,gk20a" }, | 59 | { |
53 | { .compatible = "nvidia,gm20b" }, | 60 | .compatible = "nvidia,gk20a", |
61 | .data = &gk20a_platform_data, | ||
62 | }, | ||
63 | { | ||
64 | .compatible = "nvidia,gm20b", | ||
65 | .data = &gk20a_platform_data, | ||
66 | }, | ||
54 | { } | 67 | { } |
55 | }; | 68 | }; |
56 | 69 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_sysfs.c b/drivers/gpu/drm/nouveau/nouveau_sysfs.c index d12a5faee047..5dac3546c1b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sysfs.c +++ b/drivers/gpu/drm/nouveau/nouveau_sysfs.c | |||
@@ -188,9 +188,8 @@ nouveau_sysfs_init(struct drm_device *dev) | |||
188 | if (!sysfs) | 188 | if (!sysfs) |
189 | return -ENOMEM; | 189 | return -ENOMEM; |
190 | 190 | ||
191 | ret = nvif_object_init(&device->object, NVDRM_CONTROL, | 191 | ret = nvif_object_init(&device->object, 0, NVIF_IOCTL_NEW_V0_CONTROL, |
192 | NVIF_IOCTL_NEW_V0_CONTROL, NULL, 0, | 192 | NULL, 0, &sysfs->ctrl); |
193 | &sysfs->ctrl); | ||
194 | if (ret == 0) | 193 | if (ret == 0) |
195 | device_create_file(nvxx_device(device)->dev, &dev_attr_pstate); | 194 | device_create_file(nvxx_device(device)->dev, &dev_attr_pstate); |
196 | 195 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index 3f0fb55cb473..3f713c1b5dc1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include "nouveau_gem.h" | 29 | #include "nouveau_gem.h" |
30 | 30 | ||
31 | #include "drm_legacy.h" | 31 | #include "drm_legacy.h" |
32 | |||
33 | #include <core/tegra.h> | ||
34 | |||
32 | static int | 35 | static int |
33 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) | 36 | nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) |
34 | { | 37 | { |
@@ -338,7 +341,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) | |||
338 | struct nvkm_device *device = nvxx_device(&drm->device); | 341 | struct nvkm_device *device = nvxx_device(&drm->device); |
339 | struct nvkm_pci *pci = device->pci; | 342 | struct nvkm_pci *pci = device->pci; |
340 | struct drm_device *dev = drm->dev; | 343 | struct drm_device *dev = drm->dev; |
341 | u32 bits; | 344 | u8 bits; |
342 | int ret; | 345 | int ret; |
343 | 346 | ||
344 | if (pci && pci->agp.bridge) { | 347 | if (pci && pci->agp.bridge) { |
@@ -351,20 +354,28 @@ nouveau_ttm_init(struct nouveau_drm *drm) | |||
351 | bits = nvxx_mmu(&drm->device)->dma_bits; | 354 | bits = nvxx_mmu(&drm->device)->dma_bits; |
352 | if (nvxx_device(&drm->device)->func->pci) { | 355 | if (nvxx_device(&drm->device)->func->pci) { |
353 | if (drm->agp.bridge || | 356 | if (drm->agp.bridge || |
354 | !pci_dma_supported(dev->pdev, DMA_BIT_MASK(bits))) | 357 | !dma_supported(dev->dev, DMA_BIT_MASK(bits))) |
355 | bits = 32; | 358 | bits = 32; |
359 | } else if (device->func->tegra) { | ||
360 | struct nvkm_device_tegra *tegra = device->func->tegra(device); | ||
356 | 361 | ||
357 | ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(bits)); | 362 | /* |
358 | if (ret) | 363 | * If the platform can use a IOMMU, then the addressable DMA |
359 | return ret; | 364 | * space is constrained by the IOMMU bit |
365 | */ | ||
366 | if (tegra->func->iommu_bit) | ||
367 | bits = min(bits, tegra->func->iommu_bit); | ||
360 | 368 | ||
361 | ret = pci_set_consistent_dma_mask(dev->pdev, | ||
362 | DMA_BIT_MASK(bits)); | ||
363 | if (ret) | ||
364 | pci_set_consistent_dma_mask(dev->pdev, | ||
365 | DMA_BIT_MASK(32)); | ||
366 | } | 369 | } |
367 | 370 | ||
371 | ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); | ||
372 | if (ret) | ||
373 | return ret; | ||
374 | |||
375 | ret = dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(bits)); | ||
376 | if (ret) | ||
377 | dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(32)); | ||
378 | |||
368 | ret = nouveau_ttm_global_init(drm); | 379 | ret = nouveau_ttm_global_init(drm); |
369 | if (ret) | 380 | if (ret) |
370 | return ret; | 381 | return ret; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c index cb1182d7e80e..89dc4ce63490 100644 --- a/drivers/gpu/drm/nouveau/nouveau_usif.c +++ b/drivers/gpu/drm/nouveau/nouveau_usif.c | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include "nouveau_drm.h" | 25 | #include "nouveau_drm.h" |
26 | #include "nouveau_usif.h" | 26 | #include "nouveau_usif.h" |
27 | #include "nouveau_abi16.h" | ||
27 | 28 | ||
28 | #include <nvif/notify.h> | 29 | #include <nvif/notify.h> |
29 | #include <nvif/unpack.h> | 30 | #include <nvif/unpack.h> |
@@ -316,11 +317,21 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc) | |||
316 | } else | 317 | } else |
317 | goto done; | 318 | goto done; |
318 | 319 | ||
320 | /* USIF slightly abuses some return-only ioctl members in order | ||
321 | * to provide interoperability with the older ABI16 objects | ||
322 | */ | ||
319 | mutex_lock(&cli->mutex); | 323 | mutex_lock(&cli->mutex); |
324 | if (argv->v0.route) { | ||
325 | if (ret = -EINVAL, argv->v0.route == 0xff) | ||
326 | ret = nouveau_abi16_usif(filp, argv, argc); | ||
327 | if (ret) { | ||
328 | mutex_unlock(&cli->mutex); | ||
329 | goto done; | ||
330 | } | ||
331 | } | ||
332 | |||
320 | switch (argv->v0.type) { | 333 | switch (argv->v0.type) { |
321 | case NVIF_IOCTL_V0_NEW: | 334 | case NVIF_IOCTL_V0_NEW: |
322 | /* ... except if we're creating children */ | ||
323 | argv->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; | ||
324 | ret = usif_object_new(filp, data, size, argv, argc); | 335 | ret = usif_object_new(filp, data, size, argv, argc); |
325 | break; | 336 | break; |
326 | case NVIF_IOCTL_V0_NTFY_NEW: | 337 | case NVIF_IOCTL_V0_NTFY_NEW: |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 4ae87aed4505..c053c50b346a 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -68,7 +68,6 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, | |||
68 | const s32 *oclass, u8 head, void *data, u32 size, | 68 | const s32 *oclass, u8 head, void *data, u32 size, |
69 | struct nv50_chan *chan) | 69 | struct nv50_chan *chan) |
70 | { | 70 | { |
71 | const u32 handle = (oclass[0] << 16) | head; | ||
72 | struct nvif_sclass *sclass; | 71 | struct nvif_sclass *sclass; |
73 | int ret, i, n; | 72 | int ret, i, n; |
74 | 73 | ||
@@ -81,7 +80,7 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, | |||
81 | while (oclass[0]) { | 80 | while (oclass[0]) { |
82 | for (i = 0; i < n; i++) { | 81 | for (i = 0; i < n; i++) { |
83 | if (sclass[i].oclass == oclass[0]) { | 82 | if (sclass[i].oclass == oclass[0]) { |
84 | ret = nvif_object_init(disp, handle, oclass[0], | 83 | ret = nvif_object_init(disp, 0, oclass[0], |
85 | data, size, &chan->user); | 84 | data, size, &chan->user); |
86 | if (ret == 0) | 85 | if (ret == 0) |
87 | nvif_object_map(&chan->user); | 86 | nvif_object_map(&chan->user); |
@@ -231,8 +230,8 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, | |||
231 | if (!dmac->ptr) | 230 | if (!dmac->ptr) |
232 | return -ENOMEM; | 231 | return -ENOMEM; |
233 | 232 | ||
234 | ret = nvif_object_init(&device->object, 0xd0000000, | 233 | ret = nvif_object_init(&device->object, 0, NV_DMA_FROM_MEMORY, |
235 | NV_DMA_FROM_MEMORY, &(struct nv_dma_v0) { | 234 | &(struct nv_dma_v0) { |
236 | .target = NV_DMA_V0_TARGET_PCI_US, | 235 | .target = NV_DMA_V0_TARGET_PCI_US, |
237 | .access = NV_DMA_V0_ACCESS_RD, | 236 | .access = NV_DMA_V0_ACCESS_RD, |
238 | .start = dmac->handle + 0x0000, | 237 | .start = dmac->handle + 0x0000, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 94a906b8cb88..bbc9824af6e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | |||
@@ -637,7 +637,7 @@ nv46_chipset = { | |||
637 | .imem = nv40_instmem_new, | 637 | .imem = nv40_instmem_new, |
638 | .mc = nv44_mc_new, | 638 | .mc = nv44_mc_new, |
639 | .mmu = nv44_mmu_new, | 639 | .mmu = nv44_mmu_new, |
640 | .pci = nv4c_pci_new, | 640 | .pci = nv46_pci_new, |
641 | .therm = nv40_therm_new, | 641 | .therm = nv40_therm_new, |
642 | .timer = nv41_timer_new, | 642 | .timer = nv41_timer_new, |
643 | .volt = nv40_volt_new, | 643 | .volt = nv40_volt_new, |
@@ -822,7 +822,7 @@ nv50_chipset = { | |||
822 | .mc = nv50_mc_new, | 822 | .mc = nv50_mc_new, |
823 | .mmu = nv50_mmu_new, | 823 | .mmu = nv50_mmu_new, |
824 | .mxm = nv50_mxm_new, | 824 | .mxm = nv50_mxm_new, |
825 | .pci = nv50_pci_new, | 825 | .pci = nv46_pci_new, |
826 | .therm = nv50_therm_new, | 826 | .therm = nv50_therm_new, |
827 | .timer = nv41_timer_new, | 827 | .timer = nv41_timer_new, |
828 | .volt = nv40_volt_new, | 828 | .volt = nv40_volt_new, |
@@ -929,7 +929,7 @@ nv84_chipset = { | |||
929 | .mc = nv50_mc_new, | 929 | .mc = nv50_mc_new, |
930 | .mmu = nv50_mmu_new, | 930 | .mmu = nv50_mmu_new, |
931 | .mxm = nv50_mxm_new, | 931 | .mxm = nv50_mxm_new, |
932 | .pci = nv50_pci_new, | 932 | .pci = g84_pci_new, |
933 | .therm = g84_therm_new, | 933 | .therm = g84_therm_new, |
934 | .timer = nv41_timer_new, | 934 | .timer = nv41_timer_new, |
935 | .volt = nv40_volt_new, | 935 | .volt = nv40_volt_new, |
@@ -961,7 +961,7 @@ nv86_chipset = { | |||
961 | .mc = nv50_mc_new, | 961 | .mc = nv50_mc_new, |
962 | .mmu = nv50_mmu_new, | 962 | .mmu = nv50_mmu_new, |
963 | .mxm = nv50_mxm_new, | 963 | .mxm = nv50_mxm_new, |
964 | .pci = nv50_pci_new, | 964 | .pci = g84_pci_new, |
965 | .therm = g84_therm_new, | 965 | .therm = g84_therm_new, |
966 | .timer = nv41_timer_new, | 966 | .timer = nv41_timer_new, |
967 | .volt = nv40_volt_new, | 967 | .volt = nv40_volt_new, |
@@ -993,7 +993,7 @@ nv92_chipset = { | |||
993 | .mc = nv50_mc_new, | 993 | .mc = nv50_mc_new, |
994 | .mmu = nv50_mmu_new, | 994 | .mmu = nv50_mmu_new, |
995 | .mxm = nv50_mxm_new, | 995 | .mxm = nv50_mxm_new, |
996 | .pci = nv50_pci_new, | 996 | .pci = g84_pci_new, |
997 | .therm = g84_therm_new, | 997 | .therm = g84_therm_new, |
998 | .timer = nv41_timer_new, | 998 | .timer = nv41_timer_new, |
999 | .volt = nv40_volt_new, | 999 | .volt = nv40_volt_new, |
@@ -1025,7 +1025,7 @@ nv94_chipset = { | |||
1025 | .mc = nv50_mc_new, | 1025 | .mc = nv50_mc_new, |
1026 | .mmu = nv50_mmu_new, | 1026 | .mmu = nv50_mmu_new, |
1027 | .mxm = nv50_mxm_new, | 1027 | .mxm = nv50_mxm_new, |
1028 | .pci = nv40_pci_new, | 1028 | .pci = g94_pci_new, |
1029 | .therm = g84_therm_new, | 1029 | .therm = g84_therm_new, |
1030 | .timer = nv41_timer_new, | 1030 | .timer = nv41_timer_new, |
1031 | .volt = nv40_volt_new, | 1031 | .volt = nv40_volt_new, |
@@ -1057,7 +1057,7 @@ nv96_chipset = { | |||
1057 | .mc = nv50_mc_new, | 1057 | .mc = nv50_mc_new, |
1058 | .mmu = nv50_mmu_new, | 1058 | .mmu = nv50_mmu_new, |
1059 | .mxm = nv50_mxm_new, | 1059 | .mxm = nv50_mxm_new, |
1060 | .pci = nv40_pci_new, | 1060 | .pci = g94_pci_new, |
1061 | .therm = g84_therm_new, | 1061 | .therm = g84_therm_new, |
1062 | .timer = nv41_timer_new, | 1062 | .timer = nv41_timer_new, |
1063 | .volt = nv40_volt_new, | 1063 | .volt = nv40_volt_new, |
@@ -1089,7 +1089,7 @@ nv98_chipset = { | |||
1089 | .mc = g98_mc_new, | 1089 | .mc = g98_mc_new, |
1090 | .mmu = nv50_mmu_new, | 1090 | .mmu = nv50_mmu_new, |
1091 | .mxm = nv50_mxm_new, | 1091 | .mxm = nv50_mxm_new, |
1092 | .pci = nv40_pci_new, | 1092 | .pci = g94_pci_new, |
1093 | .therm = g84_therm_new, | 1093 | .therm = g84_therm_new, |
1094 | .timer = nv41_timer_new, | 1094 | .timer = nv41_timer_new, |
1095 | .volt = nv40_volt_new, | 1095 | .volt = nv40_volt_new, |
@@ -1121,7 +1121,7 @@ nva0_chipset = { | |||
1121 | .mc = g98_mc_new, | 1121 | .mc = g98_mc_new, |
1122 | .mmu = nv50_mmu_new, | 1122 | .mmu = nv50_mmu_new, |
1123 | .mxm = nv50_mxm_new, | 1123 | .mxm = nv50_mxm_new, |
1124 | .pci = nv40_pci_new, | 1124 | .pci = g94_pci_new, |
1125 | .therm = g84_therm_new, | 1125 | .therm = g84_therm_new, |
1126 | .timer = nv41_timer_new, | 1126 | .timer = nv41_timer_new, |
1127 | .volt = nv40_volt_new, | 1127 | .volt = nv40_volt_new, |
@@ -1153,7 +1153,7 @@ nva3_chipset = { | |||
1153 | .mc = g98_mc_new, | 1153 | .mc = g98_mc_new, |
1154 | .mmu = nv50_mmu_new, | 1154 | .mmu = nv50_mmu_new, |
1155 | .mxm = nv50_mxm_new, | 1155 | .mxm = nv50_mxm_new, |
1156 | .pci = nv40_pci_new, | 1156 | .pci = g94_pci_new, |
1157 | .pmu = gt215_pmu_new, | 1157 | .pmu = gt215_pmu_new, |
1158 | .therm = gt215_therm_new, | 1158 | .therm = gt215_therm_new, |
1159 | .timer = nv41_timer_new, | 1159 | .timer = nv41_timer_new, |
@@ -1187,7 +1187,7 @@ nva5_chipset = { | |||
1187 | .mc = g98_mc_new, | 1187 | .mc = g98_mc_new, |
1188 | .mmu = nv50_mmu_new, | 1188 | .mmu = nv50_mmu_new, |
1189 | .mxm = nv50_mxm_new, | 1189 | .mxm = nv50_mxm_new, |
1190 | .pci = nv40_pci_new, | 1190 | .pci = g94_pci_new, |
1191 | .pmu = gt215_pmu_new, | 1191 | .pmu = gt215_pmu_new, |
1192 | .therm = gt215_therm_new, | 1192 | .therm = gt215_therm_new, |
1193 | .timer = nv41_timer_new, | 1193 | .timer = nv41_timer_new, |
@@ -1220,7 +1220,7 @@ nva8_chipset = { | |||
1220 | .mc = g98_mc_new, | 1220 | .mc = g98_mc_new, |
1221 | .mmu = nv50_mmu_new, | 1221 | .mmu = nv50_mmu_new, |
1222 | .mxm = nv50_mxm_new, | 1222 | .mxm = nv50_mxm_new, |
1223 | .pci = nv40_pci_new, | 1223 | .pci = g94_pci_new, |
1224 | .pmu = gt215_pmu_new, | 1224 | .pmu = gt215_pmu_new, |
1225 | .therm = gt215_therm_new, | 1225 | .therm = gt215_therm_new, |
1226 | .timer = nv41_timer_new, | 1226 | .timer = nv41_timer_new, |
@@ -1253,7 +1253,7 @@ nvaa_chipset = { | |||
1253 | .mc = g98_mc_new, | 1253 | .mc = g98_mc_new, |
1254 | .mmu = nv50_mmu_new, | 1254 | .mmu = nv50_mmu_new, |
1255 | .mxm = nv50_mxm_new, | 1255 | .mxm = nv50_mxm_new, |
1256 | .pci = nv40_pci_new, | 1256 | .pci = g94_pci_new, |
1257 | .therm = g84_therm_new, | 1257 | .therm = g84_therm_new, |
1258 | .timer = nv41_timer_new, | 1258 | .timer = nv41_timer_new, |
1259 | .volt = nv40_volt_new, | 1259 | .volt = nv40_volt_new, |
@@ -1285,7 +1285,7 @@ nvac_chipset = { | |||
1285 | .mc = g98_mc_new, | 1285 | .mc = g98_mc_new, |
1286 | .mmu = nv50_mmu_new, | 1286 | .mmu = nv50_mmu_new, |
1287 | .mxm = nv50_mxm_new, | 1287 | .mxm = nv50_mxm_new, |
1288 | .pci = nv40_pci_new, | 1288 | .pci = g94_pci_new, |
1289 | .therm = g84_therm_new, | 1289 | .therm = g84_therm_new, |
1290 | .timer = nv41_timer_new, | 1290 | .timer = nv41_timer_new, |
1291 | .volt = nv40_volt_new, | 1291 | .volt = nv40_volt_new, |
@@ -1317,7 +1317,7 @@ nvaf_chipset = { | |||
1317 | .mc = g98_mc_new, | 1317 | .mc = g98_mc_new, |
1318 | .mmu = nv50_mmu_new, | 1318 | .mmu = nv50_mmu_new, |
1319 | .mxm = nv50_mxm_new, | 1319 | .mxm = nv50_mxm_new, |
1320 | .pci = nv40_pci_new, | 1320 | .pci = g94_pci_new, |
1321 | .pmu = gt215_pmu_new, | 1321 | .pmu = gt215_pmu_new, |
1322 | .therm = gt215_therm_new, | 1322 | .therm = gt215_therm_new, |
1323 | .timer = nv41_timer_new, | 1323 | .timer = nv41_timer_new, |
@@ -1388,7 +1388,7 @@ nvc1_chipset = { | |||
1388 | .mc = gf100_mc_new, | 1388 | .mc = gf100_mc_new, |
1389 | .mmu = gf100_mmu_new, | 1389 | .mmu = gf100_mmu_new, |
1390 | .mxm = nv50_mxm_new, | 1390 | .mxm = nv50_mxm_new, |
1391 | .pci = nv40_pci_new, | 1391 | .pci = g94_pci_new, |
1392 | .pmu = gf100_pmu_new, | 1392 | .pmu = gf100_pmu_new, |
1393 | .therm = gt215_therm_new, | 1393 | .therm = gt215_therm_new, |
1394 | .timer = nv41_timer_new, | 1394 | .timer = nv41_timer_new, |
@@ -1423,7 +1423,7 @@ nvc3_chipset = { | |||
1423 | .mc = gf100_mc_new, | 1423 | .mc = gf100_mc_new, |
1424 | .mmu = gf100_mmu_new, | 1424 | .mmu = gf100_mmu_new, |
1425 | .mxm = nv50_mxm_new, | 1425 | .mxm = nv50_mxm_new, |
1426 | .pci = nv40_pci_new, | 1426 | .pci = g94_pci_new, |
1427 | .pmu = gf100_pmu_new, | 1427 | .pmu = gf100_pmu_new, |
1428 | .therm = gt215_therm_new, | 1428 | .therm = gt215_therm_new, |
1429 | .timer = nv41_timer_new, | 1429 | .timer = nv41_timer_new, |
@@ -1566,7 +1566,7 @@ nvcf_chipset = { | |||
1566 | .mc = gf100_mc_new, | 1566 | .mc = gf100_mc_new, |
1567 | .mmu = gf100_mmu_new, | 1567 | .mmu = gf100_mmu_new, |
1568 | .mxm = nv50_mxm_new, | 1568 | .mxm = nv50_mxm_new, |
1569 | .pci = nv40_pci_new, | 1569 | .pci = g94_pci_new, |
1570 | .pmu = gf100_pmu_new, | 1570 | .pmu = gf100_pmu_new, |
1571 | .therm = gt215_therm_new, | 1571 | .therm = gt215_therm_new, |
1572 | .timer = nv41_timer_new, | 1572 | .timer = nv41_timer_new, |
@@ -1595,13 +1595,13 @@ nvd7_chipset = { | |||
1595 | .fuse = gf100_fuse_new, | 1595 | .fuse = gf100_fuse_new, |
1596 | .gpio = gf119_gpio_new, | 1596 | .gpio = gf119_gpio_new, |
1597 | .i2c = gf117_i2c_new, | 1597 | .i2c = gf117_i2c_new, |
1598 | .ibus = gf100_ibus_new, | 1598 | .ibus = gf117_ibus_new, |
1599 | .imem = nv50_instmem_new, | 1599 | .imem = nv50_instmem_new, |
1600 | .ltc = gf100_ltc_new, | 1600 | .ltc = gf100_ltc_new, |
1601 | .mc = gf100_mc_new, | 1601 | .mc = gf100_mc_new, |
1602 | .mmu = gf100_mmu_new, | 1602 | .mmu = gf100_mmu_new, |
1603 | .mxm = nv50_mxm_new, | 1603 | .mxm = nv50_mxm_new, |
1604 | .pci = nv40_pci_new, | 1604 | .pci = g94_pci_new, |
1605 | .therm = gf119_therm_new, | 1605 | .therm = gf119_therm_new, |
1606 | .timer = nv41_timer_new, | 1606 | .timer = nv41_timer_new, |
1607 | .ce[0] = gf100_ce_new, | 1607 | .ce[0] = gf100_ce_new, |
@@ -1628,13 +1628,13 @@ nvd9_chipset = { | |||
1628 | .fuse = gf100_fuse_new, | 1628 | .fuse = gf100_fuse_new, |
1629 | .gpio = gf119_gpio_new, | 1629 | .gpio = gf119_gpio_new, |
1630 | .i2c = gf119_i2c_new, | 1630 | .i2c = gf119_i2c_new, |
1631 | .ibus = gf100_ibus_new, | 1631 | .ibus = gf117_ibus_new, |
1632 | .imem = nv50_instmem_new, | 1632 | .imem = nv50_instmem_new, |
1633 | .ltc = gf100_ltc_new, | 1633 | .ltc = gf100_ltc_new, |
1634 | .mc = gf100_mc_new, | 1634 | .mc = gf100_mc_new, |
1635 | .mmu = gf100_mmu_new, | 1635 | .mmu = gf100_mmu_new, |
1636 | .mxm = nv50_mxm_new, | 1636 | .mxm = nv50_mxm_new, |
1637 | .pci = nv40_pci_new, | 1637 | .pci = g94_pci_new, |
1638 | .pmu = gf119_pmu_new, | 1638 | .pmu = gf119_pmu_new, |
1639 | .therm = gf119_therm_new, | 1639 | .therm = gf119_therm_new, |
1640 | .timer = nv41_timer_new, | 1640 | .timer = nv41_timer_new, |
@@ -1669,11 +1669,11 @@ nve4_chipset = { | |||
1669 | .mc = gf100_mc_new, | 1669 | .mc = gf100_mc_new, |
1670 | .mmu = gf100_mmu_new, | 1670 | .mmu = gf100_mmu_new, |
1671 | .mxm = nv50_mxm_new, | 1671 | .mxm = nv50_mxm_new, |
1672 | .pci = nv40_pci_new, | 1672 | .pci = g94_pci_new, |
1673 | .pmu = gk104_pmu_new, | 1673 | .pmu = gk104_pmu_new, |
1674 | .therm = gf119_therm_new, | 1674 | .therm = gf119_therm_new, |
1675 | .timer = nv41_timer_new, | 1675 | .timer = nv41_timer_new, |
1676 | .volt = nv40_volt_new, | 1676 | .volt = gk104_volt_new, |
1677 | .ce[0] = gk104_ce_new, | 1677 | .ce[0] = gk104_ce_new, |
1678 | .ce[1] = gk104_ce_new, | 1678 | .ce[1] = gk104_ce_new, |
1679 | .ce[2] = gk104_ce_new, | 1679 | .ce[2] = gk104_ce_new, |
@@ -1706,11 +1706,11 @@ nve6_chipset = { | |||
1706 | .mc = gf100_mc_new, | 1706 | .mc = gf100_mc_new, |
1707 | .mmu = gf100_mmu_new, | 1707 | .mmu = gf100_mmu_new, |
1708 | .mxm = nv50_mxm_new, | 1708 | .mxm = nv50_mxm_new, |
1709 | .pci = nv40_pci_new, | 1709 | .pci = g94_pci_new, |
1710 | .pmu = gk104_pmu_new, | 1710 | .pmu = gk104_pmu_new, |
1711 | .therm = gf119_therm_new, | 1711 | .therm = gf119_therm_new, |
1712 | .timer = nv41_timer_new, | 1712 | .timer = nv41_timer_new, |
1713 | .volt = nv40_volt_new, | 1713 | .volt = gk104_volt_new, |
1714 | .ce[0] = gk104_ce_new, | 1714 | .ce[0] = gk104_ce_new, |
1715 | .ce[1] = gk104_ce_new, | 1715 | .ce[1] = gk104_ce_new, |
1716 | .ce[2] = gk104_ce_new, | 1716 | .ce[2] = gk104_ce_new, |
@@ -1743,11 +1743,11 @@ nve7_chipset = { | |||
1743 | .mc = gf100_mc_new, | 1743 | .mc = gf100_mc_new, |
1744 | .mmu = gf100_mmu_new, | 1744 | .mmu = gf100_mmu_new, |
1745 | .mxm = nv50_mxm_new, | 1745 | .mxm = nv50_mxm_new, |
1746 | .pci = nv40_pci_new, | 1746 | .pci = g94_pci_new, |
1747 | .pmu = gf119_pmu_new, | 1747 | .pmu = gk104_pmu_new, |
1748 | .therm = gf119_therm_new, | 1748 | .therm = gf119_therm_new, |
1749 | .timer = nv41_timer_new, | 1749 | .timer = nv41_timer_new, |
1750 | .volt = nv40_volt_new, | 1750 | .volt = gk104_volt_new, |
1751 | .ce[0] = gk104_ce_new, | 1751 | .ce[0] = gk104_ce_new, |
1752 | .ce[1] = gk104_ce_new, | 1752 | .ce[1] = gk104_ce_new, |
1753 | .ce[2] = gk104_ce_new, | 1753 | .ce[2] = gk104_ce_new, |
@@ -1804,11 +1804,11 @@ nvf0_chipset = { | |||
1804 | .mc = gf100_mc_new, | 1804 | .mc = gf100_mc_new, |
1805 | .mmu = gf100_mmu_new, | 1805 | .mmu = gf100_mmu_new, |
1806 | .mxm = nv50_mxm_new, | 1806 | .mxm = nv50_mxm_new, |
1807 | .pci = nv40_pci_new, | 1807 | .pci = g94_pci_new, |
1808 | .pmu = gk110_pmu_new, | 1808 | .pmu = gk110_pmu_new, |
1809 | .therm = gf119_therm_new, | 1809 | .therm = gf119_therm_new, |
1810 | .timer = nv41_timer_new, | 1810 | .timer = nv41_timer_new, |
1811 | .volt = nv40_volt_new, | 1811 | .volt = gk104_volt_new, |
1812 | .ce[0] = gk104_ce_new, | 1812 | .ce[0] = gk104_ce_new, |
1813 | .ce[1] = gk104_ce_new, | 1813 | .ce[1] = gk104_ce_new, |
1814 | .ce[2] = gk104_ce_new, | 1814 | .ce[2] = gk104_ce_new, |
@@ -1840,11 +1840,11 @@ nvf1_chipset = { | |||
1840 | .mc = gf100_mc_new, | 1840 | .mc = gf100_mc_new, |
1841 | .mmu = gf100_mmu_new, | 1841 | .mmu = gf100_mmu_new, |
1842 | .mxm = nv50_mxm_new, | 1842 | .mxm = nv50_mxm_new, |
1843 | .pci = nv40_pci_new, | 1843 | .pci = g94_pci_new, |
1844 | .pmu = gk110_pmu_new, | 1844 | .pmu = gk110_pmu_new, |
1845 | .therm = gf119_therm_new, | 1845 | .therm = gf119_therm_new, |
1846 | .timer = nv41_timer_new, | 1846 | .timer = nv41_timer_new, |
1847 | .volt = nv40_volt_new, | 1847 | .volt = gk104_volt_new, |
1848 | .ce[0] = gk104_ce_new, | 1848 | .ce[0] = gk104_ce_new, |
1849 | .ce[1] = gk104_ce_new, | 1849 | .ce[1] = gk104_ce_new, |
1850 | .ce[2] = gk104_ce_new, | 1850 | .ce[2] = gk104_ce_new, |
@@ -1876,11 +1876,11 @@ nv106_chipset = { | |||
1876 | .mc = gk20a_mc_new, | 1876 | .mc = gk20a_mc_new, |
1877 | .mmu = gf100_mmu_new, | 1877 | .mmu = gf100_mmu_new, |
1878 | .mxm = nv50_mxm_new, | 1878 | .mxm = nv50_mxm_new, |
1879 | .pci = nv40_pci_new, | 1879 | .pci = g94_pci_new, |
1880 | .pmu = gk208_pmu_new, | 1880 | .pmu = gk208_pmu_new, |
1881 | .therm = gf119_therm_new, | 1881 | .therm = gf119_therm_new, |
1882 | .timer = nv41_timer_new, | 1882 | .timer = nv41_timer_new, |
1883 | .volt = nv40_volt_new, | 1883 | .volt = gk104_volt_new, |
1884 | .ce[0] = gk104_ce_new, | 1884 | .ce[0] = gk104_ce_new, |
1885 | .ce[1] = gk104_ce_new, | 1885 | .ce[1] = gk104_ce_new, |
1886 | .ce[2] = gk104_ce_new, | 1886 | .ce[2] = gk104_ce_new, |
@@ -1912,11 +1912,11 @@ nv108_chipset = { | |||
1912 | .mc = gk20a_mc_new, | 1912 | .mc = gk20a_mc_new, |
1913 | .mmu = gf100_mmu_new, | 1913 | .mmu = gf100_mmu_new, |
1914 | .mxm = nv50_mxm_new, | 1914 | .mxm = nv50_mxm_new, |
1915 | .pci = nv40_pci_new, | 1915 | .pci = g94_pci_new, |
1916 | .pmu = gk208_pmu_new, | 1916 | .pmu = gk208_pmu_new, |
1917 | .therm = gf119_therm_new, | 1917 | .therm = gf119_therm_new, |
1918 | .timer = nv41_timer_new, | 1918 | .timer = nv41_timer_new, |
1919 | .volt = nv40_volt_new, | 1919 | .volt = gk104_volt_new, |
1920 | .ce[0] = gk104_ce_new, | 1920 | .ce[0] = gk104_ce_new, |
1921 | .ce[1] = gk104_ce_new, | 1921 | .ce[1] = gk104_ce_new, |
1922 | .ce[2] = gk104_ce_new, | 1922 | .ce[2] = gk104_ce_new, |
@@ -1948,10 +1948,11 @@ nv117_chipset = { | |||
1948 | .mc = gk20a_mc_new, | 1948 | .mc = gk20a_mc_new, |
1949 | .mmu = gf100_mmu_new, | 1949 | .mmu = gf100_mmu_new, |
1950 | .mxm = nv50_mxm_new, | 1950 | .mxm = nv50_mxm_new, |
1951 | .pci = nv40_pci_new, | 1951 | .pci = g94_pci_new, |
1952 | .pmu = gm107_pmu_new, | 1952 | .pmu = gm107_pmu_new, |
1953 | .therm = gm107_therm_new, | 1953 | .therm = gm107_therm_new, |
1954 | .timer = gk20a_timer_new, | 1954 | .timer = gk20a_timer_new, |
1955 | .volt = gk104_volt_new, | ||
1955 | .ce[0] = gk104_ce_new, | 1956 | .ce[0] = gk104_ce_new, |
1956 | .ce[2] = gk104_ce_new, | 1957 | .ce[2] = gk104_ce_new, |
1957 | .disp = gm107_disp_new, | 1958 | .disp = gm107_disp_new, |
@@ -1978,9 +1979,10 @@ nv124_chipset = { | |||
1978 | .mc = gk20a_mc_new, | 1979 | .mc = gk20a_mc_new, |
1979 | .mmu = gf100_mmu_new, | 1980 | .mmu = gf100_mmu_new, |
1980 | .mxm = nv50_mxm_new, | 1981 | .mxm = nv50_mxm_new, |
1981 | .pci = nv40_pci_new, | 1982 | .pci = g94_pci_new, |
1982 | .pmu = gm107_pmu_new, | 1983 | .pmu = gm107_pmu_new, |
1983 | .timer = gk20a_timer_new, | 1984 | .timer = gk20a_timer_new, |
1985 | .volt = gk104_volt_new, | ||
1984 | .ce[0] = gm204_ce_new, | 1986 | .ce[0] = gm204_ce_new, |
1985 | .ce[1] = gm204_ce_new, | 1987 | .ce[1] = gm204_ce_new, |
1986 | .ce[2] = gm204_ce_new, | 1988 | .ce[2] = gm204_ce_new, |
@@ -2008,9 +2010,10 @@ nv126_chipset = { | |||
2008 | .mc = gk20a_mc_new, | 2010 | .mc = gk20a_mc_new, |
2009 | .mmu = gf100_mmu_new, | 2011 | .mmu = gf100_mmu_new, |
2010 | .mxm = nv50_mxm_new, | 2012 | .mxm = nv50_mxm_new, |
2011 | .pci = nv40_pci_new, | 2013 | .pci = g94_pci_new, |
2012 | .pmu = gm107_pmu_new, | 2014 | .pmu = gm107_pmu_new, |
2013 | .timer = gk20a_timer_new, | 2015 | .timer = gk20a_timer_new, |
2016 | .volt = gk104_volt_new, | ||
2014 | .ce[0] = gm204_ce_new, | 2017 | .ce[0] = gm204_ce_new, |
2015 | .ce[1] = gm204_ce_new, | 2018 | .ce[1] = gm204_ce_new, |
2016 | .ce[2] = gm204_ce_new, | 2019 | .ce[2] = gm204_ce_new, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c index e8eb14e438f4..e3c783d0e2ab 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c | |||
@@ -259,6 +259,12 @@ nvkm_device_pci_10de_0df4[] = { | |||
259 | }; | 259 | }; |
260 | 260 | ||
261 | static const struct nvkm_device_pci_vendor | 261 | static const struct nvkm_device_pci_vendor |
262 | nvkm_device_pci_10de_0fcd[] = { | ||
263 | { 0x17aa, 0x3801, NULL, { .War00C800_0 = true } }, /* Lenovo Y510P */ | ||
264 | {} | ||
265 | }; | ||
266 | |||
267 | static const struct nvkm_device_pci_vendor | ||
262 | nvkm_device_pci_10de_0fd2[] = { | 268 | nvkm_device_pci_10de_0fd2[] = { |
263 | { 0x1028, 0x0595, "GeForce GT 640M LE" }, | 269 | { 0x1028, 0x0595, "GeForce GT 640M LE" }, |
264 | { 0x1028, 0x05b2, "GeForce GT 640M LE" }, | 270 | { 0x1028, 0x05b2, "GeForce GT 640M LE" }, |
@@ -678,6 +684,7 @@ nvkm_device_pci_10de_1189[] = { | |||
678 | static const struct nvkm_device_pci_vendor | 684 | static const struct nvkm_device_pci_vendor |
679 | nvkm_device_pci_10de_1199[] = { | 685 | nvkm_device_pci_10de_1199[] = { |
680 | { 0x1458, 0xd001, "GeForce GTX 760" }, | 686 | { 0x1458, 0xd001, "GeForce GTX 760" }, |
687 | { 0x1462, 0x1106, "GeForce GTX 780M", { .War00C800_0 = true } }, /* Medion Erazer X7827 */ | ||
681 | {} | 688 | {} |
682 | }; | 689 | }; |
683 | 690 | ||
@@ -1349,7 +1356,7 @@ nvkm_device_pci_10de[] = { | |||
1349 | { 0x0fc6, "GeForce GTX 650" }, | 1356 | { 0x0fc6, "GeForce GTX 650" }, |
1350 | { 0x0fc8, "GeForce GT 740" }, | 1357 | { 0x0fc8, "GeForce GT 740" }, |
1351 | { 0x0fc9, "GeForce GT 730" }, | 1358 | { 0x0fc9, "GeForce GT 730" }, |
1352 | { 0x0fcd, "GeForce GT 755M" }, | 1359 | { 0x0fcd, "GeForce GT 755M", nvkm_device_pci_10de_0fcd }, |
1353 | { 0x0fce, "GeForce GT 640M LE" }, | 1360 | { 0x0fce, "GeForce GT 640M LE" }, |
1354 | { 0x0fd1, "GeForce GT 650M" }, | 1361 | { 0x0fd1, "GeForce GT 650M" }, |
1355 | { 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 }, | 1362 | { 0x0fd2, "GeForce GT 640M", nvkm_device_pci_10de_0fd2 }, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index da57c8a60608..7f8a42721eb2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c | |||
@@ -85,6 +85,9 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) | |||
85 | unsigned long pgsize_bitmap; | 85 | unsigned long pgsize_bitmap; |
86 | int ret; | 86 | int ret; |
87 | 87 | ||
88 | if (!tdev->func->iommu_bit) | ||
89 | return; | ||
90 | |||
88 | mutex_init(&tdev->iommu.mutex); | 91 | mutex_init(&tdev->iommu.mutex); |
89 | 92 | ||
90 | if (iommu_present(&platform_bus_type)) { | 93 | if (iommu_present(&platform_bus_type)) { |
@@ -114,7 +117,8 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) | |||
114 | goto free_domain; | 117 | goto free_domain; |
115 | 118 | ||
116 | ret = nvkm_mm_init(&tdev->iommu.mm, 0, | 119 | ret = nvkm_mm_init(&tdev->iommu.mm, 0, |
117 | (1ULL << 40) >> tdev->iommu.pgshift, 1); | 120 | (1ULL << tdev->func->iommu_bit) >> |
121 | tdev->iommu.pgshift, 1); | ||
118 | if (ret) | 122 | if (ret) |
119 | goto detach_device; | 123 | goto detach_device; |
120 | } | 124 | } |
@@ -237,7 +241,8 @@ nvkm_device_tegra_func = { | |||
237 | }; | 241 | }; |
238 | 242 | ||
239 | int | 243 | int |
240 | nvkm_device_tegra_new(struct platform_device *pdev, | 244 | nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, |
245 | struct platform_device *pdev, | ||
241 | const char *cfg, const char *dbg, | 246 | const char *cfg, const char *dbg, |
242 | bool detect, bool mmio, u64 subdev_mask, | 247 | bool detect, bool mmio, u64 subdev_mask, |
243 | struct nvkm_device **pdevice) | 248 | struct nvkm_device **pdevice) |
@@ -248,6 +253,7 @@ nvkm_device_tegra_new(struct platform_device *pdev, | |||
248 | if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) | 253 | if (!(tdev = kzalloc(sizeof(*tdev), GFP_KERNEL))) |
249 | return -ENOMEM; | 254 | return -ENOMEM; |
250 | *pdevice = &tdev->device; | 255 | *pdevice = &tdev->device; |
256 | tdev->func = func; | ||
251 | tdev->pdev = pdev; | 257 | tdev->pdev = pdev; |
252 | tdev->irq = -1; | 258 | tdev->irq = -1; |
253 | 259 | ||
@@ -285,7 +291,8 @@ nvkm_device_tegra_new(struct platform_device *pdev, | |||
285 | } | 291 | } |
286 | #else | 292 | #else |
287 | int | 293 | int |
288 | nvkm_device_tegra_new(struct platform_device *pdev, | 294 | nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, |
295 | struct platform_device *pdev, | ||
289 | const char *cfg, const char *dbg, | 296 | const char *cfg, const char *dbg, |
290 | bool detect, bool mmio, u64 subdev_mask, | 297 | bool detect, bool mmio, u64 subdev_mask, |
291 | struct nvkm_device **pdevice) | 298 | struct nvkm_device **pdevice) |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c index 62d3fb66d0ec..2be846374d39 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c | |||
@@ -109,7 +109,7 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) | |||
109 | return -EINVAL; | 109 | return -EINVAL; |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct nvkm_object_func | 112 | static const struct nvkm_object_func |
113 | nv04_disp_root = { | 113 | nv04_disp_root = { |
114 | .mthd = nv04_disp_mthd, | 114 | .mthd = nv04_disp_mthd, |
115 | .ntfy = nvkm_disp_ntfy, | 115 | .ntfy = nvkm_disp_ntfy, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index f1358a564e3e..dda7a7d224c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c | |||
@@ -882,6 +882,7 @@ static const struct nvkm_enum gf100_mp_warp_error[] = { | |||
882 | { 0x0d, "GPR_OUT_OF_BOUNDS" }, | 882 | { 0x0d, "GPR_OUT_OF_BOUNDS" }, |
883 | { 0x0e, "MEM_OUT_OF_BOUNDS" }, | 883 | { 0x0e, "MEM_OUT_OF_BOUNDS" }, |
884 | { 0x0f, "UNALIGNED_MEM_ACCESS" }, | 884 | { 0x0f, "UNALIGNED_MEM_ACCESS" }, |
885 | { 0x10, "INVALID_ADDR_SPACE" }, | ||
885 | { 0x11, "INVALID_PARAM" }, | 886 | { 0x11, "INVALID_PARAM" }, |
886 | {} | 887 | {} |
887 | }; | 888 | }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index d13187409d68..d081ee41fc14 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c | |||
@@ -98,6 +98,7 @@ gf110_gr = { | |||
98 | { -1, -1, FERMI_B, &gf100_fermi }, | 98 | { -1, -1, FERMI_B, &gf100_fermi }, |
99 | { -1, -1, FERMI_C, &gf100_fermi }, | 99 | { -1, -1, FERMI_C, &gf100_fermi }, |
100 | { -1, -1, FERMI_COMPUTE_A }, | 100 | { -1, -1, FERMI_COMPUTE_A }, |
101 | { -1, -1, FERMI_COMPUTE_B }, | ||
101 | {} | 102 | {} |
102 | } | 103 | } |
103 | }; | 104 | }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index 28483d8bf3d2..d8e8af4d3b30 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c | |||
@@ -135,6 +135,7 @@ gf117_gr = { | |||
135 | { -1, -1, FERMI_B, &gf100_fermi }, | 135 | { -1, -1, FERMI_B, &gf100_fermi }, |
136 | { -1, -1, FERMI_C, &gf100_fermi }, | 136 | { -1, -1, FERMI_C, &gf100_fermi }, |
137 | { -1, -1, FERMI_COMPUTE_A }, | 137 | { -1, -1, FERMI_COMPUTE_A }, |
138 | { -1, -1, FERMI_COMPUTE_B }, | ||
138 | {} | 139 | {} |
139 | } | 140 | } |
140 | }; | 141 | }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index 9811a72e0313..01faf9a73774 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c | |||
@@ -189,6 +189,7 @@ gf119_gr = { | |||
189 | { -1, -1, FERMI_B, &gf100_fermi }, | 189 | { -1, -1, FERMI_B, &gf100_fermi }, |
190 | { -1, -1, FERMI_C, &gf100_fermi }, | 190 | { -1, -1, FERMI_C, &gf100_fermi }, |
191 | { -1, -1, FERMI_COMPUTE_A }, | 191 | { -1, -1, FERMI_COMPUTE_A }, |
192 | { -1, -1, FERMI_COMPUTE_B }, | ||
192 | {} | 193 | {} |
193 | } | 194 | } |
194 | }; | 195 | }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index 0db9be202c42..2721592d3031 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | |||
@@ -633,7 +633,7 @@ nvkm_perfmon_dtor(struct nvkm_object *object) | |||
633 | return perfmon; | 633 | return perfmon; |
634 | } | 634 | } |
635 | 635 | ||
636 | static struct nvkm_object_func | 636 | static const struct nvkm_object_func |
637 | nvkm_perfmon = { | 637 | nvkm_perfmon = { |
638 | .dtor = nvkm_perfmon_dtor, | 638 | .dtor = nvkm_perfmon_dtor, |
639 | .mthd = nvkm_perfmon_mthd, | 639 | .mthd = nvkm_perfmon_mthd, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c index 441ec451b788..c268e5afe852 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/pmu.c | |||
@@ -62,19 +62,6 @@ nvbios_pmuTe(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) | |||
62 | } | 62 | } |
63 | 63 | ||
64 | u32 | 64 | u32 |
65 | nvbios_pmuTp(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | ||
66 | struct nvbios_pmuT *info) | ||
67 | { | ||
68 | u32 data = nvbios_pmuTe(bios, ver, hdr, cnt, len); | ||
69 | memset(info, 0x00, sizeof(*info)); | ||
70 | switch (!!data * *ver) { | ||
71 | default: | ||
72 | break; | ||
73 | } | ||
74 | return data; | ||
75 | } | ||
76 | |||
77 | u32 | ||
78 | nvbios_pmuEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr) | 65 | nvbios_pmuEe(struct nvkm_bios *bios, int idx, u8 *ver, u8 *hdr) |
79 | { | 66 | { |
80 | u8 cnt, len; | 67 | u8 cnt, len; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c index f0e1fc74a52e..d0ae7454764e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c | |||
@@ -171,6 +171,7 @@ nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx, | |||
171 | p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x03) & 0x04) >> 2; | 171 | p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x03) & 0x04) >> 2; |
172 | p->ramcfg_00_03_08 = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3; | 172 | p->ramcfg_00_03_08 = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3; |
173 | p->ramcfg_RON = (nvbios_rd08(bios, data + 0x03) & 0x10) >> 3; | 173 | p->ramcfg_RON = (nvbios_rd08(bios, data + 0x03) & 0x10) >> 3; |
174 | p->ramcfg_FBVDDQ = (nvbios_rd08(bios, data + 0x03) & 0x80) >> 7; | ||
174 | p->ramcfg_00_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1; | 175 | p->ramcfg_00_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1; |
175 | p->ramcfg_00_04_04 = (nvbios_rd08(bios, data + 0x04) & 0x04) >> 2; | 176 | p->ramcfg_00_04_04 = (nvbios_rd08(bios, data + 0x04) & 0x04) >> 2; |
176 | p->ramcfg_00_04_20 = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5; | 177 | p->ramcfg_00_04_20 = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5; |
@@ -205,6 +206,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data, | |||
205 | p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6; | 206 | p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x02) & 0x40) >> 6; |
206 | p->ramcfg_10_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0; | 207 | p->ramcfg_10_03_0f = (nvbios_rd08(bios, data + 0x03) & 0x0f) >> 0; |
207 | p->ramcfg_10_04_01 = (nvbios_rd08(bios, data + 0x04) & 0x01) >> 0; | 208 | p->ramcfg_10_04_01 = (nvbios_rd08(bios, data + 0x04) & 0x01) >> 0; |
209 | p->ramcfg_FBVDDQ = (nvbios_rd08(bios, data + 0x04) & 0x08) >> 3; | ||
208 | p->ramcfg_10_05 = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0; | 210 | p->ramcfg_10_05 = (nvbios_rd08(bios, data + 0x05) & 0xff) >> 0; |
209 | p->ramcfg_10_06 = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0; | 211 | p->ramcfg_10_06 = (nvbios_rd08(bios, data + 0x06) & 0xff) >> 0; |
210 | p->ramcfg_10_07 = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0; | 212 | p->ramcfg_10_07 = (nvbios_rd08(bios, data + 0x07) & 0xff) >> 0; |
@@ -219,7 +221,7 @@ nvbios_rammapSp(struct nvkm_bios *bios, u32 data, | |||
219 | p->ramcfg_11_01_04 = (nvbios_rd08(bios, data + 0x01) & 0x04) >> 2; | 221 | p->ramcfg_11_01_04 = (nvbios_rd08(bios, data + 0x01) & 0x04) >> 2; |
220 | p->ramcfg_11_01_08 = (nvbios_rd08(bios, data + 0x01) & 0x08) >> 3; | 222 | p->ramcfg_11_01_08 = (nvbios_rd08(bios, data + 0x01) & 0x08) >> 3; |
221 | p->ramcfg_11_01_10 = (nvbios_rd08(bios, data + 0x01) & 0x10) >> 4; | 223 | p->ramcfg_11_01_10 = (nvbios_rd08(bios, data + 0x01) & 0x10) >> 4; |
222 | p->ramcfg_11_01_20 = (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5; | 224 | p->ramcfg_DLLoff = (nvbios_rd08(bios, data + 0x01) & 0x20) >> 5; |
223 | p->ramcfg_11_01_40 = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6; | 225 | p->ramcfg_11_01_40 = (nvbios_rd08(bios, data + 0x01) & 0x40) >> 6; |
224 | p->ramcfg_11_01_80 = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7; | 226 | p->ramcfg_11_01_80 = (nvbios_rd08(bios, data + 0x01) & 0x80) >> 7; |
225 | p->ramcfg_11_02_03 = (nvbios_rd08(bios, data + 0x02) & 0x03) >> 0; | 227 | p->ramcfg_11_02_03 = (nvbios_rd08(bios, data + 0x02) & 0x03) >> 0; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c index 615804c3887b..6e0a33648be9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/volt.c | |||
@@ -73,15 +73,19 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | |||
73 | memset(info, 0x00, sizeof(*info)); | 73 | memset(info, 0x00, sizeof(*info)); |
74 | switch (!!volt * *ver) { | 74 | switch (!!volt * *ver) { |
75 | case 0x12: | 75 | case 0x12: |
76 | info->type = NVBIOS_VOLT_GPIO; | ||
76 | info->vidmask = nvbios_rd08(bios, volt + 0x04); | 77 | info->vidmask = nvbios_rd08(bios, volt + 0x04); |
77 | break; | 78 | break; |
78 | case 0x20: | 79 | case 0x20: |
80 | info->type = NVBIOS_VOLT_GPIO; | ||
79 | info->vidmask = nvbios_rd08(bios, volt + 0x05); | 81 | info->vidmask = nvbios_rd08(bios, volt + 0x05); |
80 | break; | 82 | break; |
81 | case 0x30: | 83 | case 0x30: |
84 | info->type = NVBIOS_VOLT_GPIO; | ||
82 | info->vidmask = nvbios_rd08(bios, volt + 0x04); | 85 | info->vidmask = nvbios_rd08(bios, volt + 0x04); |
83 | break; | 86 | break; |
84 | case 0x40: | 87 | case 0x40: |
88 | info->type = NVBIOS_VOLT_GPIO; | ||
85 | info->base = nvbios_rd32(bios, volt + 0x04); | 89 | info->base = nvbios_rd32(bios, volt + 0x04); |
86 | info->step = nvbios_rd16(bios, volt + 0x08); | 90 | info->step = nvbios_rd16(bios, volt + 0x08); |
87 | info->vidmask = nvbios_rd08(bios, volt + 0x0b); | 91 | info->vidmask = nvbios_rd08(bios, volt + 0x0b); |
@@ -90,11 +94,20 @@ nvbios_volt_parse(struct nvkm_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, | |||
90 | info->max = info->base; | 94 | info->max = info->base; |
91 | break; | 95 | break; |
92 | case 0x50: | 96 | case 0x50: |
93 | info->vidmask = nvbios_rd08(bios, volt + 0x06); | ||
94 | info->min = nvbios_rd32(bios, volt + 0x0a); | 97 | info->min = nvbios_rd32(bios, volt + 0x0a); |
95 | info->max = nvbios_rd32(bios, volt + 0x0e); | 98 | info->max = nvbios_rd32(bios, volt + 0x0e); |
96 | info->base = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff; | 99 | info->base = nvbios_rd32(bios, volt + 0x12) & 0x00ffffff; |
97 | info->step = nvbios_rd16(bios, volt + 0x16); | 100 | |
101 | /* offset 4 seems to be a flag byte */ | ||
102 | if (nvbios_rd32(bios, volt + 0x4) & 1) { | ||
103 | info->type = NVBIOS_VOLT_PWM; | ||
104 | info->pwm_freq = nvbios_rd32(bios, volt + 0x5) / 1000; | ||
105 | info->pwm_range = nvbios_rd32(bios, volt + 0x16); | ||
106 | } else { | ||
107 | info->type = NVBIOS_VOLT_GPIO; | ||
108 | info->vidmask = nvbios_rd08(bios, volt + 0x06); | ||
109 | info->step = nvbios_rd16(bios, volt + 0x16); | ||
110 | } | ||
98 | break; | 111 | break; |
99 | } | 112 | } |
100 | return volt; | 113 | return volt; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c index 79f1cf513b36..2a5668938f2f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.c | |||
@@ -132,6 +132,38 @@ nvkm_hwsq_wait(struct nvkm_hwsq *hwsq, u8 flag, u8 data) | |||
132 | } | 132 | } |
133 | 133 | ||
134 | void | 134 | void |
135 | nvkm_hwsq_wait_vblank(struct nvkm_hwsq *hwsq) | ||
136 | { | ||
137 | struct nvkm_subdev *subdev = hwsq->subdev; | ||
138 | struct nvkm_device *device = subdev->device; | ||
139 | u32 heads, x, y, px = 0; | ||
140 | int i, head_sync; | ||
141 | |||
142 | heads = nvkm_rd32(device, 0x610050); | ||
143 | for (i = 0; i < 2; i++) { | ||
144 | /* Heuristic: sync to head with biggest resolution */ | ||
145 | if (heads & (2 << (i << 3))) { | ||
146 | x = nvkm_rd32(device, 0x610b40 + (0x540 * i)); | ||
147 | y = (x & 0xffff0000) >> 16; | ||
148 | x &= 0x0000ffff; | ||
149 | if ((x * y) > px) { | ||
150 | px = (x * y); | ||
151 | head_sync = i; | ||
152 | } | ||
153 | } | ||
154 | } | ||
155 | |||
156 | if (px == 0) { | ||
157 | nvkm_debug(subdev, "WAIT VBLANK !NO ACTIVE HEAD\n"); | ||
158 | return; | ||
159 | } | ||
160 | |||
161 | nvkm_debug(subdev, "WAIT VBLANK HEAD%d\n", head_sync); | ||
162 | nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x0); | ||
163 | nvkm_hwsq_wait(hwsq, head_sync ? 0x3 : 0x1, 0x1); | ||
164 | } | ||
165 | |||
166 | void | ||
135 | nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec) | 167 | nvkm_hwsq_nsec(struct nvkm_hwsq *hwsq, u32 nsec) |
136 | { | 168 | { |
137 | u8 shift = 0, usec = nsec / 1000; | 169 | u8 shift = 0, usec = nsec / 1000; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h index 8117ec5a1468..54ec3b131dfd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bus/hwsq.h | |||
@@ -134,6 +134,12 @@ hwsq_wait(struct hwsq *ram, u8 flag, u8 data) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | static inline void | 136 | static inline void |
137 | hwsq_wait_vblank(struct hwsq *ram) | ||
138 | { | ||
139 | nvkm_hwsq_wait_vblank(ram->hwsq); | ||
140 | } | ||
141 | |||
142 | static inline void | ||
137 | hwsq_nsec(struct hwsq *ram, u32 nsec) | 143 | hwsq_nsec(struct hwsq *ram, u32 nsec) |
138 | { | 144 | { |
139 | nvkm_hwsq_nsec(ram->hwsq, nsec); | 145 | nvkm_hwsq_nsec(ram->hwsq, nsec); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c index 347da9ee20f5..f97e3ec196bb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/g84.c | |||
@@ -44,5 +44,5 @@ int | |||
44 | g84_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) | 44 | g84_clk_new(struct nvkm_device *device, int index, struct nvkm_clk **pclk) |
45 | { | 45 | { |
46 | return nv50_clk_new_(&g84_clk, device, index, | 46 | return nv50_clk_new_(&g84_clk, device, index, |
47 | (device->chipset == 0xa0), pclk); | 47 | (device->chipset >= 0x94), pclk); |
48 | } | 48 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c index 79b523aa52aa..60ece0a8a2e1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr3.c | |||
@@ -63,7 +63,7 @@ ramgddr3_wr_lo[] = { | |||
63 | { 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 }, | 63 | { 5, 2 }, { 7, 4 }, { 8, 5 }, { 9, 6 }, { 10, 7 }, |
64 | { 11, 0 }, { 13 , 1 }, | 64 | { 11, 0 }, { 13 , 1 }, |
65 | /* the below are mentioned in some, but not all, gddr3 docs */ | 65 | /* the below are mentioned in some, but not all, gddr3 docs */ |
66 | { 4, 1 }, { 6, 3 }, { 12, 1 }, | 66 | { 4, 0 }, { 6, 3 }, { 12, 1 }, |
67 | { -1 } | 67 | { -1 } |
68 | }; | 68 | }; |
69 | 69 | ||
@@ -87,15 +87,17 @@ nvkm_gddr3_calc(struct nvkm_ram *ram) | |||
87 | WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; | 87 | WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; |
88 | /* XXX: Get these values from the VBIOS instead */ | 88 | /* XXX: Get these values from the VBIOS instead */ |
89 | DLL = !(ram->mr[1] & 0x1); | 89 | DLL = !(ram->mr[1] & 0x1); |
90 | ODT = (ram->mr[1] & 0x004) >> 2 | | ||
91 | (ram->mr[1] & 0x040) >> 5 | | ||
92 | (ram->mr[1] & 0x200) >> 7; | ||
93 | RON = !(ram->mr[1] & 0x300) >> 8; | 90 | RON = !(ram->mr[1] & 0x300) >> 8; |
94 | break; | 91 | break; |
95 | default: | 92 | default: |
96 | return -ENOSYS; | 93 | return -ENOSYS; |
97 | } | 94 | } |
98 | 95 | ||
96 | if (ram->next->bios.timing_ver == 0x20 || | ||
97 | ram->next->bios.ramcfg_timing == 0xff) { | ||
98 | ODT = (ram->mr[1] & 0xc) >> 2; | ||
99 | } | ||
100 | |||
99 | hi = ram->mr[2] & 0x1; | 101 | hi = ram->mr[2] & 0x1; |
100 | CL = ramxlat(hi ? ramgddr3_cl_hi : ramgddr3_cl_lo, CL); | 102 | CL = ramxlat(hi ? ramgddr3_cl_hi : ramgddr3_cl_lo, CL); |
101 | WR = ramxlat(ramgddr3_wr_lo, WR); | 103 | WR = ramxlat(ramgddr3_wr_lo, WR); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c index 24f83b09e6a1..2cc074d3901a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gddr5.c | |||
@@ -38,11 +38,12 @@ nvkm_gddr5_calc(struct nvkm_ram *ram, bool nuts) | |||
38 | int WL, CL, WR, at[2], dt, ds; | 38 | int WL, CL, WR, at[2], dt, ds; |
39 | int rq = ram->freq < 1000000; /* XXX */ | 39 | int rq = ram->freq < 1000000; /* XXX */ |
40 | 40 | ||
41 | xd = !ram->next->bios.ramcfg_DLLoff; | ||
42 | |||
41 | switch (ram->next->bios.ramcfg_ver) { | 43 | switch (ram->next->bios.ramcfg_ver) { |
42 | case 0x11: | 44 | case 0x11: |
43 | pd = ram->next->bios.ramcfg_11_01_80; | 45 | pd = ram->next->bios.ramcfg_11_01_80; |
44 | lf = ram->next->bios.ramcfg_11_01_40; | 46 | lf = ram->next->bios.ramcfg_11_01_40; |
45 | xd = !ram->next->bios.ramcfg_11_01_20; | ||
46 | vh = ram->next->bios.ramcfg_11_02_10; | 47 | vh = ram->next->bios.ramcfg_11_02_10; |
47 | vr = ram->next->bios.ramcfg_11_02_04; | 48 | vr = ram->next->bios.ramcfg_11_02_04; |
48 | vo = ram->next->bios.ramcfg_11_06; | 49 | vo = ram->next->bios.ramcfg_11_06; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 989355622aac..9df45030ff9f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c | |||
@@ -673,6 +673,25 @@ gk104_ram_calc_gddr5(struct gk104_ram *ram, u32 freq) | |||
673 | * DDR3 | 673 | * DDR3 |
674 | ******************************************************************************/ | 674 | ******************************************************************************/ |
675 | 675 | ||
676 | static void | ||
677 | nvkm_sddr3_dll_reset(struct gk104_ramfuc *fuc) | ||
678 | { | ||
679 | ram_nuke(fuc, mr[0]); | ||
680 | ram_mask(fuc, mr[0], 0x100, 0x100); | ||
681 | ram_mask(fuc, mr[0], 0x100, 0x000); | ||
682 | } | ||
683 | |||
684 | static void | ||
685 | nvkm_sddr3_dll_disable(struct gk104_ramfuc *fuc) | ||
686 | { | ||
687 | u32 mr1_old = ram_rd32(fuc, mr[1]); | ||
688 | |||
689 | if (!(mr1_old & 0x1)) { | ||
690 | ram_mask(fuc, mr[1], 0x1, 0x1); | ||
691 | ram_nsec(fuc, 1000); | ||
692 | } | ||
693 | } | ||
694 | |||
676 | static int | 695 | static int |
677 | gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) | 696 | gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) |
678 | { | 697 | { |
@@ -702,6 +721,10 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) | |||
702 | ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000); | 721 | ram_mask(fuc, 0x10f808, 0x04000000, 0x04000000); |
703 | 722 | ||
704 | ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ | 723 | ram_wr32(fuc, 0x10f314, 0x00000001); /* PRECHARGE */ |
724 | |||
725 | if (next->bios.ramcfg_DLLoff) | ||
726 | nvkm_sddr3_dll_disable(fuc); | ||
727 | |||
705 | ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */ | 728 | ram_wr32(fuc, 0x10f210, 0x00000000); /* REFRESH_AUTO = 0 */ |
706 | ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ | 729 | ram_wr32(fuc, 0x10f310, 0x00000001); /* REFRESH */ |
707 | ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); | 730 | ram_mask(fuc, 0x10f200, 0x80000000, 0x80000000); |
@@ -879,17 +902,20 @@ gk104_ram_calc_sddr3(struct gk104_ram *ram, u32 freq) | |||
879 | ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */ | 902 | ram_wr32(fuc, 0x10f210, 0x80000000); /* REFRESH_AUTO = 1 */ |
880 | ram_nsec(fuc, 1000); | 903 | ram_nsec(fuc, 1000); |
881 | 904 | ||
882 | ram_nuke(fuc, mr[0]); | 905 | if (!next->bios.ramcfg_DLLoff) { |
883 | ram_mask(fuc, mr[0], 0x100, 0x100); | 906 | ram_mask(fuc, mr[1], 0x1, 0x0); |
884 | ram_mask(fuc, mr[0], 0x100, 0x000); | 907 | nvkm_sddr3_dll_reset(fuc); |
908 | } | ||
885 | 909 | ||
886 | ram_mask(fuc, mr[2], 0xfff, ram->base.mr[2]); | 910 | ram_mask(fuc, mr[2], 0x00000fff, ram->base.mr[2]); |
911 | ram_mask(fuc, mr[1], 0xffffffff, ram->base.mr[1]); | ||
887 | ram_wr32(fuc, mr[0], ram->base.mr[0]); | 912 | ram_wr32(fuc, mr[0], ram->base.mr[0]); |
888 | ram_nsec(fuc, 1000); | 913 | ram_nsec(fuc, 1000); |
889 | 914 | ||
890 | ram_nuke(fuc, mr[0]); | 915 | if (!next->bios.ramcfg_DLLoff) { |
891 | ram_mask(fuc, mr[0], 0x100, 0x100); | 916 | nvkm_sddr3_dll_reset(fuc); |
892 | ram_mask(fuc, mr[0], 0x100, 0x000); | 917 | ram_nsec(fuc, 1000); |
918 | } | ||
893 | 919 | ||
894 | if (vc == 0 && ram_have(fuc, gpio2E)) { | 920 | if (vc == 0 && ram_have(fuc, gpio2E)) { |
895 | u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]); | 921 | u32 temp = ram_mask(fuc, gpio2E, 0x3000, fuc->r_func2E[0]); |
@@ -945,6 +971,67 @@ gk104_ram_calc_data(struct gk104_ram *ram, u32 khz, struct nvkm_ram_data *data) | |||
945 | } | 971 | } |
946 | 972 | ||
947 | static int | 973 | static int |
974 | gk104_calc_pll_output(int fN, int M, int N, int P, int clk) | ||
975 | { | ||
976 | return ((clk * N) + (((u16)(fN + 4096) * clk) >> 13)) / (M * P); | ||
977 | } | ||
978 | |||
979 | static int | ||
980 | gk104_pll_calc_hiclk(int target_khz, int crystal, | ||
981 | int *N1, int *fN1, int *M1, int *P1, | ||
982 | int *N2, int *M2, int *P2) | ||
983 | { | ||
984 | int best_clk = 0, best_err = target_khz, p_ref, n_ref; | ||
985 | bool upper = false; | ||
986 | |||
987 | *M1 = 1; | ||
988 | /* M has to be 1, otherwise it gets unstable */ | ||
989 | *M2 = 1; | ||
990 | /* can be 1 or 2, sticking with 1 for simplicity */ | ||
991 | *P2 = 1; | ||
992 | |||
993 | for (p_ref = 0x7; p_ref >= 0x5; --p_ref) { | ||
994 | for (n_ref = 0x25; n_ref <= 0x2b; ++n_ref) { | ||
995 | int cur_N, cur_clk, cur_err; | ||
996 | |||
997 | cur_clk = gk104_calc_pll_output(0, 1, n_ref, p_ref, crystal); | ||
998 | cur_N = target_khz / cur_clk; | ||
999 | cur_err = target_khz | ||
1000 | - gk104_calc_pll_output(0xf000, 1, cur_N, 1, cur_clk); | ||
1001 | |||
1002 | /* we found a better combination */ | ||
1003 | if (cur_err < best_err) { | ||
1004 | best_err = cur_err; | ||
1005 | best_clk = cur_clk; | ||
1006 | *N2 = cur_N; | ||
1007 | *N1 = n_ref; | ||
1008 | *P1 = p_ref; | ||
1009 | upper = false; | ||
1010 | } | ||
1011 | |||
1012 | cur_N += 1; | ||
1013 | cur_err = gk104_calc_pll_output(0xf000, 1, cur_N, 1, cur_clk) | ||
1014 | - target_khz; | ||
1015 | if (cur_err < best_err) { | ||
1016 | best_err = cur_err; | ||
1017 | best_clk = cur_clk; | ||
1018 | *N2 = cur_N; | ||
1019 | *N1 = n_ref; | ||
1020 | *P1 = p_ref; | ||
1021 | upper = true; | ||
1022 | } | ||
1023 | } | ||
1024 | } | ||
1025 | |||
1026 | /* adjust fN to get closer to the target clock */ | ||
1027 | *fN1 = (u16)((((best_err / *N2 * *P2) * (*P1 * *M1)) << 13) / crystal); | ||
1028 | if (upper) | ||
1029 | *fN1 = (u16)(1 - *fN1); | ||
1030 | |||
1031 | return gk104_calc_pll_output(*fN1, 1, *N1, *P1, crystal); | ||
1032 | } | ||
1033 | |||
1034 | static int | ||
948 | gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next) | 1035 | gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next) |
949 | { | 1036 | { |
950 | struct gk104_ramfuc *fuc = &ram->fuc; | 1037 | struct gk104_ramfuc *fuc = &ram->fuc; |
@@ -968,31 +1055,24 @@ gk104_ram_calc_xits(struct gk104_ram *ram, struct nvkm_ram_data *next) | |||
968 | * kepler boards, no idea how/why they're chosen. | 1055 | * kepler boards, no idea how/why they're chosen. |
969 | */ | 1056 | */ |
970 | refclk = next->freq; | 1057 | refclk = next->freq; |
971 | if (ram->mode == 2) | ||
972 | refclk = fuc->mempll.refclk; | ||
973 | |||
974 | /* calculate refpll coefficients */ | ||
975 | ret = gt215_pll_calc(subdev, &fuc->refpll, refclk, &ram->N1, | ||
976 | &ram->fN1, &ram->M1, &ram->P1); | ||
977 | fuc->mempll.refclk = ret; | ||
978 | if (ret <= 0) { | ||
979 | nvkm_error(subdev, "unable to calc refpll\n"); | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | /* calculate mempll coefficients, if we're using it */ | ||
984 | if (ram->mode == 2) { | 1058 | if (ram->mode == 2) { |
985 | /* post-divider doesn't work... the reg takes the values but | 1059 | ret = gk104_pll_calc_hiclk(next->freq, subdev->device->crystal, |
986 | * appears to completely ignore it. there *is* a bit at | 1060 | &ram->N1, &ram->fN1, &ram->M1, &ram->P1, |
987 | * bit 28 that appears to divide the clock by 2 if set. | 1061 | &ram->N2, &ram->M2, &ram->P2); |
988 | */ | 1062 | fuc->mempll.refclk = ret; |
989 | fuc->mempll.min_p = 1; | 1063 | if (ret <= 0) { |
990 | fuc->mempll.max_p = 2; | 1064 | nvkm_error(subdev, "unable to calc plls\n"); |
991 | 1065 | return -EINVAL; | |
992 | ret = gt215_pll_calc(subdev, &fuc->mempll, next->freq, | 1066 | } |
993 | &ram->N2, NULL, &ram->M2, &ram->P2); | 1067 | nvkm_debug(subdev, "sucessfully calced PLLs for clock %i kHz" |
1068 | " (refclock: %i kHz)\n", next->freq, ret); | ||
1069 | } else { | ||
1070 | /* calculate refpll coefficients */ | ||
1071 | ret = gt215_pll_calc(subdev, &fuc->refpll, refclk, &ram->N1, | ||
1072 | &ram->fN1, &ram->M1, &ram->P1); | ||
1073 | fuc->mempll.refclk = ret; | ||
994 | if (ret <= 0) { | 1074 | if (ret <= 0) { |
995 | nvkm_error(subdev, "unable to calc mempll\n"); | 1075 | nvkm_error(subdev, "unable to calc refpll\n"); |
996 | return -EINVAL; | 1076 | return -EINVAL; |
997 | } | 1077 | } |
998 | } | 1078 | } |
@@ -1600,6 +1680,7 @@ gk104_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) | |||
1600 | break; | 1680 | break; |
1601 | case NVKM_RAM_TYPE_DDR3: | 1681 | case NVKM_RAM_TYPE_DDR3: |
1602 | ram->fuc.r_mr[0] = ramfuc_reg(0x10f300); | 1682 | ram->fuc.r_mr[0] = ramfuc_reg(0x10f300); |
1683 | ram->fuc.r_mr[1] = ramfuc_reg(0x10f304); | ||
1603 | ram->fuc.r_mr[2] = ramfuc_reg(0x10f320); | 1684 | ram->fuc.r_mr[2] = ramfuc_reg(0x10f320); |
1604 | break; | 1685 | break; |
1605 | default: | 1686 | default: |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c index 5c08ae8023fa..d15ea886df27 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #include <subdev/clk/gt215.h> | 34 | #include <subdev/clk/gt215.h> |
35 | #include <subdev/gpio.h> | 35 | #include <subdev/gpio.h> |
36 | 36 | ||
37 | /* XXX: Remove when memx gains GPIO support */ | ||
38 | extern int nv50_gpio_location(int line, u32 *reg, u32 *shift); | ||
39 | |||
40 | struct gt215_ramfuc { | 37 | struct gt215_ramfuc { |
41 | struct ramfuc base; | 38 | struct ramfuc base; |
42 | struct ramfuc_reg r_0x001610; | 39 | struct ramfuc_reg r_0x001610; |
@@ -75,7 +72,7 @@ struct gt215_ramfuc { | |||
75 | struct ramfuc_reg r_0x111400; | 72 | struct ramfuc_reg r_0x111400; |
76 | struct ramfuc_reg r_0x611200; | 73 | struct ramfuc_reg r_0x611200; |
77 | struct ramfuc_reg r_mr[4]; | 74 | struct ramfuc_reg r_mr[4]; |
78 | struct ramfuc_reg r_gpioFBVREF; | 75 | struct ramfuc_reg r_gpio[4]; |
79 | }; | 76 | }; |
80 | 77 | ||
81 | struct gt215_ltrain { | 78 | struct gt215_ltrain { |
@@ -466,24 +463,27 @@ gt215_ram_lock_pll(struct gt215_ramfuc *fuc, struct gt215_clk_info *mclk) | |||
466 | } | 463 | } |
467 | 464 | ||
468 | static void | 465 | static void |
469 | gt215_ram_fbvref(struct gt215_ramfuc *fuc, u32 val) | 466 | gt215_ram_gpio(struct gt215_ramfuc *fuc, u8 tag, u32 val) |
470 | { | 467 | { |
471 | struct nvkm_gpio *gpio = fuc->base.fb->subdev.device->gpio; | 468 | struct nvkm_gpio *gpio = fuc->base.fb->subdev.device->gpio; |
472 | struct dcb_gpio_func func; | 469 | struct dcb_gpio_func func; |
473 | u32 reg, sh, gpio_val; | 470 | u32 reg, sh, gpio_val; |
474 | int ret; | 471 | int ret; |
475 | 472 | ||
476 | if (nvkm_gpio_get(gpio, 0, 0x2e, DCB_GPIO_UNUSED) != val) { | 473 | if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) { |
477 | ret = nvkm_gpio_find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); | 474 | ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func); |
478 | if (ret) | 475 | if (ret) |
479 | return; | 476 | return; |
480 | 477 | ||
481 | nv50_gpio_location(func.line, ®, &sh); | 478 | reg = func.line >> 3; |
482 | gpio_val = ram_rd32(fuc, gpioFBVREF); | 479 | sh = (func.line & 0x7) << 2; |
480 | gpio_val = ram_rd32(fuc, gpio[reg]); | ||
483 | if (gpio_val & (8 << sh)) | 481 | if (gpio_val & (8 << sh)) |
484 | val = !val; | 482 | val = !val; |
483 | if (!(func.log[1] & 1)) | ||
484 | val = !val; | ||
485 | 485 | ||
486 | ram_mask(fuc, gpioFBVREF, (0x3 << sh), ((val | 0x2) << sh)); | 486 | ram_mask(fuc, gpio[reg], (0x3 << sh), ((val | 0x2) << sh)); |
487 | ram_nsec(fuc, 20000); | 487 | ram_nsec(fuc, 20000); |
488 | } | 488 | } |
489 | } | 489 | } |
@@ -498,6 +498,7 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq) | |||
498 | struct nvkm_device *device = subdev->device; | 498 | struct nvkm_device *device = subdev->device; |
499 | struct nvkm_bios *bios = device->bios; | 499 | struct nvkm_bios *bios = device->bios; |
500 | struct gt215_clk_info mclk; | 500 | struct gt215_clk_info mclk; |
501 | struct nvkm_gpio *gpio = device->gpio; | ||
501 | struct nvkm_ram_data *next; | 502 | struct nvkm_ram_data *next; |
502 | u8 ver, hdr, cnt, len, strap; | 503 | u8 ver, hdr, cnt, len, strap; |
503 | u32 data; | 504 | u32 data; |
@@ -642,8 +643,8 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq) | |||
642 | break; | 643 | break; |
643 | } | 644 | } |
644 | 645 | ||
645 | if (fuc->r_gpioFBVREF.addr && next->bios.timing_10_ODT) | 646 | if (next->bios.timing_10_ODT) |
646 | gt215_ram_fbvref(fuc, 0); | 647 | gt215_ram_gpio(fuc, 0x2e, 1); |
647 | 648 | ||
648 | /* Brace RAM for impact */ | 649 | /* Brace RAM for impact */ |
649 | ram_wr32(fuc, 0x1002d4, 0x00000001); | 650 | ram_wr32(fuc, 0x1002d4, 0x00000001); |
@@ -656,6 +657,23 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq) | |||
656 | if (device->chipset == 0xa3 && freq <= 500000) | 657 | if (device->chipset == 0xa3 && freq <= 500000) |
657 | ram_mask(fuc, 0x100700, 0x00000006, 0x00000006); | 658 | ram_mask(fuc, 0x100700, 0x00000006, 0x00000006); |
658 | 659 | ||
660 | /* Alter FBVDD/Q, apparently must be done with PLL disabled, thus | ||
661 | * set it to bypass */ | ||
662 | if (nvkm_gpio_get(gpio, 0, 0x18, DCB_GPIO_UNUSED) == | ||
663 | next->bios.ramcfg_FBVDDQ) { | ||
664 | data = ram_rd32(fuc, 0x004000) & 0x9; | ||
665 | |||
666 | if (data == 0x1) | ||
667 | ram_mask(fuc, 0x004000, 0x8, 0x8); | ||
668 | if (data & 0x1) | ||
669 | ram_mask(fuc, 0x004000, 0x1, 0x0); | ||
670 | |||
671 | gt215_ram_gpio(fuc, 0x18, !next->bios.ramcfg_FBVDDQ); | ||
672 | |||
673 | if (data & 0x1) | ||
674 | ram_mask(fuc, 0x004000, 0x1, 0x1); | ||
675 | } | ||
676 | |||
659 | /* Fiddle with clocks */ | 677 | /* Fiddle with clocks */ |
660 | /* There's 4 scenario's | 678 | /* There's 4 scenario's |
661 | * pll->pll: first switch to a 324MHz clock, set up new PLL, switch | 679 | * pll->pll: first switch to a 324MHz clock, set up new PLL, switch |
@@ -753,39 +771,43 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq) | |||
753 | unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100; | 771 | unk71c = ram_rd32(fuc, 0x10071c) & ~0x00000100; |
754 | r111100 = ram_rd32(fuc, 0x111100) & ~0x3a800000; | 772 | r111100 = ram_rd32(fuc, 0x111100) & ~0x3a800000; |
755 | 773 | ||
756 | if (next->bios.ramcfg_10_02_04) { | 774 | /* NVA8 seems to skip various bits related to ramcfg_10_02_04 */ |
757 | switch (ram->base.type) { | 775 | if (device->chipset == 0xa8) { |
758 | case NVKM_RAM_TYPE_DDR3: | 776 | r111100 |= 0x08000000; |
759 | if (device->chipset != 0xa8) | 777 | if (!next->bios.ramcfg_10_02_04) |
760 | r111100 |= 0x00000004; | ||
761 | /* no break */ | ||
762 | case NVKM_RAM_TYPE_DDR2: | ||
763 | r111100 |= 0x08000000; | ||
764 | break; | ||
765 | default: | ||
766 | break; | ||
767 | } | ||
768 | } else { | ||
769 | switch (ram->base.type) { | ||
770 | case NVKM_RAM_TYPE_DDR2: | ||
771 | r111100 |= 0x1a800000; | ||
772 | unk714 |= 0x00000010; | 778 | unk714 |= 0x00000010; |
773 | break; | 779 | } else { |
774 | case NVKM_RAM_TYPE_DDR3: | 780 | if (next->bios.ramcfg_10_02_04) { |
775 | if (device->chipset == 0xa8) { | 781 | switch (ram->base.type) { |
776 | r111100 |= 0x08000000; | 782 | case NVKM_RAM_TYPE_DDR2: |
777 | } else { | 783 | case NVKM_RAM_TYPE_DDR3: |
778 | r111100 &= ~0x00000004; | 784 | r111100 &= ~0x00000020; |
785 | if (next->bios.ramcfg_10_02_10) | ||
786 | r111100 |= 0x08000004; | ||
787 | else | ||
788 | r111100 |= 0x00000024; | ||
789 | break; | ||
790 | default: | ||
791 | break; | ||
792 | } | ||
793 | } else { | ||
794 | switch (ram->base.type) { | ||
795 | case NVKM_RAM_TYPE_DDR2: | ||
796 | case NVKM_RAM_TYPE_DDR3: | ||
797 | r111100 &= ~0x00000024; | ||
779 | r111100 |= 0x12800000; | 798 | r111100 |= 0x12800000; |
799 | |||
800 | if (next->bios.ramcfg_10_02_10) | ||
801 | r111100 |= 0x08000000; | ||
802 | unk714 |= 0x00000010; | ||
803 | break; | ||
804 | case NVKM_RAM_TYPE_GDDR3: | ||
805 | r111100 |= 0x30000000; | ||
806 | unk714 |= 0x00000020; | ||
807 | break; | ||
808 | default: | ||
809 | break; | ||
780 | } | 810 | } |
781 | unk714 |= 0x00000010; | ||
782 | break; | ||
783 | case NVKM_RAM_TYPE_GDDR3: | ||
784 | r111100 |= 0x30000000; | ||
785 | unk714 |= 0x00000020; | ||
786 | break; | ||
787 | default: | ||
788 | break; | ||
789 | } | 811 | } |
790 | } | 812 | } |
791 | 813 | ||
@@ -809,8 +831,8 @@ gt215_ram_calc(struct nvkm_ram *base, u32 freq) | |||
809 | ram_mask(fuc, 0x100718, 0xffffffff, unk718); | 831 | ram_mask(fuc, 0x100718, 0xffffffff, unk718); |
810 | ram_mask(fuc, 0x111100, 0xffffffff, r111100); | 832 | ram_mask(fuc, 0x111100, 0xffffffff, r111100); |
811 | 833 | ||
812 | if (fuc->r_gpioFBVREF.addr && !next->bios.timing_10_ODT) | 834 | if (!next->bios.timing_10_ODT) |
813 | gt215_ram_fbvref(fuc, 1); | 835 | gt215_ram_gpio(fuc, 0x2e, 0); |
814 | 836 | ||
815 | /* Reset DLL */ | 837 | /* Reset DLL */ |
816 | if (!next->bios.ramcfg_DLLoff) | 838 | if (!next->bios.ramcfg_DLLoff) |
@@ -919,10 +941,7 @@ gt215_ram_func = { | |||
919 | int | 941 | int |
920 | gt215_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) | 942 | gt215_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) |
921 | { | 943 | { |
922 | struct nvkm_gpio *gpio = fb->subdev.device->gpio; | ||
923 | struct dcb_gpio_func func; | ||
924 | struct gt215_ram *ram; | 944 | struct gt215_ram *ram; |
925 | u32 reg, shift; | ||
926 | int ret, i; | 945 | int ret, i; |
927 | 946 | ||
928 | if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) | 947 | if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) |
@@ -981,12 +1000,10 @@ gt215_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) | |||
981 | ram->fuc.r_mr[2] = ramfuc_reg(0x1002e0); | 1000 | ram->fuc.r_mr[2] = ramfuc_reg(0x1002e0); |
982 | ram->fuc.r_mr[3] = ramfuc_reg(0x1002e4); | 1001 | ram->fuc.r_mr[3] = ramfuc_reg(0x1002e4); |
983 | } | 1002 | } |
984 | 1003 | ram->fuc.r_gpio[0] = ramfuc_reg(0x00e104); | |
985 | ret = nvkm_gpio_find(gpio, 0, 0x2e, DCB_GPIO_UNUSED, &func); | 1004 | ram->fuc.r_gpio[1] = ramfuc_reg(0x00e108); |
986 | if (ret == 0) { | 1005 | ram->fuc.r_gpio[2] = ramfuc_reg(0x00e120); |
987 | nv50_gpio_location(func.line, ®, &shift); | 1006 | ram->fuc.r_gpio[3] = ramfuc_reg(0x00e124); |
988 | ram->fuc.r_gpioFBVREF = ramfuc_reg(reg); | ||
989 | } | ||
990 | 1007 | ||
991 | return 0; | 1008 | return 0; |
992 | } | 1009 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index 9197e0ef5cdb..87bde8ff2d6b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <subdev/bios/rammap.h> | 33 | #include <subdev/bios/rammap.h> |
34 | #include <subdev/bios/timing.h> | 34 | #include <subdev/bios/timing.h> |
35 | #include <subdev/clk/pll.h> | 35 | #include <subdev/clk/pll.h> |
36 | #include <subdev/gpio.h> | ||
36 | 37 | ||
37 | struct nv50_ramseq { | 38 | struct nv50_ramseq { |
38 | struct hwsq base; | 39 | struct hwsq base; |
@@ -59,6 +60,7 @@ struct nv50_ramseq { | |||
59 | struct hwsq_reg r_0x611200; | 60 | struct hwsq_reg r_0x611200; |
60 | struct hwsq_reg r_timing[9]; | 61 | struct hwsq_reg r_timing[9]; |
61 | struct hwsq_reg r_mr[4]; | 62 | struct hwsq_reg r_mr[4]; |
63 | struct hwsq_reg r_gpio[4]; | ||
62 | }; | 64 | }; |
63 | 65 | ||
64 | struct nv50_ram { | 66 | struct nv50_ram { |
@@ -144,6 +146,38 @@ nv50_ram_timing_calc(struct nv50_ram *ram, u32 *timing) | |||
144 | nvkm_debug(subdev, " 240: %08x\n", timing[8]); | 146 | nvkm_debug(subdev, " 240: %08x\n", timing[8]); |
145 | return 0; | 147 | return 0; |
146 | } | 148 | } |
149 | |||
150 | static int | ||
151 | nv50_ram_timing_read(struct nv50_ram *ram, u32 *timing) | ||
152 | { | ||
153 | unsigned int i; | ||
154 | struct nvbios_ramcfg *cfg = &ram->base.target.bios; | ||
155 | struct nvkm_subdev *subdev = &ram->base.fb->subdev; | ||
156 | struct nvkm_device *device = subdev->device; | ||
157 | |||
158 | for (i = 0; i <= 8; i++) | ||
159 | timing[i] = nvkm_rd32(device, 0x100220 + (i * 4)); | ||
160 | |||
161 | /* Derive the bare minimum for the MR calculation to succeed */ | ||
162 | cfg->timing_ver = 0x10; | ||
163 | T(CL) = (timing[3] & 0xff) + 1; | ||
164 | |||
165 | switch (ram->base.type) { | ||
166 | case NVKM_RAM_TYPE_DDR2: | ||
167 | T(CWL) = T(CL) - 1; | ||
168 | break; | ||
169 | case NVKM_RAM_TYPE_GDDR3: | ||
170 | T(CWL) = ((timing[2] & 0xff000000) >> 24) + 1; | ||
171 | break; | ||
172 | default: | ||
173 | return -ENOSYS; | ||
174 | break; | ||
175 | } | ||
176 | |||
177 | T(WR) = ((timing[1] >> 24) & 0xff) - 1 - T(CWL); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
147 | #undef T | 181 | #undef T |
148 | 182 | ||
149 | static void | 183 | static void |
@@ -154,6 +188,33 @@ nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq) | |||
154 | ram_nsec(hwsq, 24000); | 188 | ram_nsec(hwsq, 24000); |
155 | } | 189 | } |
156 | 190 | ||
191 | static void | ||
192 | nv50_ram_gpio(struct nv50_ramseq *hwsq, u8 tag, u32 val) | ||
193 | { | ||
194 | struct nvkm_gpio *gpio = hwsq->base.subdev->device->gpio; | ||
195 | struct dcb_gpio_func func; | ||
196 | u32 reg, sh, gpio_val; | ||
197 | int ret; | ||
198 | |||
199 | if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) { | ||
200 | ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func); | ||
201 | if (ret) | ||
202 | return; | ||
203 | |||
204 | reg = func.line >> 3; | ||
205 | sh = (func.line & 0x7) << 2; | ||
206 | gpio_val = ram_rd32(hwsq, gpio[reg]); | ||
207 | |||
208 | if (gpio_val & (8 << sh)) | ||
209 | val = !val; | ||
210 | if (!(func.log[1] & 1)) | ||
211 | val = !val; | ||
212 | |||
213 | ram_mask(hwsq, gpio[reg], (0x3 << sh), ((val | 0x2) << sh)); | ||
214 | ram_nsec(hwsq, 20000); | ||
215 | } | ||
216 | } | ||
217 | |||
157 | static int | 218 | static int |
158 | nv50_ram_calc(struct nvkm_ram *base, u32 freq) | 219 | nv50_ram_calc(struct nvkm_ram *base, u32 freq) |
159 | { | 220 | { |
@@ -213,10 +274,11 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
213 | strap, data, ver, hdr); | 274 | strap, data, ver, hdr); |
214 | return -EINVAL; | 275 | return -EINVAL; |
215 | } | 276 | } |
277 | nv50_ram_timing_calc(ram, timing); | ||
278 | } else { | ||
279 | nv50_ram_timing_read(ram, timing); | ||
216 | } | 280 | } |
217 | 281 | ||
218 | nv50_ram_timing_calc(ram, timing); | ||
219 | |||
220 | ret = ram_init(hwsq, subdev); | 282 | ret = ram_init(hwsq, subdev); |
221 | if (ret) | 283 | if (ret) |
222 | return ret; | 284 | return ret; |
@@ -235,14 +297,18 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
235 | break; | 297 | break; |
236 | } | 298 | } |
237 | 299 | ||
238 | if (ret) | 300 | if (ret) { |
301 | nvkm_error(subdev, "Could not calculate MR\n"); | ||
239 | return ret; | 302 | return ret; |
303 | } | ||
304 | |||
305 | if (subdev->device->chipset <= 0x96 && !next->bios.ramcfg_00_03_02) | ||
306 | ram_mask(hwsq, 0x100710, 0x00000200, 0x00000000); | ||
240 | 307 | ||
241 | /* Always disable this bit during reclock */ | 308 | /* Always disable this bit during reclock */ |
242 | ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000); | 309 | ram_mask(hwsq, 0x100200, 0x00000800, 0x00000000); |
243 | 310 | ||
244 | ram_wait(hwsq, 0x01, 0x00); /* wait for !vblank */ | 311 | ram_wait_vblank(hwsq); |
245 | ram_wait(hwsq, 0x01, 0x01); /* wait for vblank */ | ||
246 | ram_wr32(hwsq, 0x611200, 0x00003300); | 312 | ram_wr32(hwsq, 0x611200, 0x00003300); |
247 | ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */ | 313 | ram_wr32(hwsq, 0x002504, 0x00000001); /* block fifo */ |
248 | ram_nsec(hwsq, 8000); | 314 | ram_nsec(hwsq, 8000); |
@@ -250,6 +316,9 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
250 | ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ | 316 | ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */ |
251 | ram_nsec(hwsq, 2000); | 317 | ram_nsec(hwsq, 2000); |
252 | 318 | ||
319 | if (next->bios.timing_10_ODT) | ||
320 | nv50_ram_gpio(hwsq, 0x2e, 1); | ||
321 | |||
253 | ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */ | 322 | ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */ |
254 | ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ | 323 | ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ |
255 | ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ | 324 | ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */ |
@@ -286,8 +355,12 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
286 | next->bios.rammap_00_16_40 << 14); | 355 | next->bios.rammap_00_16_40 << 14); |
287 | ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); | 356 | ram_mask(hwsq, 0x00400c, 0x0000ffff, (N1 << 8) | M1); |
288 | ram_mask(hwsq, 0x004008, 0x91ff0000, r004008); | 357 | ram_mask(hwsq, 0x004008, 0x91ff0000, r004008); |
289 | if (subdev->device->chipset >= 0x96) | 358 | |
359 | /* XXX: GDDR3 only? */ | ||
360 | if (subdev->device->chipset >= 0x92) | ||
290 | ram_wr32(hwsq, 0x100da0, r100da0); | 361 | ram_wr32(hwsq, 0x100da0, r100da0); |
362 | |||
363 | nv50_ram_gpio(hwsq, 0x18, !next->bios.ramcfg_FBVDDQ); | ||
291 | ram_nsec(hwsq, 64000); /*XXX*/ | 364 | ram_nsec(hwsq, 64000); /*XXX*/ |
292 | ram_nsec(hwsq, 32000); /*XXX*/ | 365 | ram_nsec(hwsq, 32000); /*XXX*/ |
293 | 366 | ||
@@ -329,19 +402,33 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
329 | ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 << 12); | 402 | ram_mask(hwsq, 0x100200, 0x00001000, !next->bios.ramcfg_00_04_02 << 12); |
330 | 403 | ||
331 | /* XXX: A lot of this could be "chipset"/"ram type" specific stuff */ | 404 | /* XXX: A lot of this could be "chipset"/"ram type" specific stuff */ |
332 | unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000101; | 405 | unk710 = ram_rd32(hwsq, 0x100710) & ~0x00000100; |
333 | unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020; | 406 | unk714 = ram_rd32(hwsq, 0x100714) & ~0xf0000020; |
334 | unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100; | 407 | unk718 = ram_rd32(hwsq, 0x100718) & ~0x00000100; |
335 | unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100; | 408 | unk71c = ram_rd32(hwsq, 0x10071c) & ~0x00000100; |
409 | if (subdev->device->chipset <= 0x96) { | ||
410 | unk710 &= ~0x0000006e; | ||
411 | unk714 &= ~0x00000100; | ||
412 | |||
413 | if (!next->bios.ramcfg_00_03_08) | ||
414 | unk710 |= 0x00000060; | ||
415 | if (!next->bios.ramcfg_FBVDDQ) | ||
416 | unk714 |= 0x00000100; | ||
417 | if ( next->bios.ramcfg_00_04_04) | ||
418 | unk710 |= 0x0000000e; | ||
419 | } else { | ||
420 | unk710 &= ~0x00000001; | ||
421 | |||
422 | if (!next->bios.ramcfg_00_03_08) | ||
423 | unk710 |= 0x00000001; | ||
424 | } | ||
336 | 425 | ||
337 | if ( next->bios.ramcfg_00_03_01) | 426 | if ( next->bios.ramcfg_00_03_01) |
338 | unk71c |= 0x00000100; | 427 | unk71c |= 0x00000100; |
339 | if ( next->bios.ramcfg_00_03_02) | 428 | if ( next->bios.ramcfg_00_03_02) |
340 | unk710 |= 0x00000100; | 429 | unk710 |= 0x00000100; |
341 | if (!next->bios.ramcfg_00_03_08) { | 430 | if (!next->bios.ramcfg_00_03_08) |
342 | unk710 |= 0x1; | 431 | unk714 |= 0x00000020; |
343 | unk714 |= 0x20; | ||
344 | } | ||
345 | if ( next->bios.ramcfg_00_04_04) | 432 | if ( next->bios.ramcfg_00_04_04) |
346 | unk714 |= 0x70000000; | 433 | unk714 |= 0x70000000; |
347 | if ( next->bios.ramcfg_00_04_20) | 434 | if ( next->bios.ramcfg_00_04_20) |
@@ -352,6 +439,8 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
352 | ram_mask(hwsq, 0x100718, 0xffffffff, unk718); | 439 | ram_mask(hwsq, 0x100718, 0xffffffff, unk718); |
353 | ram_mask(hwsq, 0x100710, 0xffffffff, unk710); | 440 | ram_mask(hwsq, 0x100710, 0xffffffff, unk710); |
354 | 441 | ||
442 | /* XXX: G94 does not even test these regs in trace. Harmless we do it, | ||
443 | * but why is it omitted? */ | ||
355 | if (next->bios.rammap_00_16_20) { | 444 | if (next->bios.rammap_00_16_20) { |
356 | ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 | | 445 | ram_wr32(hwsq, 0x1005a0, next->bios.ramcfg_00_07 << 16 | |
357 | next->bios.ramcfg_00_06 << 8 | | 446 | next->bios.ramcfg_00_06 << 8 | |
@@ -364,6 +453,9 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
364 | } | 453 | } |
365 | ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]); | 454 | ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]); |
366 | 455 | ||
456 | if (!next->bios.timing_10_ODT) | ||
457 | nv50_ram_gpio(hwsq, 0x2e, 0); | ||
458 | |||
367 | /* Reset DLL */ | 459 | /* Reset DLL */ |
368 | if (!next->bios.ramcfg_DLLoff) | 460 | if (!next->bios.ramcfg_DLLoff) |
369 | nvkm_sddr2_dll_reset(hwsq); | 461 | nvkm_sddr2_dll_reset(hwsq); |
@@ -379,6 +471,8 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq) | |||
379 | ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000); | 471 | ram_mask(hwsq, 0x004008, 0x00004000, 0x00000000); |
380 | if (next->bios.ramcfg_00_03_02) | 472 | if (next->bios.ramcfg_00_03_02) |
381 | ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000); | 473 | ram_mask(hwsq, 0x10021c, 0x00010000, 0x00010000); |
474 | if (subdev->device->chipset <= 0x96 && next->bios.ramcfg_00_03_02) | ||
475 | ram_mask(hwsq, 0x100710, 0x00000200, 0x00000200); | ||
382 | 476 | ||
383 | return 0; | 477 | return 0; |
384 | } | 478 | } |
@@ -634,5 +728,10 @@ nv50_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) | |||
634 | ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4); | 728 | ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4); |
635 | } | 729 | } |
636 | 730 | ||
731 | ram->hwsq.r_gpio[0] = hwsq_reg(0x00e104); | ||
732 | ram->hwsq.r_gpio[1] = hwsq_reg(0x00e108); | ||
733 | ram->hwsq.r_gpio[2] = hwsq_reg(0x00e120); | ||
734 | ram->hwsq.r_gpio[3] = hwsq_reg(0x00e124); | ||
735 | |||
637 | return 0; | 736 | return 0; |
638 | } | 737 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h index 0f1f97ccd5f6..8df7306d5729 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramseq.h | |||
@@ -11,5 +11,6 @@ | |||
11 | #define ram_mask(s,r,m,d) hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d)) | 11 | #define ram_mask(s,r,m,d) hwsq_mask(&(s)->base, &(s)->r_##r, (m), (d)) |
12 | #define ram_setf(s,f,d) hwsq_setf(&(s)->base, (f), (d)) | 12 | #define ram_setf(s,f,d) hwsq_setf(&(s)->base, (f), (d)) |
13 | #define ram_wait(s,f,d) hwsq_wait(&(s)->base, (f), (d)) | 13 | #define ram_wait(s,f,d) hwsq_wait(&(s)->base, (f), (d)) |
14 | #define ram_wait_vblank(s) hwsq_wait_vblank(&(s)->base) | ||
14 | #define ram_nsec(s,n) hwsq_nsec(&(s)->base, (n)) | 15 | #define ram_nsec(s,n) hwsq_nsec(&(s)->base, (n)) |
15 | #endif | 16 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c index 86bf67456b14..b9f1ffdfc602 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr2.c | |||
@@ -76,6 +76,12 @@ nvkm_sddr2_calc(struct nvkm_ram *ram) | |||
76 | return -ENOSYS; | 76 | return -ENOSYS; |
77 | } | 77 | } |
78 | 78 | ||
79 | if (ram->next->bios.timing_ver == 0x20 || | ||
80 | ram->next->bios.ramcfg_timing == 0xff) { | ||
81 | ODT = (ram->mr[1] & 0x004) >> 2 | | ||
82 | (ram->mr[1] & 0x040) >> 5; | ||
83 | } | ||
84 | |||
79 | CL = ramxlat(ramddr2_cl, CL); | 85 | CL = ramxlat(ramddr2_cl, CL); |
80 | WR = ramxlat(ramddr2_wr, WR); | 86 | WR = ramxlat(ramddr2_wr, WR); |
81 | if (CL < 0 || WR < 0) | 87 | if (CL < 0 || WR < 0) |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c index b4edc97dc8c5..26900333b1d6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/sddr3.c | |||
@@ -70,6 +70,8 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) | |||
70 | { | 70 | { |
71 | int CWL, CL, WR, DLL = 0, ODT = 0; | 71 | int CWL, CL, WR, DLL = 0, ODT = 0; |
72 | 72 | ||
73 | DLL = !ram->next->bios.ramcfg_DLLoff; | ||
74 | |||
73 | switch (ram->next->bios.timing_ver) { | 75 | switch (ram->next->bios.timing_ver) { |
74 | case 0x10: | 76 | case 0x10: |
75 | if (ram->next->bios.timing_hdr < 0x17) { | 77 | if (ram->next->bios.timing_hdr < 0x17) { |
@@ -79,7 +81,6 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) | |||
79 | CWL = ram->next->bios.timing_10_CWL; | 81 | CWL = ram->next->bios.timing_10_CWL; |
80 | CL = ram->next->bios.timing_10_CL; | 82 | CL = ram->next->bios.timing_10_CL; |
81 | WR = ram->next->bios.timing_10_WR; | 83 | WR = ram->next->bios.timing_10_WR; |
82 | DLL = !ram->next->bios.ramcfg_DLLoff; | ||
83 | ODT = ram->next->bios.timing_10_ODT; | 84 | ODT = ram->next->bios.timing_10_ODT; |
84 | break; | 85 | break; |
85 | case 0x20: | 86 | case 0x20: |
@@ -87,7 +88,6 @@ nvkm_sddr3_calc(struct nvkm_ram *ram) | |||
87 | CL = (ram->next->bios.timing[1] & 0x0000001f) >> 0; | 88 | CL = (ram->next->bios.timing[1] & 0x0000001f) >> 0; |
88 | WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; | 89 | WR = (ram->next->bios.timing[2] & 0x007f0000) >> 16; |
89 | /* XXX: Get these values from the VBIOS instead */ | 90 | /* XXX: Get these values from the VBIOS instead */ |
90 | DLL = !(ram->mr[1] & 0x1); | ||
91 | ODT = (ram->mr[1] & 0x004) >> 2 | | 91 | ODT = (ram->mr[1] & 0x004) >> 2 | |
92 | (ram->mr[1] & 0x040) >> 5 | | 92 | (ram->mr[1] & 0x040) >> 5 | |
93 | (ram->mr[1] & 0x200) >> 7; | 93 | (ram->mr[1] & 0x200) >> 7; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c index 8996649209ab..73923fd5f7f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/nv50.c | |||
@@ -54,7 +54,7 @@ nv50_gpio_reset(struct nvkm_gpio *gpio, u8 match) | |||
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | int | 57 | static int |
58 | nv50_gpio_location(int line, u32 *reg, u32 *shift) | 58 | nv50_gpio_location(int line, u32 *reg, u32 *shift) |
59 | { | 59 | { |
60 | const u32 nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; | 60 | const u32 nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild index a0b12d27284a..de888fa62b3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/Kbuild | |||
@@ -1,3 +1,4 @@ | |||
1 | nvkm-y += nvkm/subdev/ibus/gf100.o | 1 | nvkm-y += nvkm/subdev/ibus/gf100.o |
2 | nvkm-y += nvkm/subdev/ibus/gf117.o | ||
2 | nvkm-y += nvkm/subdev/ibus/gk104.o | 3 | nvkm-y += nvkm/subdev/ibus/gk104.o |
3 | nvkm-y += nvkm/subdev/ibus/gk20a.o | 4 | nvkm-y += nvkm/subdev/ibus/gk20a.o |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c index 37a0496f7ed1..72d6330d243d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf100.c | |||
@@ -21,7 +21,7 @@ | |||
21 | * | 21 | * |
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | #include <subdev/ibus.h> | 24 | #include "priv.h" |
25 | 25 | ||
26 | static void | 26 | static void |
27 | gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i) | 27 | gf100_ibus_intr_hub(struct nvkm_subdev *ibus, int i) |
@@ -56,7 +56,7 @@ gf100_ibus_intr_gpc(struct nvkm_subdev *ibus, int i) | |||
56 | nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000); | 56 | nvkm_mask(device, 0x128128 + (i * 0x0400), 0x00000200, 0x00000000); |
57 | } | 57 | } |
58 | 58 | ||
59 | static void | 59 | void |
60 | gf100_ibus_intr(struct nvkm_subdev *ibus) | 60 | gf100_ibus_intr(struct nvkm_subdev *ibus) |
61 | { | 61 | { |
62 | struct nvkm_device *device = ibus->device; | 62 | struct nvkm_device *device = ibus->device; |
@@ -92,8 +92,21 @@ gf100_ibus_intr(struct nvkm_subdev *ibus) | |||
92 | } | 92 | } |
93 | } | 93 | } |
94 | 94 | ||
95 | static int | ||
96 | gf100_ibus_init(struct nvkm_subdev *ibus) | ||
97 | { | ||
98 | struct nvkm_device *device = ibus->device; | ||
99 | nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800); | ||
100 | nvkm_wr32(device, 0x12232c, 0x00100064); | ||
101 | nvkm_wr32(device, 0x122330, 0x00100064); | ||
102 | nvkm_wr32(device, 0x122334, 0x00100064); | ||
103 | nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100); | ||
104 | return 0; | ||
105 | } | ||
106 | |||
95 | static const struct nvkm_subdev_func | 107 | static const struct nvkm_subdev_func |
96 | gf100_ibus = { | 108 | gf100_ibus = { |
109 | .init = gf100_ibus_init, | ||
97 | .intr = gf100_ibus_intr, | 110 | .intr = gf100_ibus_intr, |
98 | }; | 111 | }; |
99 | 112 | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c new file mode 100644 index 000000000000..f69f263c5906 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/gf117.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Samuel Pitosiet | ||
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: Samuel Pitoiset | ||
23 | */ | ||
24 | #include "priv.h" | ||
25 | |||
26 | static int | ||
27 | gf117_ibus_init(struct nvkm_subdev *ibus) | ||
28 | { | ||
29 | struct nvkm_device *device = ibus->device; | ||
30 | nvkm_mask(device, 0x122310, 0x0003ffff, 0x00000800); | ||
31 | nvkm_mask(device, 0x122348, 0x0003ffff, 0x00000100); | ||
32 | nvkm_mask(device, 0x1223b0, 0x0003ffff, 0x00000fff); | ||
33 | return 0; | ||
34 | } | ||
35 | |||
36 | static const struct nvkm_subdev_func | ||
37 | gf117_ibus = { | ||
38 | .init = gf117_ibus_init, | ||
39 | .intr = gf100_ibus_intr, | ||
40 | }; | ||
41 | |||
42 | int | ||
43 | gf117_ibus_new(struct nvkm_device *device, int index, | ||
44 | struct nvkm_subdev **pibus) | ||
45 | { | ||
46 | struct nvkm_subdev *ibus; | ||
47 | if (!(ibus = *pibus = kzalloc(sizeof(*ibus), GFP_KERNEL))) | ||
48 | return -ENOMEM; | ||
49 | nvkm_subdev_ctor(&gf117_ibus, device, index, 0, ibus); | ||
50 | return 0; | ||
51 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h new file mode 100644 index 000000000000..48e1b6365ce6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ibus/priv.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __NVKM_IBUS_PRIV_H__ | ||
2 | #define __NVKM_IBUS_PRIV_H__ | ||
3 | |||
4 | #include <subdev/ibus.h> | ||
5 | |||
6 | void gf100_ibus_intr(struct nvkm_subdev *); | ||
7 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c index cd7feb1b25f6..fc419bb8eab7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c | |||
@@ -23,35 +23,42 @@ | |||
23 | /* | 23 | /* |
24 | * GK20A does not have dedicated video memory, and to accurately represent this | 24 | * GK20A does not have dedicated video memory, and to accurately represent this |
25 | * fact Nouveau will not create a RAM device for it. Therefore its instmem | 25 | * fact Nouveau will not create a RAM device for it. Therefore its instmem |
26 | * implementation must be done directly on top of system memory, while providing | 26 | * implementation must be done directly on top of system memory, while |
27 | * coherent read and write operations. | 27 | * preserving coherency for read and write operations. |
28 | * | 28 | * |
29 | * Instmem can be allocated through two means: | 29 | * Instmem can be allocated through two means: |
30 | * 1) If an IOMMU mapping has been probed, the IOMMU API is used to make memory | 30 | * 1) If an IOMMU unit has been probed, the IOMMU API is used to make memory |
31 | * pages contiguous to the GPU. This is the preferred way. | 31 | * pages contiguous to the GPU. This is the preferred way. |
32 | * 2) If no IOMMU mapping is probed, the DMA API is used to allocate physically | 32 | * 2) If no IOMMU unit is probed, the DMA API is used to allocate physically |
33 | * contiguous memory. | 33 | * contiguous memory. |
34 | * | 34 | * |
35 | * In both cases CPU read and writes are performed using PRAMIN (i.e. using the | 35 | * In both cases CPU read and writes are performed by creating a write-combined |
36 | * GPU path) to ensure these operations are coherent for the GPU. This allows us | 36 | * mapping. The GPU L2 cache must thus be flushed/invalidated when required. To |
37 | * to use more "relaxed" allocation parameters when using the DMA API, since we | 37 | * be conservative we do this every time we acquire or release an instobj, but |
38 | * never need a kernel mapping. | 38 | * ideally L2 management should be handled at a higher level. |
39 | * | ||
40 | * To improve performance, CPU mappings are not removed upon instobj release. | ||
41 | * Instead they are placed into a LRU list to be recycled when the mapped space | ||
42 | * goes beyond a certain threshold. At the moment this limit is 1MB. | ||
39 | */ | 43 | */ |
40 | #define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base) | ||
41 | #include "priv.h" | 44 | #include "priv.h" |
42 | 45 | ||
43 | #include <core/memory.h> | 46 | #include <core/memory.h> |
44 | #include <core/mm.h> | 47 | #include <core/mm.h> |
45 | #include <core/tegra.h> | 48 | #include <core/tegra.h> |
46 | #include <subdev/fb.h> | 49 | #include <subdev/fb.h> |
47 | 50 | #include <subdev/ltc.h> | |
48 | #define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory) | ||
49 | 51 | ||
50 | struct gk20a_instobj { | 52 | struct gk20a_instobj { |
51 | struct nvkm_memory memory; | 53 | struct nvkm_memory memory; |
52 | struct gk20a_instmem *imem; | ||
53 | struct nvkm_mem mem; | 54 | struct nvkm_mem mem; |
55 | struct gk20a_instmem *imem; | ||
56 | |||
57 | /* CPU mapping */ | ||
58 | u32 *vaddr; | ||
59 | struct list_head vaddr_node; | ||
54 | }; | 60 | }; |
61 | #define gk20a_instobj(p) container_of((p), struct gk20a_instobj, memory) | ||
55 | 62 | ||
56 | /* | 63 | /* |
57 | * Used for objects allocated using the DMA API | 64 | * Used for objects allocated using the DMA API |
@@ -59,10 +66,12 @@ struct gk20a_instobj { | |||
59 | struct gk20a_instobj_dma { | 66 | struct gk20a_instobj_dma { |
60 | struct gk20a_instobj base; | 67 | struct gk20a_instobj base; |
61 | 68 | ||
62 | void *cpuaddr; | 69 | u32 *cpuaddr; |
63 | dma_addr_t handle; | 70 | dma_addr_t handle; |
64 | struct nvkm_mm_node r; | 71 | struct nvkm_mm_node r; |
65 | }; | 72 | }; |
73 | #define gk20a_instobj_dma(p) \ | ||
74 | container_of(gk20a_instobj(p), struct gk20a_instobj_dma, base) | ||
66 | 75 | ||
67 | /* | 76 | /* |
68 | * Used for objects flattened using the IOMMU API | 77 | * Used for objects flattened using the IOMMU API |
@@ -70,25 +79,38 @@ struct gk20a_instobj_dma { | |||
70 | struct gk20a_instobj_iommu { | 79 | struct gk20a_instobj_iommu { |
71 | struct gk20a_instobj base; | 80 | struct gk20a_instobj base; |
72 | 81 | ||
73 | /* array of base.mem->size pages */ | 82 | /* will point to the higher half of pages */ |
83 | dma_addr_t *dma_addrs; | ||
84 | /* array of base.mem->size pages (+ dma_addr_ts) */ | ||
74 | struct page *pages[]; | 85 | struct page *pages[]; |
75 | }; | 86 | }; |
87 | #define gk20a_instobj_iommu(p) \ | ||
88 | container_of(gk20a_instobj(p), struct gk20a_instobj_iommu, base) | ||
76 | 89 | ||
77 | struct gk20a_instmem { | 90 | struct gk20a_instmem { |
78 | struct nvkm_instmem base; | 91 | struct nvkm_instmem base; |
79 | unsigned long lock_flags; | 92 | |
93 | /* protects vaddr_* and gk20a_instobj::vaddr* */ | ||
80 | spinlock_t lock; | 94 | spinlock_t lock; |
81 | u64 addr; | 95 | |
96 | /* CPU mappings LRU */ | ||
97 | unsigned int vaddr_use; | ||
98 | unsigned int vaddr_max; | ||
99 | struct list_head vaddr_lru; | ||
82 | 100 | ||
83 | /* Only used if IOMMU if present */ | 101 | /* Only used if IOMMU if present */ |
84 | struct mutex *mm_mutex; | 102 | struct mutex *mm_mutex; |
85 | struct nvkm_mm *mm; | 103 | struct nvkm_mm *mm; |
86 | struct iommu_domain *domain; | 104 | struct iommu_domain *domain; |
87 | unsigned long iommu_pgshift; | 105 | unsigned long iommu_pgshift; |
106 | u16 iommu_bit; | ||
88 | 107 | ||
89 | /* Only used by DMA API */ | 108 | /* Only used by DMA API */ |
90 | struct dma_attrs attrs; | 109 | struct dma_attrs attrs; |
110 | |||
111 | void __iomem * (*cpu_map)(struct nvkm_memory *); | ||
91 | }; | 112 | }; |
113 | #define gk20a_instmem(p) container_of((p), struct gk20a_instmem, base) | ||
92 | 114 | ||
93 | static enum nvkm_memory_target | 115 | static enum nvkm_memory_target |
94 | gk20a_instobj_target(struct nvkm_memory *memory) | 116 | gk20a_instobj_target(struct nvkm_memory *memory) |
@@ -100,7 +122,6 @@ static u64 | |||
100 | gk20a_instobj_addr(struct nvkm_memory *memory) | 122 | gk20a_instobj_addr(struct nvkm_memory *memory) |
101 | { | 123 | { |
102 | return gk20a_instobj(memory)->mem.offset; | 124 | return gk20a_instobj(memory)->mem.offset; |
103 | |||
104 | } | 125 | } |
105 | 126 | ||
106 | static u64 | 127 | static u64 |
@@ -110,107 +131,217 @@ gk20a_instobj_size(struct nvkm_memory *memory) | |||
110 | } | 131 | } |
111 | 132 | ||
112 | static void __iomem * | 133 | static void __iomem * |
134 | gk20a_instobj_cpu_map_dma(struct nvkm_memory *memory) | ||
135 | { | ||
136 | struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory); | ||
137 | struct device *dev = node->base.imem->base.subdev.device->dev; | ||
138 | int npages = nvkm_memory_size(memory) >> 12; | ||
139 | struct page *pages[npages]; | ||
140 | int i; | ||
141 | |||
142 | /* phys_to_page does not exist on all platforms... */ | ||
143 | pages[0] = pfn_to_page(dma_to_phys(dev, node->handle) >> PAGE_SHIFT); | ||
144 | for (i = 1; i < npages; i++) | ||
145 | pages[i] = pages[0] + i; | ||
146 | |||
147 | return vmap(pages, npages, VM_MAP, pgprot_writecombine(PAGE_KERNEL)); | ||
148 | } | ||
149 | |||
150 | static void __iomem * | ||
151 | gk20a_instobj_cpu_map_iommu(struct nvkm_memory *memory) | ||
152 | { | ||
153 | struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory); | ||
154 | int npages = nvkm_memory_size(memory) >> 12; | ||
155 | |||
156 | return vmap(node->pages, npages, VM_MAP, | ||
157 | pgprot_writecombine(PAGE_KERNEL)); | ||
158 | } | ||
159 | |||
160 | /* | ||
161 | * Must be called while holding gk20a_instmem_lock | ||
162 | */ | ||
163 | static void | ||
164 | gk20a_instmem_vaddr_gc(struct gk20a_instmem *imem, const u64 size) | ||
165 | { | ||
166 | while (imem->vaddr_use + size > imem->vaddr_max) { | ||
167 | struct gk20a_instobj *obj; | ||
168 | |||
169 | /* no candidate that can be unmapped, abort... */ | ||
170 | if (list_empty(&imem->vaddr_lru)) | ||
171 | break; | ||
172 | |||
173 | obj = list_first_entry(&imem->vaddr_lru, struct gk20a_instobj, | ||
174 | vaddr_node); | ||
175 | list_del(&obj->vaddr_node); | ||
176 | vunmap(obj->vaddr); | ||
177 | obj->vaddr = NULL; | ||
178 | imem->vaddr_use -= nvkm_memory_size(&obj->memory); | ||
179 | nvkm_debug(&imem->base.subdev, "(GC) vaddr used: %x/%x\n", | ||
180 | imem->vaddr_use, imem->vaddr_max); | ||
181 | |||
182 | } | ||
183 | } | ||
184 | |||
185 | static void __iomem * | ||
113 | gk20a_instobj_acquire(struct nvkm_memory *memory) | 186 | gk20a_instobj_acquire(struct nvkm_memory *memory) |
114 | { | 187 | { |
115 | struct gk20a_instmem *imem = gk20a_instobj(memory)->imem; | 188 | struct gk20a_instobj *node = gk20a_instobj(memory); |
189 | struct gk20a_instmem *imem = node->imem; | ||
190 | struct nvkm_ltc *ltc = imem->base.subdev.device->ltc; | ||
191 | const u64 size = nvkm_memory_size(memory); | ||
116 | unsigned long flags; | 192 | unsigned long flags; |
193 | |||
194 | nvkm_ltc_flush(ltc); | ||
195 | |||
117 | spin_lock_irqsave(&imem->lock, flags); | 196 | spin_lock_irqsave(&imem->lock, flags); |
118 | imem->lock_flags = flags; | 197 | |
119 | return NULL; | 198 | if (node->vaddr) { |
199 | /* remove us from the LRU list since we cannot be unmapped */ | ||
200 | list_del(&node->vaddr_node); | ||
201 | |||
202 | goto out; | ||
203 | } | ||
204 | |||
205 | /* try to free some address space if we reached the limit */ | ||
206 | gk20a_instmem_vaddr_gc(imem, size); | ||
207 | |||
208 | node->vaddr = imem->cpu_map(memory); | ||
209 | |||
210 | if (!node->vaddr) { | ||
211 | nvkm_error(&imem->base.subdev, "cannot map instobj - " | ||
212 | "this is not going to end well...\n"); | ||
213 | goto out; | ||
214 | } | ||
215 | |||
216 | imem->vaddr_use += size; | ||
217 | nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", | ||
218 | imem->vaddr_use, imem->vaddr_max); | ||
219 | |||
220 | out: | ||
221 | spin_unlock_irqrestore(&imem->lock, flags); | ||
222 | |||
223 | return node->vaddr; | ||
120 | } | 224 | } |
121 | 225 | ||
122 | static void | 226 | static void |
123 | gk20a_instobj_release(struct nvkm_memory *memory) | 227 | gk20a_instobj_release(struct nvkm_memory *memory) |
124 | { | 228 | { |
125 | struct gk20a_instmem *imem = gk20a_instobj(memory)->imem; | 229 | struct gk20a_instobj *node = gk20a_instobj(memory); |
126 | spin_unlock_irqrestore(&imem->lock, imem->lock_flags); | 230 | struct gk20a_instmem *imem = node->imem; |
127 | } | 231 | struct nvkm_ltc *ltc = imem->base.subdev.device->ltc; |
232 | unsigned long flags; | ||
128 | 233 | ||
129 | /* | 234 | spin_lock_irqsave(&imem->lock, flags); |
130 | * Use PRAMIN to read/write data and avoid coherency issues. | 235 | |
131 | * PRAMIN uses the GPU path and ensures data will always be coherent. | 236 | /* add ourselves to the LRU list so our CPU mapping can be freed */ |
132 | * | 237 | list_add_tail(&node->vaddr_node, &imem->vaddr_lru); |
133 | * A dynamic mapping based solution would be desirable in the future, but | 238 | |
134 | * the issue remains of how to maintain coherency efficiently. On ARM it is | 239 | spin_unlock_irqrestore(&imem->lock, flags); |
135 | * not easy (if possible at all?) to create uncached temporary mappings. | 240 | |
136 | */ | 241 | wmb(); |
242 | nvkm_ltc_invalidate(ltc); | ||
243 | } | ||
137 | 244 | ||
138 | static u32 | 245 | static u32 |
139 | gk20a_instobj_rd32(struct nvkm_memory *memory, u64 offset) | 246 | gk20a_instobj_rd32(struct nvkm_memory *memory, u64 offset) |
140 | { | 247 | { |
141 | struct gk20a_instobj *node = gk20a_instobj(memory); | 248 | struct gk20a_instobj *node = gk20a_instobj(memory); |
142 | struct gk20a_instmem *imem = node->imem; | 249 | |
143 | struct nvkm_device *device = imem->base.subdev.device; | 250 | return node->vaddr[offset / 4]; |
144 | u64 base = (node->mem.offset + offset) & 0xffffff00000ULL; | ||
145 | u64 addr = (node->mem.offset + offset) & 0x000000fffffULL; | ||
146 | u32 data; | ||
147 | |||
148 | if (unlikely(imem->addr != base)) { | ||
149 | nvkm_wr32(device, 0x001700, base >> 16); | ||
150 | imem->addr = base; | ||
151 | } | ||
152 | data = nvkm_rd32(device, 0x700000 + addr); | ||
153 | return data; | ||
154 | } | 251 | } |
155 | 252 | ||
156 | static void | 253 | static void |
157 | gk20a_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) | 254 | gk20a_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) |
158 | { | 255 | { |
159 | struct gk20a_instobj *node = gk20a_instobj(memory); | 256 | struct gk20a_instobj *node = gk20a_instobj(memory); |
160 | struct gk20a_instmem *imem = node->imem; | ||
161 | struct nvkm_device *device = imem->base.subdev.device; | ||
162 | u64 base = (node->mem.offset + offset) & 0xffffff00000ULL; | ||
163 | u64 addr = (node->mem.offset + offset) & 0x000000fffffULL; | ||
164 | 257 | ||
165 | if (unlikely(imem->addr != base)) { | 258 | node->vaddr[offset / 4] = data; |
166 | nvkm_wr32(device, 0x001700, base >> 16); | ||
167 | imem->addr = base; | ||
168 | } | ||
169 | nvkm_wr32(device, 0x700000 + addr, data); | ||
170 | } | 259 | } |
171 | 260 | ||
172 | static void | 261 | static void |
173 | gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) | 262 | gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) |
174 | { | 263 | { |
175 | struct gk20a_instobj *node = gk20a_instobj(memory); | 264 | struct gk20a_instobj *node = gk20a_instobj(memory); |
265 | |||
176 | nvkm_vm_map_at(vma, offset, &node->mem); | 266 | nvkm_vm_map_at(vma, offset, &node->mem); |
177 | } | 267 | } |
178 | 268 | ||
269 | /* | ||
270 | * Clear the CPU mapping of an instobj if it exists | ||
271 | */ | ||
179 | static void | 272 | static void |
180 | gk20a_instobj_dtor_dma(struct gk20a_instobj *_node) | 273 | gk20a_instobj_dtor(struct gk20a_instobj *node) |
274 | { | ||
275 | struct gk20a_instmem *imem = node->imem; | ||
276 | struct gk20a_instobj *obj; | ||
277 | unsigned long flags; | ||
278 | |||
279 | spin_lock_irqsave(&imem->lock, flags); | ||
280 | |||
281 | if (!node->vaddr) | ||
282 | goto out; | ||
283 | |||
284 | list_for_each_entry(obj, &imem->vaddr_lru, vaddr_node) { | ||
285 | if (obj == node) { | ||
286 | list_del(&obj->vaddr_node); | ||
287 | break; | ||
288 | } | ||
289 | } | ||
290 | vunmap(node->vaddr); | ||
291 | node->vaddr = NULL; | ||
292 | imem->vaddr_use -= nvkm_memory_size(&node->memory); | ||
293 | nvkm_debug(&imem->base.subdev, "vaddr used: %x/%x\n", | ||
294 | imem->vaddr_use, imem->vaddr_max); | ||
295 | |||
296 | out: | ||
297 | spin_unlock_irqrestore(&imem->lock, flags); | ||
298 | } | ||
299 | |||
300 | static void * | ||
301 | gk20a_instobj_dtor_dma(struct nvkm_memory *memory) | ||
181 | { | 302 | { |
182 | struct gk20a_instobj_dma *node = (void *)_node; | 303 | struct gk20a_instobj_dma *node = gk20a_instobj_dma(memory); |
183 | struct gk20a_instmem *imem = _node->imem; | 304 | struct gk20a_instmem *imem = node->base.imem; |
184 | struct device *dev = imem->base.subdev.device->dev; | 305 | struct device *dev = imem->base.subdev.device->dev; |
185 | 306 | ||
307 | gk20a_instobj_dtor(&node->base); | ||
308 | |||
186 | if (unlikely(!node->cpuaddr)) | 309 | if (unlikely(!node->cpuaddr)) |
187 | return; | 310 | goto out; |
188 | 311 | ||
189 | dma_free_attrs(dev, _node->mem.size << PAGE_SHIFT, node->cpuaddr, | 312 | dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->cpuaddr, |
190 | node->handle, &imem->attrs); | 313 | node->handle, &imem->attrs); |
314 | |||
315 | out: | ||
316 | return node; | ||
191 | } | 317 | } |
192 | 318 | ||
193 | static void | 319 | static void * |
194 | gk20a_instobj_dtor_iommu(struct gk20a_instobj *_node) | 320 | gk20a_instobj_dtor_iommu(struct nvkm_memory *memory) |
195 | { | 321 | { |
196 | struct gk20a_instobj_iommu *node = (void *)_node; | 322 | struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory); |
197 | struct gk20a_instmem *imem = _node->imem; | 323 | struct gk20a_instmem *imem = node->base.imem; |
324 | struct device *dev = imem->base.subdev.device->dev; | ||
198 | struct nvkm_mm_node *r; | 325 | struct nvkm_mm_node *r; |
199 | int i; | 326 | int i; |
200 | 327 | ||
201 | if (unlikely(list_empty(&_node->mem.regions))) | 328 | gk20a_instobj_dtor(&node->base); |
202 | return; | ||
203 | 329 | ||
204 | r = list_first_entry(&_node->mem.regions, struct nvkm_mm_node, | 330 | if (unlikely(list_empty(&node->base.mem.regions))) |
331 | goto out; | ||
332 | |||
333 | r = list_first_entry(&node->base.mem.regions, struct nvkm_mm_node, | ||
205 | rl_entry); | 334 | rl_entry); |
206 | 335 | ||
207 | /* clear bit 34 to unmap pages */ | 336 | /* clear IOMMU bit to unmap pages */ |
208 | r->offset &= ~BIT(34 - imem->iommu_pgshift); | 337 | r->offset &= ~BIT(imem->iommu_bit - imem->iommu_pgshift); |
209 | 338 | ||
210 | /* Unmap pages from GPU address space and free them */ | 339 | /* Unmap pages from GPU address space and free them */ |
211 | for (i = 0; i < _node->mem.size; i++) { | 340 | for (i = 0; i < node->base.mem.size; i++) { |
212 | iommu_unmap(imem->domain, | 341 | iommu_unmap(imem->domain, |
213 | (r->offset + i) << imem->iommu_pgshift, PAGE_SIZE); | 342 | (r->offset + i) << imem->iommu_pgshift, PAGE_SIZE); |
343 | dma_unmap_page(dev, node->dma_addrs[i], PAGE_SIZE, | ||
344 | DMA_BIDIRECTIONAL); | ||
214 | __free_page(node->pages[i]); | 345 | __free_page(node->pages[i]); |
215 | } | 346 | } |
216 | 347 | ||
@@ -218,25 +349,27 @@ gk20a_instobj_dtor_iommu(struct gk20a_instobj *_node) | |||
218 | mutex_lock(imem->mm_mutex); | 349 | mutex_lock(imem->mm_mutex); |
219 | nvkm_mm_free(imem->mm, &r); | 350 | nvkm_mm_free(imem->mm, &r); |
220 | mutex_unlock(imem->mm_mutex); | 351 | mutex_unlock(imem->mm_mutex); |
221 | } | ||
222 | |||
223 | static void * | ||
224 | gk20a_instobj_dtor(struct nvkm_memory *memory) | ||
225 | { | ||
226 | struct gk20a_instobj *node = gk20a_instobj(memory); | ||
227 | struct gk20a_instmem *imem = node->imem; | ||
228 | |||
229 | if (imem->domain) | ||
230 | gk20a_instobj_dtor_iommu(node); | ||
231 | else | ||
232 | gk20a_instobj_dtor_dma(node); | ||
233 | 352 | ||
353 | out: | ||
234 | return node; | 354 | return node; |
235 | } | 355 | } |
236 | 356 | ||
237 | static const struct nvkm_memory_func | 357 | static const struct nvkm_memory_func |
238 | gk20a_instobj_func = { | 358 | gk20a_instobj_func_dma = { |
239 | .dtor = gk20a_instobj_dtor, | 359 | .dtor = gk20a_instobj_dtor_dma, |
360 | .target = gk20a_instobj_target, | ||
361 | .addr = gk20a_instobj_addr, | ||
362 | .size = gk20a_instobj_size, | ||
363 | .acquire = gk20a_instobj_acquire, | ||
364 | .release = gk20a_instobj_release, | ||
365 | .rd32 = gk20a_instobj_rd32, | ||
366 | .wr32 = gk20a_instobj_wr32, | ||
367 | .map = gk20a_instobj_map, | ||
368 | }; | ||
369 | |||
370 | static const struct nvkm_memory_func | ||
371 | gk20a_instobj_func_iommu = { | ||
372 | .dtor = gk20a_instobj_dtor_iommu, | ||
240 | .target = gk20a_instobj_target, | 373 | .target = gk20a_instobj_target, |
241 | .addr = gk20a_instobj_addr, | 374 | .addr = gk20a_instobj_addr, |
242 | .size = gk20a_instobj_size, | 375 | .size = gk20a_instobj_size, |
@@ -259,6 +392,8 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align, | |||
259 | return -ENOMEM; | 392 | return -ENOMEM; |
260 | *_node = &node->base; | 393 | *_node = &node->base; |
261 | 394 | ||
395 | nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory); | ||
396 | |||
262 | node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, | 397 | node->cpuaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, |
263 | &node->handle, GFP_KERNEL, | 398 | &node->handle, GFP_KERNEL, |
264 | &imem->attrs); | 399 | &imem->attrs); |
@@ -292,24 +427,40 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, | |||
292 | { | 427 | { |
293 | struct gk20a_instobj_iommu *node; | 428 | struct gk20a_instobj_iommu *node; |
294 | struct nvkm_subdev *subdev = &imem->base.subdev; | 429 | struct nvkm_subdev *subdev = &imem->base.subdev; |
430 | struct device *dev = subdev->device->dev; | ||
295 | struct nvkm_mm_node *r; | 431 | struct nvkm_mm_node *r; |
296 | int ret; | 432 | int ret; |
297 | int i; | 433 | int i; |
298 | 434 | ||
299 | if (!(node = kzalloc(sizeof(*node) + | 435 | /* |
300 | sizeof( node->pages[0]) * npages, GFP_KERNEL))) | 436 | * despite their variable size, instmem allocations are small enough |
437 | * (< 1 page) to be handled by kzalloc | ||
438 | */ | ||
439 | if (!(node = kzalloc(sizeof(*node) + ((sizeof(node->pages[0]) + | ||
440 | sizeof(*node->dma_addrs)) * npages), GFP_KERNEL))) | ||
301 | return -ENOMEM; | 441 | return -ENOMEM; |
302 | *_node = &node->base; | 442 | *_node = &node->base; |
443 | node->dma_addrs = (void *)(node->pages + npages); | ||
444 | |||
445 | nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory); | ||
303 | 446 | ||
304 | /* Allocate backing memory */ | 447 | /* Allocate backing memory */ |
305 | for (i = 0; i < npages; i++) { | 448 | for (i = 0; i < npages; i++) { |
306 | struct page *p = alloc_page(GFP_KERNEL); | 449 | struct page *p = alloc_page(GFP_KERNEL); |
450 | dma_addr_t dma_adr; | ||
307 | 451 | ||
308 | if (p == NULL) { | 452 | if (p == NULL) { |
309 | ret = -ENOMEM; | 453 | ret = -ENOMEM; |
310 | goto free_pages; | 454 | goto free_pages; |
311 | } | 455 | } |
312 | node->pages[i] = p; | 456 | node->pages[i] = p; |
457 | dma_adr = dma_map_page(dev, p, 0, PAGE_SIZE, DMA_BIDIRECTIONAL); | ||
458 | if (dma_mapping_error(dev, dma_adr)) { | ||
459 | nvkm_error(subdev, "DMA mapping error!\n"); | ||
460 | ret = -ENOMEM; | ||
461 | goto free_pages; | ||
462 | } | ||
463 | node->dma_addrs[i] = dma_adr; | ||
313 | } | 464 | } |
314 | 465 | ||
315 | mutex_lock(imem->mm_mutex); | 466 | mutex_lock(imem->mm_mutex); |
@@ -318,16 +469,15 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, | |||
318 | align >> imem->iommu_pgshift, &r); | 469 | align >> imem->iommu_pgshift, &r); |
319 | mutex_unlock(imem->mm_mutex); | 470 | mutex_unlock(imem->mm_mutex); |
320 | if (ret) { | 471 | if (ret) { |
321 | nvkm_error(subdev, "virtual space is full!\n"); | 472 | nvkm_error(subdev, "IOMMU space is full!\n"); |
322 | goto free_pages; | 473 | goto free_pages; |
323 | } | 474 | } |
324 | 475 | ||
325 | /* Map into GPU address space */ | 476 | /* Map into GPU address space */ |
326 | for (i = 0; i < npages; i++) { | 477 | for (i = 0; i < npages; i++) { |
327 | struct page *p = node->pages[i]; | ||
328 | u32 offset = (r->offset + i) << imem->iommu_pgshift; | 478 | u32 offset = (r->offset + i) << imem->iommu_pgshift; |
329 | 479 | ||
330 | ret = iommu_map(imem->domain, offset, page_to_phys(p), | 480 | ret = iommu_map(imem->domain, offset, node->dma_addrs[i], |
331 | PAGE_SIZE, IOMMU_READ | IOMMU_WRITE); | 481 | PAGE_SIZE, IOMMU_READ | IOMMU_WRITE); |
332 | if (ret < 0) { | 482 | if (ret < 0) { |
333 | nvkm_error(subdev, "IOMMU mapping failure: %d\n", ret); | 483 | nvkm_error(subdev, "IOMMU mapping failure: %d\n", ret); |
@@ -340,8 +490,8 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, | |||
340 | } | 490 | } |
341 | } | 491 | } |
342 | 492 | ||
343 | /* Bit 34 tells that an address is to be resolved through the IOMMU */ | 493 | /* IOMMU bit tells that an address is to be resolved through the IOMMU */ |
344 | r->offset |= BIT(34 - imem->iommu_pgshift); | 494 | r->offset |= BIT(imem->iommu_bit - imem->iommu_pgshift); |
345 | 495 | ||
346 | node->base.mem.offset = ((u64)r->offset) << imem->iommu_pgshift; | 496 | node->base.mem.offset = ((u64)r->offset) << imem->iommu_pgshift; |
347 | 497 | ||
@@ -356,8 +506,13 @@ release_area: | |||
356 | mutex_unlock(imem->mm_mutex); | 506 | mutex_unlock(imem->mm_mutex); |
357 | 507 | ||
358 | free_pages: | 508 | free_pages: |
359 | for (i = 0; i < npages && node->pages[i] != NULL; i++) | 509 | for (i = 0; i < npages && node->pages[i] != NULL; i++) { |
510 | dma_addr_t dma_addr = node->dma_addrs[i]; | ||
511 | if (dma_addr) | ||
512 | dma_unmap_page(dev, dma_addr, PAGE_SIZE, | ||
513 | DMA_BIDIRECTIONAL); | ||
360 | __free_page(node->pages[i]); | 514 | __free_page(node->pages[i]); |
515 | } | ||
361 | 516 | ||
362 | return ret; | 517 | return ret; |
363 | } | 518 | } |
@@ -367,8 +522,8 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, | |||
367 | struct nvkm_memory **pmemory) | 522 | struct nvkm_memory **pmemory) |
368 | { | 523 | { |
369 | struct gk20a_instmem *imem = gk20a_instmem(base); | 524 | struct gk20a_instmem *imem = gk20a_instmem(base); |
370 | struct gk20a_instobj *node = NULL; | ||
371 | struct nvkm_subdev *subdev = &imem->base.subdev; | 525 | struct nvkm_subdev *subdev = &imem->base.subdev; |
526 | struct gk20a_instobj *node = NULL; | ||
372 | int ret; | 527 | int ret; |
373 | 528 | ||
374 | nvkm_debug(subdev, "%s (%s): size: %x align: %x\n", __func__, | 529 | nvkm_debug(subdev, "%s (%s): size: %x align: %x\n", __func__, |
@@ -388,7 +543,6 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, | |||
388 | if (ret) | 543 | if (ret) |
389 | return ret; | 544 | return ret; |
390 | 545 | ||
391 | nvkm_memory_ctor(&gk20a_instobj_func, &node->memory); | ||
392 | node->imem = imem; | 546 | node->imem = imem; |
393 | 547 | ||
394 | /* present memory for being mapped using small pages */ | 548 | /* present memory for being mapped using small pages */ |
@@ -402,15 +556,25 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, | |||
402 | return 0; | 556 | return 0; |
403 | } | 557 | } |
404 | 558 | ||
405 | static void | 559 | static void * |
406 | gk20a_instmem_fini(struct nvkm_instmem *base) | 560 | gk20a_instmem_dtor(struct nvkm_instmem *base) |
407 | { | 561 | { |
408 | gk20a_instmem(base)->addr = ~0ULL; | 562 | struct gk20a_instmem *imem = gk20a_instmem(base); |
563 | |||
564 | /* perform some sanity checks... */ | ||
565 | if (!list_empty(&imem->vaddr_lru)) | ||
566 | nvkm_warn(&base->subdev, "instobj LRU not empty!\n"); | ||
567 | |||
568 | if (imem->vaddr_use != 0) | ||
569 | nvkm_warn(&base->subdev, "instobj vmap area not empty! " | ||
570 | "0x%x bytes still mapped\n", imem->vaddr_use); | ||
571 | |||
572 | return imem; | ||
409 | } | 573 | } |
410 | 574 | ||
411 | static const struct nvkm_instmem_func | 575 | static const struct nvkm_instmem_func |
412 | gk20a_instmem = { | 576 | gk20a_instmem = { |
413 | .fini = gk20a_instmem_fini, | 577 | .dtor = gk20a_instmem_dtor, |
414 | .memory_new = gk20a_instobj_new, | 578 | .memory_new = gk20a_instobj_new, |
415 | .persistent = true, | 579 | .persistent = true, |
416 | .zero = false, | 580 | .zero = false, |
@@ -429,23 +593,28 @@ gk20a_instmem_new(struct nvkm_device *device, int index, | |||
429 | spin_lock_init(&imem->lock); | 593 | spin_lock_init(&imem->lock); |
430 | *pimem = &imem->base; | 594 | *pimem = &imem->base; |
431 | 595 | ||
596 | /* do not allow more than 1MB of CPU-mapped instmem */ | ||
597 | imem->vaddr_use = 0; | ||
598 | imem->vaddr_max = 0x100000; | ||
599 | INIT_LIST_HEAD(&imem->vaddr_lru); | ||
600 | |||
432 | if (tdev->iommu.domain) { | 601 | if (tdev->iommu.domain) { |
433 | imem->domain = tdev->iommu.domain; | 602 | imem->mm_mutex = &tdev->iommu.mutex; |
434 | imem->mm = &tdev->iommu.mm; | 603 | imem->mm = &tdev->iommu.mm; |
604 | imem->domain = tdev->iommu.domain; | ||
435 | imem->iommu_pgshift = tdev->iommu.pgshift; | 605 | imem->iommu_pgshift = tdev->iommu.pgshift; |
436 | imem->mm_mutex = &tdev->iommu.mutex; | 606 | imem->cpu_map = gk20a_instobj_cpu_map_iommu; |
607 | imem->iommu_bit = tdev->func->iommu_bit; | ||
437 | 608 | ||
438 | nvkm_info(&imem->base.subdev, "using IOMMU\n"); | 609 | nvkm_info(&imem->base.subdev, "using IOMMU\n"); |
439 | } else { | 610 | } else { |
440 | init_dma_attrs(&imem->attrs); | 611 | init_dma_attrs(&imem->attrs); |
441 | /* | 612 | /* We will access the memory through our own mapping */ |
442 | * We will access instmem through PRAMIN and thus do not need a | ||
443 | * consistent CPU pointer or kernel mapping | ||
444 | */ | ||
445 | dma_set_attr(DMA_ATTR_NON_CONSISTENT, &imem->attrs); | 613 | dma_set_attr(DMA_ATTR_NON_CONSISTENT, &imem->attrs); |
446 | dma_set_attr(DMA_ATTR_WEAK_ORDERING, &imem->attrs); | 614 | dma_set_attr(DMA_ATTR_WEAK_ORDERING, &imem->attrs); |
447 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &imem->attrs); | 615 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &imem->attrs); |
448 | dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem->attrs); | 616 | dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem->attrs); |
617 | imem->cpu_map = gk20a_instobj_cpu_map_dma; | ||
449 | 618 | ||
450 | nvkm_info(&imem->base.subdev, "using DMA API\n"); | 619 | nvkm_info(&imem->base.subdev, "using DMA API\n"); |
451 | } | 620 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c index 930d25b6e63c..85b1464c0194 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c | |||
@@ -67,6 +67,20 @@ nvkm_ltc_zbc_depth_get(struct nvkm_ltc *ltc, int index, const u32 depth) | |||
67 | return index; | 67 | return index; |
68 | } | 68 | } |
69 | 69 | ||
70 | void | ||
71 | nvkm_ltc_invalidate(struct nvkm_ltc *ltc) | ||
72 | { | ||
73 | if (ltc->func->invalidate) | ||
74 | ltc->func->invalidate(ltc); | ||
75 | } | ||
76 | |||
77 | void | ||
78 | nvkm_ltc_flush(struct nvkm_ltc *ltc) | ||
79 | { | ||
80 | if (ltc->func->flush) | ||
81 | ltc->func->flush(ltc); | ||
82 | } | ||
83 | |||
70 | static void | 84 | static void |
71 | nvkm_ltc_intr(struct nvkm_subdev *subdev) | 85 | nvkm_ltc_intr(struct nvkm_subdev *subdev) |
72 | { | 86 | { |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c index 45ac765b753e..fb0de83da13c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c | |||
@@ -122,6 +122,36 @@ gf100_ltc_intr(struct nvkm_ltc *ltc) | |||
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | void | ||
126 | gf100_ltc_invalidate(struct nvkm_ltc *ltc) | ||
127 | { | ||
128 | struct nvkm_device *device = ltc->subdev.device; | ||
129 | s64 taken; | ||
130 | |||
131 | nvkm_wr32(device, 0x70004, 0x00000001); | ||
132 | taken = nvkm_wait_msec(device, 2, 0x70004, 0x00000003, 0x00000000); | ||
133 | if (taken < 0) | ||
134 | nvkm_warn(<c->subdev, "LTC invalidate timeout\n"); | ||
135 | |||
136 | if (taken > 0) | ||
137 | nvkm_debug(<c->subdev, "LTC invalidate took %lld ns\n", taken); | ||
138 | } | ||
139 | |||
140 | void | ||
141 | gf100_ltc_flush(struct nvkm_ltc *ltc) | ||
142 | { | ||
143 | struct nvkm_device *device = ltc->subdev.device; | ||
144 | s64 taken; | ||
145 | |||
146 | nvkm_wr32(device, 0x70010, 0x00000001); | ||
147 | taken = nvkm_wait_msec(device, 2, 0x70010, 0x00000003, 0x00000000); | ||
148 | if (taken < 0) | ||
149 | nvkm_warn(<c->subdev, "LTC flush timeout\n"); | ||
150 | |||
151 | if (taken > 0) | ||
152 | nvkm_debug(<c->subdev, "LTC flush took %lld ns\n", taken); | ||
153 | } | ||
154 | |||
125 | /* TODO: Figure out tag memory details and drop the over-cautious allocation. | 155 | /* TODO: Figure out tag memory details and drop the over-cautious allocation. |
126 | */ | 156 | */ |
127 | int | 157 | int |
@@ -215,6 +245,8 @@ gf100_ltc = { | |||
215 | .zbc = 16, | 245 | .zbc = 16, |
216 | .zbc_clear_color = gf100_ltc_zbc_clear_color, | 246 | .zbc_clear_color = gf100_ltc_zbc_clear_color, |
217 | .zbc_clear_depth = gf100_ltc_zbc_clear_depth, | 247 | .zbc_clear_depth = gf100_ltc_zbc_clear_depth, |
248 | .invalidate = gf100_ltc_invalidate, | ||
249 | .flush = gf100_ltc_flush, | ||
218 | }; | 250 | }; |
219 | 251 | ||
220 | int | 252 | int |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c index 839e6b4c597b..b4f6e0034d58 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c | |||
@@ -45,6 +45,8 @@ gk104_ltc = { | |||
45 | .zbc = 16, | 45 | .zbc = 16, |
46 | .zbc_clear_color = gf100_ltc_zbc_clear_color, | 46 | .zbc_clear_color = gf100_ltc_zbc_clear_color, |
47 | .zbc_clear_depth = gf100_ltc_zbc_clear_depth, | 47 | .zbc_clear_depth = gf100_ltc_zbc_clear_depth, |
48 | .invalidate = gf100_ltc_invalidate, | ||
49 | .flush = gf100_ltc_flush, | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | int | 52 | int |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c index 389331bb63ba..3043bbfd7384 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c | |||
@@ -138,6 +138,8 @@ gm107_ltc = { | |||
138 | .zbc = 16, | 138 | .zbc = 16, |
139 | .zbc_clear_color = gm107_ltc_zbc_clear_color, | 139 | .zbc_clear_color = gm107_ltc_zbc_clear_color, |
140 | .zbc_clear_depth = gm107_ltc_zbc_clear_depth, | 140 | .zbc_clear_depth = gm107_ltc_zbc_clear_depth, |
141 | .invalidate = gf100_ltc_invalidate, | ||
142 | .flush = gf100_ltc_flush, | ||
141 | }; | 143 | }; |
142 | 144 | ||
143 | int | 145 | int |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h index 4e05037cc99f..4e3755b82769 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h | |||
@@ -17,6 +17,9 @@ struct nvkm_ltc_func { | |||
17 | int zbc; | 17 | int zbc; |
18 | void (*zbc_clear_color)(struct nvkm_ltc *, int, const u32[4]); | 18 | void (*zbc_clear_color)(struct nvkm_ltc *, int, const u32[4]); |
19 | void (*zbc_clear_depth)(struct nvkm_ltc *, int, const u32); | 19 | void (*zbc_clear_depth)(struct nvkm_ltc *, int, const u32); |
20 | |||
21 | void (*invalidate)(struct nvkm_ltc *); | ||
22 | void (*flush)(struct nvkm_ltc *); | ||
20 | }; | 23 | }; |
21 | 24 | ||
22 | int gf100_ltc_oneinit(struct nvkm_ltc *); | 25 | int gf100_ltc_oneinit(struct nvkm_ltc *); |
@@ -26,4 +29,6 @@ void gf100_ltc_cbc_clear(struct nvkm_ltc *, u32, u32); | |||
26 | void gf100_ltc_cbc_wait(struct nvkm_ltc *); | 29 | void gf100_ltc_cbc_wait(struct nvkm_ltc *); |
27 | void gf100_ltc_zbc_clear_color(struct nvkm_ltc *, int, const u32[4]); | 30 | void gf100_ltc_zbc_clear_color(struct nvkm_ltc *, int, const u32[4]); |
28 | void gf100_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32); | 31 | void gf100_ltc_zbc_clear_depth(struct nvkm_ltc *, int, const u32); |
32 | void gf100_ltc_invalidate(struct nvkm_ltc *); | ||
33 | void gf100_ltc_flush(struct nvkm_ltc *); | ||
29 | #endif | 34 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild index 99672c3d0bad..4476ef75acd6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/Kbuild | |||
@@ -2,6 +2,8 @@ nvkm-y += nvkm/subdev/pci/agp.o | |||
2 | nvkm-y += nvkm/subdev/pci/base.o | 2 | nvkm-y += nvkm/subdev/pci/base.o |
3 | nvkm-y += nvkm/subdev/pci/nv04.o | 3 | nvkm-y += nvkm/subdev/pci/nv04.o |
4 | nvkm-y += nvkm/subdev/pci/nv40.o | 4 | nvkm-y += nvkm/subdev/pci/nv40.o |
5 | nvkm-y += nvkm/subdev/pci/nv46.o | ||
5 | nvkm-y += nvkm/subdev/pci/nv4c.o | 6 | nvkm-y += nvkm/subdev/pci/nv4c.o |
6 | nvkm-y += nvkm/subdev/pci/nv50.o | 7 | nvkm-y += nvkm/subdev/pci/g84.o |
8 | nvkm-y += nvkm/subdev/pci/g94.o | ||
7 | nvkm-y += nvkm/subdev/pci/gf100.o | 9 | nvkm-y += nvkm/subdev/pci/gf100.o |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index d1c148e51922..d671dcfaff3c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c | |||
@@ -46,6 +46,14 @@ nvkm_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data) | |||
46 | pci->func->wr32(pci, addr, data); | 46 | pci->func->wr32(pci, addr, data); |
47 | } | 47 | } |
48 | 48 | ||
49 | u32 | ||
50 | nvkm_pci_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32 value) | ||
51 | { | ||
52 | u32 data = pci->func->rd32(pci, addr); | ||
53 | pci->func->wr32(pci, addr, (data & ~mask) | value); | ||
54 | return data; | ||
55 | } | ||
56 | |||
49 | void | 57 | void |
50 | nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) | 58 | nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow) |
51 | { | 59 | { |
@@ -111,6 +119,9 @@ nvkm_pci_init(struct nvkm_subdev *subdev) | |||
111 | return ret; | 119 | return ret; |
112 | } | 120 | } |
113 | 121 | ||
122 | if (pci->func->init) | ||
123 | pci->func->init(pci); | ||
124 | |||
114 | ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); | 125 | ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci); |
115 | if (ret) | 126 | if (ret) |
116 | return ret; | 127 | return ret; |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c new file mode 100644 index 000000000000..3faa6bfb895b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g84.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * Copyright 2015 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 <bskeggs@redhat.com> | ||
23 | */ | ||
24 | #include "priv.h" | ||
25 | |||
26 | #include <core/pci.h> | ||
27 | |||
28 | void | ||
29 | g84_pci_init(struct nvkm_pci *pci) | ||
30 | { | ||
31 | /* The following only concerns PCIe cards. */ | ||
32 | if (!pci_is_pcie(pci->pdev)) | ||
33 | return; | ||
34 | |||
35 | /* Tag field is 8-bit long, regardless of EXT_TAG. | ||
36 | * However, if EXT_TAG is disabled, only the lower 5 bits of the tag | ||
37 | * field should be used, limiting the number of request to 32. | ||
38 | * | ||
39 | * Apparently, 0x041c stores some limit on the number of requests | ||
40 | * possible, so if EXT_TAG is disabled, limit that requests number to | ||
41 | * 32 | ||
42 | * | ||
43 | * Fixes fdo#86537 | ||
44 | */ | ||
45 | if (nvkm_pci_rd32(pci, 0x007c) & 0x00000020) | ||
46 | nvkm_pci_mask(pci, 0x0080, 0x00000100, 0x00000100); | ||
47 | else | ||
48 | nvkm_pci_mask(pci, 0x041c, 0x00000060, 0x00000000); | ||
49 | } | ||
50 | |||
51 | static const struct nvkm_pci_func | ||
52 | g84_pci_func = { | ||
53 | .init = g84_pci_init, | ||
54 | .rd32 = nv40_pci_rd32, | ||
55 | .wr08 = nv40_pci_wr08, | ||
56 | .wr32 = nv40_pci_wr32, | ||
57 | .msi_rearm = nv46_pci_msi_rearm, | ||
58 | }; | ||
59 | |||
60 | int | ||
61 | g84_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) | ||
62 | { | ||
63 | return nvkm_pci_new_(&g84_pci_func, device, index, ppci); | ||
64 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c new file mode 100644 index 000000000000..cd311ee311cc --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/g94.c | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright 2015 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 <bskeggs@redhat.com> | ||
23 | */ | ||
24 | #include "priv.h" | ||
25 | |||
26 | static const struct nvkm_pci_func | ||
27 | g94_pci_func = { | ||
28 | .init = g84_pci_init, | ||
29 | .rd32 = nv40_pci_rd32, | ||
30 | .wr08 = nv40_pci_wr08, | ||
31 | .wr32 = nv40_pci_wr32, | ||
32 | .msi_rearm = nv40_pci_msi_rearm, | ||
33 | }; | ||
34 | |||
35 | int | ||
36 | g94_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) | ||
37 | { | ||
38 | return nvkm_pci_new_(&g94_pci_func, device, index, ppci); | ||
39 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c index 86f8226532d3..25e1ae70867f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/gf100.c | |||
@@ -31,6 +31,7 @@ gf100_pci_msi_rearm(struct nvkm_pci *pci) | |||
31 | 31 | ||
32 | static const struct nvkm_pci_func | 32 | static const struct nvkm_pci_func |
33 | gf100_pci_func = { | 33 | gf100_pci_func = { |
34 | .init = g84_pci_init, | ||
34 | .rd32 = nv40_pci_rd32, | 35 | .rd32 = nv40_pci_rd32, |
35 | .wr08 = nv40_pci_wr08, | 36 | .wr08 = nv40_pci_wr08, |
36 | .wr32 = nv40_pci_wr32, | 37 | .wr32 = nv40_pci_wr32, |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c index 090a187f165f..6eb417765802 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv40.c | |||
@@ -44,7 +44,7 @@ nv40_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data) | |||
44 | nvkm_wr32(device, 0x088000 + addr, data); | 44 | nvkm_wr32(device, 0x088000 + addr, data); |
45 | } | 45 | } |
46 | 46 | ||
47 | static void | 47 | void |
48 | nv40_pci_msi_rearm(struct nvkm_pci *pci) | 48 | nv40_pci_msi_rearm(struct nvkm_pci *pci) |
49 | { | 49 | { |
50 | nvkm_pci_wr08(pci, 0x0068, 0xff); | 50 | nvkm_pci_wr08(pci, 0x0068, 0xff); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c index 3e167d4a381f..fc617e4c0ab6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/nv46.c | |||
@@ -25,11 +25,11 @@ | |||
25 | 25 | ||
26 | #include <core/pci.h> | 26 | #include <core/pci.h> |
27 | 27 | ||
28 | /* MSI re-arm through the PRI appears to be broken on the original G80, | 28 | /* MSI re-arm through the PRI appears to be broken on NV46/NV50/G84/G86/G92, |
29 | * so we access it via alternate PCI config space mechanisms. | 29 | * so we access it via alternate PCI config space mechanisms. |
30 | */ | 30 | */ |
31 | static void | 31 | void |
32 | nv50_pci_msi_rearm(struct nvkm_pci *pci) | 32 | nv46_pci_msi_rearm(struct nvkm_pci *pci) |
33 | { | 33 | { |
34 | struct nvkm_device *device = pci->subdev.device; | 34 | struct nvkm_device *device = pci->subdev.device; |
35 | struct pci_dev *pdev = device->func->pci(device)->pdev; | 35 | struct pci_dev *pdev = device->func->pci(device)->pdev; |
@@ -37,15 +37,15 @@ nv50_pci_msi_rearm(struct nvkm_pci *pci) | |||
37 | } | 37 | } |
38 | 38 | ||
39 | static const struct nvkm_pci_func | 39 | static const struct nvkm_pci_func |
40 | nv50_pci_func = { | 40 | nv46_pci_func = { |
41 | .rd32 = nv40_pci_rd32, | 41 | .rd32 = nv40_pci_rd32, |
42 | .wr08 = nv40_pci_wr08, | 42 | .wr08 = nv40_pci_wr08, |
43 | .wr32 = nv40_pci_wr32, | 43 | .wr32 = nv40_pci_wr32, |
44 | .msi_rearm = nv50_pci_msi_rearm, | 44 | .msi_rearm = nv46_pci_msi_rearm, |
45 | }; | 45 | }; |
46 | 46 | ||
47 | int | 47 | int |
48 | nv50_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) | 48 | nv46_pci_new(struct nvkm_device *device, int index, struct nvkm_pci **ppci) |
49 | { | 49 | { |
50 | return nvkm_pci_new_(&nv50_pci_func, device, index, ppci); | 50 | return nvkm_pci_new_(&nv46_pci_func, device, index, ppci); |
51 | } | 51 | } |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h index d22c2c117106..cf46d38d0b0a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/priv.h | |||
@@ -7,6 +7,7 @@ int nvkm_pci_new_(const struct nvkm_pci_func *, struct nvkm_device *, | |||
7 | int index, struct nvkm_pci **); | 7 | int index, struct nvkm_pci **); |
8 | 8 | ||
9 | struct nvkm_pci_func { | 9 | struct nvkm_pci_func { |
10 | void (*init)(struct nvkm_pci *); | ||
10 | u32 (*rd32)(struct nvkm_pci *, u16 addr); | 11 | u32 (*rd32)(struct nvkm_pci *, u16 addr); |
11 | void (*wr08)(struct nvkm_pci *, u16 addr, u8 data); | 12 | void (*wr08)(struct nvkm_pci *, u16 addr, u8 data); |
12 | void (*wr32)(struct nvkm_pci *, u16 addr, u32 data); | 13 | void (*wr32)(struct nvkm_pci *, u16 addr, u32 data); |
@@ -16,4 +17,9 @@ struct nvkm_pci_func { | |||
16 | u32 nv40_pci_rd32(struct nvkm_pci *, u16); | 17 | u32 nv40_pci_rd32(struct nvkm_pci *, u16); |
17 | void nv40_pci_wr08(struct nvkm_pci *, u16, u8); | 18 | void nv40_pci_wr08(struct nvkm_pci *, u16, u8); |
18 | void nv40_pci_wr32(struct nvkm_pci *, u16, u32); | 19 | void nv40_pci_wr32(struct nvkm_pci *, u16, u32); |
20 | void nv40_pci_msi_rearm(struct nvkm_pci *); | ||
21 | |||
22 | void nv46_pci_msi_rearm(struct nvkm_pci *); | ||
23 | |||
24 | void g84_pci_init(struct nvkm_pci *pci); | ||
19 | #endif | 25 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c index 27a79c0c3888..d95eb8659d1b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c | |||
@@ -28,7 +28,7 @@ | |||
28 | void | 28 | void |
29 | nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable) | 29 | nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable) |
30 | { | 30 | { |
31 | if (pmu->func->pgob) | 31 | if (pmu && pmu->func->pgob) |
32 | pmu->func->pgob(pmu, enable); | 32 | pmu->func->pgob(pmu, enable); |
33 | } | 33 | } |
34 | 34 | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c index e33f5c03b9ac..d942fa7b9f18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk104.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include "fuc/gf119.fuc4.h" | 27 | #include "fuc/gf119.fuc4.h" |
28 | 28 | ||
29 | #include <core/option.h> | 29 | #include <core/option.h> |
30 | #include <subdev/fuse.h> | ||
30 | #include <subdev/timer.h> | 31 | #include <subdev/timer.h> |
31 | 32 | ||
32 | static void | 33 | static void |
@@ -57,6 +58,9 @@ gk104_pmu_pgob(struct nvkm_pmu *pmu, bool enable) | |||
57 | { | 58 | { |
58 | struct nvkm_device *device = pmu->subdev.device; | 59 | struct nvkm_device *device = pmu->subdev.device; |
59 | 60 | ||
61 | if (!(nvkm_fuse_read(device->fuse, 0x31c) & 0x00000001)) | ||
62 | return; | ||
63 | |||
60 | nvkm_mask(device, 0x000200, 0x00001000, 0x00000000); | 64 | nvkm_mask(device, 0x000200, 0x00001000, 0x00000000); |
61 | nvkm_rd32(device, 0x000200); | 65 | nvkm_rd32(device, 0x000200); |
62 | nvkm_mask(device, 0x000200, 0x08000000, 0x08000000); | 66 | nvkm_mask(device, 0x000200, 0x08000000, 0x08000000); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild index 6b46ff4213a3..b035c6e28be8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/Kbuild | |||
@@ -1,4 +1,5 @@ | |||
1 | nvkm-y += nvkm/subdev/volt/base.o | 1 | nvkm-y += nvkm/subdev/volt/base.o |
2 | nvkm-y += nvkm/subdev/volt/gpio.o | 2 | nvkm-y += nvkm/subdev/volt/gpio.o |
3 | nvkm-y += nvkm/subdev/volt/nv40.o | 3 | nvkm-y += nvkm/subdev/volt/nv40.o |
4 | nvkm-y += nvkm/subdev/volt/gk104.o | ||
4 | nvkm-y += nvkm/subdev/volt/gk20a.o | 5 | nvkm-y += nvkm/subdev/volt/gk20a.o |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c index 4752dbd33923..50b5649ad1a4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/base.c | |||
@@ -30,7 +30,12 @@ | |||
30 | int | 30 | int |
31 | nvkm_volt_get(struct nvkm_volt *volt) | 31 | nvkm_volt_get(struct nvkm_volt *volt) |
32 | { | 32 | { |
33 | int ret = volt->func->vid_get(volt), i; | 33 | int ret, i; |
34 | |||
35 | if (volt->func->volt_get) | ||
36 | return volt->func->volt_get(volt); | ||
37 | |||
38 | ret = volt->func->vid_get(volt); | ||
34 | if (ret >= 0) { | 39 | if (ret >= 0) { |
35 | for (i = 0; i < volt->vid_nr; i++) { | 40 | for (i = 0; i < volt->vid_nr; i++) { |
36 | if (volt->vid[i].vid == ret) | 41 | if (volt->vid[i].vid == ret) |
@@ -46,6 +51,10 @@ nvkm_volt_set(struct nvkm_volt *volt, u32 uv) | |||
46 | { | 51 | { |
47 | struct nvkm_subdev *subdev = &volt->subdev; | 52 | struct nvkm_subdev *subdev = &volt->subdev; |
48 | int i, ret = -EINVAL; | 53 | int i, ret = -EINVAL; |
54 | |||
55 | if (volt->func->volt_set) | ||
56 | return volt->func->volt_set(volt, uv); | ||
57 | |||
49 | for (i = 0; i < volt->vid_nr; i++) { | 58 | for (i = 0; i < volt->vid_nr; i++) { |
50 | if (volt->vid[i].uv == uv) { | 59 | if (volt->vid[i].uv == uv) { |
51 | ret = volt->func->vid_set(volt, volt->vid[i].vid); | 60 | ret = volt->func->vid_set(volt, volt->vid[i].vid); |
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c new file mode 100644 index 000000000000..b61509e26ec9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/gk104.c | |||
@@ -0,0 +1,119 @@ | |||
1 | /* | ||
2 | * Copyright 2015 Martin Peres | ||
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: Martin Peres | ||
23 | */ | ||
24 | #include "priv.h" | ||
25 | |||
26 | #include <subdev/volt.h> | ||
27 | #include <subdev/gpio.h> | ||
28 | #include <subdev/bios.h> | ||
29 | #include <subdev/bios/volt.h> | ||
30 | |||
31 | #define gk104_volt(p) container_of((p), struct gk104_volt, base) | ||
32 | struct gk104_volt { | ||
33 | struct nvkm_volt base; | ||
34 | struct nvbios_volt bios; | ||
35 | }; | ||
36 | |||
37 | int | ||
38 | gk104_volt_get(struct nvkm_volt *base) | ||
39 | { | ||
40 | struct nvbios_volt *bios = &gk104_volt(base)->bios; | ||
41 | struct nvkm_device *device = base->subdev.device; | ||
42 | u32 div, duty; | ||
43 | |||
44 | div = nvkm_rd32(device, 0x20340); | ||
45 | duty = nvkm_rd32(device, 0x20344); | ||
46 | |||
47 | return bios->base + bios->pwm_range * duty / div; | ||
48 | } | ||
49 | |||
50 | int | ||
51 | gk104_volt_set(struct nvkm_volt *base, u32 uv) | ||
52 | { | ||
53 | struct nvbios_volt *bios = &gk104_volt(base)->bios; | ||
54 | struct nvkm_device *device = base->subdev.device; | ||
55 | u32 div, duty; | ||
56 | |||
57 | /* the blob uses this crystal frequency, let's use it too. */ | ||
58 | div = 27648000 / bios->pwm_freq; | ||
59 | duty = (uv - bios->base) * div / bios->pwm_range; | ||
60 | |||
61 | nvkm_wr32(device, 0x20340, div); | ||
62 | nvkm_wr32(device, 0x20344, 0x8000000 | duty); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static const struct nvkm_volt_func | ||
68 | gk104_volt_pwm = { | ||
69 | .volt_get = gk104_volt_get, | ||
70 | .volt_set = gk104_volt_set, | ||
71 | }, gk104_volt_gpio = { | ||
72 | .vid_get = nvkm_voltgpio_get, | ||
73 | .vid_set = nvkm_voltgpio_set, | ||
74 | }; | ||
75 | |||
76 | int | ||
77 | gk104_volt_new(struct nvkm_device *device, int index, struct nvkm_volt **pvolt) | ||
78 | { | ||
79 | const struct nvkm_volt_func *volt_func = &gk104_volt_gpio; | ||
80 | struct dcb_gpio_func gpio; | ||
81 | struct nvbios_volt bios; | ||
82 | struct gk104_volt *volt; | ||
83 | u8 ver, hdr, cnt, len; | ||
84 | const char *mode; | ||
85 | |||
86 | if (!nvbios_volt_parse(device->bios, &ver, &hdr, &cnt, &len, &bios)) | ||
87 | return 0; | ||
88 | |||
89 | if (!nvkm_gpio_find(device->gpio, 0, DCB_GPIO_VID_PWM, 0xff, &gpio) && | ||
90 | bios.type == NVBIOS_VOLT_PWM) { | ||
91 | volt_func = &gk104_volt_pwm; | ||
92 | } | ||
93 | |||
94 | if (!(volt = kzalloc(sizeof(*volt), GFP_KERNEL))) | ||
95 | return -ENOMEM; | ||
96 | nvkm_volt_ctor(volt_func, device, index, &volt->base); | ||
97 | *pvolt = &volt->base; | ||
98 | volt->bios = bios; | ||
99 | |||
100 | /* now that we have a subdev, we can show an error if we found through | ||
101 | * the voltage table that we were supposed to use the PWN mode but we | ||
102 | * did not find the right GPIO for it. | ||
103 | */ | ||
104 | if (bios.type == NVBIOS_VOLT_PWM && volt_func != &gk104_volt_pwm) { | ||
105 | nvkm_error(&volt->base.subdev, | ||
106 | "Type mismatch between the voltage table type and " | ||
107 | "the GPIO table. Fallback to GPIO mode.\n"); | ||
108 | } | ||
109 | |||
110 | if (volt_func == &gk104_volt_gpio) { | ||
111 | nvkm_voltgpio_init(&volt->base); | ||
112 | mode = "GPIO"; | ||
113 | } else | ||
114 | mode = "PWM"; | ||
115 | |||
116 | nvkm_debug(&volt->base.subdev, "Using %s mode\n", mode); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h index 394f37c723af..d5140d991161 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/volt/priv.h | |||
@@ -9,6 +9,8 @@ int nvkm_volt_new_(const struct nvkm_volt_func *, struct nvkm_device *, | |||
9 | int index, struct nvkm_volt **); | 9 | int index, struct nvkm_volt **); |
10 | 10 | ||
11 | struct nvkm_volt_func { | 11 | struct nvkm_volt_func { |
12 | int (*volt_get)(struct nvkm_volt *); | ||
13 | int (*volt_set)(struct nvkm_volt *, u32 uv); | ||
12 | int (*vid_get)(struct nvkm_volt *); | 14 | int (*vid_get)(struct nvkm_volt *); |
13 | int (*vid_set)(struct nvkm_volt *, u8 vid); | 15 | int (*vid_set)(struct nvkm_volt *, u8 vid); |
14 | int (*set_id)(struct nvkm_volt *, u8 id, int condition); | 16 | int (*set_id)(struct nvkm_volt *, u8 id, int condition); |
@@ -17,4 +19,8 @@ struct nvkm_volt_func { | |||
17 | int nvkm_voltgpio_init(struct nvkm_volt *); | 19 | int nvkm_voltgpio_init(struct nvkm_volt *); |
18 | int nvkm_voltgpio_get(struct nvkm_volt *); | 20 | int nvkm_voltgpio_get(struct nvkm_volt *); |
19 | int nvkm_voltgpio_set(struct nvkm_volt *, u8); | 21 | int nvkm_voltgpio_set(struct nvkm_volt *, u8); |
22 | |||
23 | int nvkm_voltpwm_init(struct nvkm_volt *volt); | ||
24 | int nvkm_voltpwm_get(struct nvkm_volt *volt); | ||
25 | int nvkm_voltpwm_set(struct nvkm_volt *volt, u32 uv); | ||
20 | #endif | 26 | #endif |