diff options
| author | Dave Airlie <airlied@redhat.com> | 2013-09-04 00:28:53 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2013-09-04 00:28:53 -0400 |
| commit | d30645ae1830f458b3a4908a2f869dd53e0c179b (patch) | |
| tree | 1bebcf449ab043da0fd5a90ee466131bc0f6ee47 /drivers | |
| parent | ef25bd84edba73f78ce7397ef3d7b97e2774ed07 (diff) | |
| parent | c859074e7d804a254f318bb55ba1b39893247fc7 (diff) | |
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next
Nothing major ready for merging yet, so mostly bug fixes below, in addition to VP3 enablement from Ilia.
* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6:
drm/nouveau: fix command submission to use vmalloc for big allocations
drm/nouveau/bios/therm: handle vbioses with duplicate entries (mostly nva5)
drm/nouveau: use MSI interrupts
drm/nv50-/kms: assume analog display connected if load on any pin
drm/nv50/disp: prevent false output detection on the original nv50
drm/nouveau/i2c: pass the function pointers in at creation time
drm/nouveau/therm: survive to suspend/resume cycles
drm/nouveau/timer: add a way to cancel alarms
drm/nouveau/timer: restore the time on resume
drm/nouveau/fan: restore pwm value on resume when in manual/auto mode
drm/nouveau/therm: Set the correct pwm_mode upon resume
drm/nouveau: require contiguous bo for framebuffer
drm/nv50-/disp: use the number of dac, sor, pior rather than hardcoded values
drm/nouveau: remove duplicate copy of nv44_graph_class
drm/nouveau/vdec: implement support for VP3 engines
drm/nouveau/core: get rid of math.h, replace log2i with order_base_2
Diffstat (limited to 'drivers')
37 files changed, 323 insertions, 145 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c index 86a64045dd60..f3b9bddc3875 100644 --- a/drivers/gpu/drm/nouveau/core/core/ramht.c +++ b/drivers/gpu/drm/nouveau/core/core/ramht.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | 22 | ||
| 23 | #include <core/object.h> | 23 | #include <core/object.h> |
| 24 | #include <core/ramht.h> | 24 | #include <core/ramht.h> |
| 25 | #include <core/math.h> | ||
| 26 | 25 | ||
| 27 | #include <subdev/bar.h> | 26 | #include <subdev/bar.h> |
| 28 | 27 | ||
| @@ -104,6 +103,6 @@ nouveau_ramht_new(struct nouveau_object *parent, struct nouveau_object *pargpu, | |||
| 104 | if (ret) | 103 | if (ret) |
| 105 | return ret; | 104 | return ret; |
| 106 | 105 | ||
| 107 | ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3); | 106 | ramht->bits = order_base_2(nv_gpuobj(ramht)->size >> 3); |
| 108 | return 0; | 107 | return 0; |
| 109 | } | 108 | } |
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c index 8bf92b0e6d82..6b089e022fd2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c | |||
| @@ -19,16 +19,14 @@ | |||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| 21 | * | 21 | * |
| 22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin |
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include <core/engctx.h> | 25 | #include <engine/falcon.h> |
| 26 | #include <core/class.h> | ||
| 27 | |||
| 28 | #include <engine/bsp.h> | 26 | #include <engine/bsp.h> |
| 29 | 27 | ||
| 30 | struct nv98_bsp_priv { | 28 | struct nv98_bsp_priv { |
| 31 | struct nouveau_engine base; | 29 | struct nouveau_falcon base; |
| 32 | }; | 30 | }; |
| 33 | 31 | ||
| 34 | /******************************************************************************* | 32 | /******************************************************************************* |
| @@ -37,31 +35,49 @@ struct nv98_bsp_priv { | |||
| 37 | 35 | ||
| 38 | static struct nouveau_oclass | 36 | static struct nouveau_oclass |
| 39 | nv98_bsp_sclass[] = { | 37 | nv98_bsp_sclass[] = { |
| 38 | { 0x88b1, &nouveau_object_ofuncs }, | ||
| 39 | { 0x85b1, &nouveau_object_ofuncs }, | ||
| 40 | { 0x86b1, &nouveau_object_ofuncs }, | ||
| 40 | {}, | 41 | {}, |
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| 43 | /******************************************************************************* | 44 | /******************************************************************************* |
| 44 | * BSP context | 45 | * PBSP context |
| 45 | ******************************************************************************/ | 46 | ******************************************************************************/ |
| 46 | 47 | ||
| 47 | static struct nouveau_oclass | 48 | static struct nouveau_oclass |
| 48 | nv98_bsp_cclass = { | 49 | nv98_bsp_cclass = { |
| 49 | .handle = NV_ENGCTX(BSP, 0x98), | 50 | .handle = NV_ENGCTX(BSP, 0x98), |
| 50 | .ofuncs = &(struct nouveau_ofuncs) { | 51 | .ofuncs = &(struct nouveau_ofuncs) { |
| 51 | .ctor = _nouveau_engctx_ctor, | 52 | .ctor = _nouveau_falcon_context_ctor, |
| 52 | .dtor = _nouveau_engctx_dtor, | 53 | .dtor = _nouveau_falcon_context_dtor, |
| 53 | .init = _nouveau_engctx_init, | 54 | .init = _nouveau_falcon_context_init, |
| 54 | .fini = _nouveau_engctx_fini, | 55 | .fini = _nouveau_falcon_context_fini, |
| 55 | .rd32 = _nouveau_engctx_rd32, | 56 | .rd32 = _nouveau_falcon_context_rd32, |
| 56 | .wr32 = _nouveau_engctx_wr32, | 57 | .wr32 = _nouveau_falcon_context_wr32, |
| 57 | }, | 58 | }, |
| 58 | }; | 59 | }; |
| 59 | 60 | ||
| 60 | /******************************************************************************* | 61 | /******************************************************************************* |
| 61 | * BSP engine/subdev functions | 62 | * PBSP engine/subdev functions |
| 62 | ******************************************************************************/ | 63 | ******************************************************************************/ |
| 63 | 64 | ||
| 64 | static int | 65 | static int |
| 66 | nv98_bsp_init(struct nouveau_object *object) | ||
| 67 | { | ||
| 68 | struct nv98_bsp_priv *priv = (void *)object; | ||
| 69 | int ret; | ||
| 70 | |||
| 71 | ret = nouveau_falcon_init(&priv->base); | ||
| 72 | if (ret) | ||
| 73 | return ret; | ||
| 74 | |||
| 75 | nv_wr32(priv, 0x084010, 0x0000ffd2); | ||
| 76 | nv_wr32(priv, 0x08401c, 0x0000fff2); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | static int | ||
| 65 | nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 81 | nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
| 66 | struct nouveau_oclass *oclass, void *data, u32 size, | 82 | struct nouveau_oclass *oclass, void *data, u32 size, |
| 67 | struct nouveau_object **pobject) | 83 | struct nouveau_object **pobject) |
| @@ -69,7 +85,7 @@ nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 69 | struct nv98_bsp_priv *priv; | 85 | struct nv98_bsp_priv *priv; |
| 70 | int ret; | 86 | int ret; |
| 71 | 87 | ||
| 72 | ret = nouveau_engine_create(parent, engine, oclass, true, | 88 | ret = nouveau_falcon_create(parent, engine, oclass, 0x084000, true, |
| 73 | "PBSP", "bsp", &priv); | 89 | "PBSP", "bsp", &priv); |
| 74 | *pobject = nv_object(priv); | 90 | *pobject = nv_object(priv); |
| 75 | if (ret) | 91 | if (ret) |
| @@ -86,8 +102,10 @@ nv98_bsp_oclass = { | |||
| 86 | .handle = NV_ENGINE(BSP, 0x98), | 102 | .handle = NV_ENGINE(BSP, 0x98), |
| 87 | .ofuncs = &(struct nouveau_ofuncs) { | 103 | .ofuncs = &(struct nouveau_ofuncs) { |
| 88 | .ctor = nv98_bsp_ctor, | 104 | .ctor = nv98_bsp_ctor, |
| 89 | .dtor = _nouveau_engine_dtor, | 105 | .dtor = _nouveau_falcon_dtor, |
| 90 | .init = _nouveau_engine_init, | 106 | .init = nv98_bsp_init, |
| 91 | .fini = _nouveau_engine_fini, | 107 | .fini = _nouveau_falcon_fini, |
| 108 | .rd32 = _nouveau_falcon_rd32, | ||
| 109 | .wr32 = _nouveau_falcon_wr32, | ||
| 92 | }, | 110 | }, |
| 93 | }; | 111 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c index f02fd9f443ff..a66b27c0fcab 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c | |||
| @@ -49,18 +49,23 @@ int | |||
| 49 | nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval) | 49 | nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval) |
| 50 | { | 50 | { |
| 51 | const u32 doff = (or * 0x800); | 51 | const u32 doff = (or * 0x800); |
| 52 | int load = -EINVAL; | 52 | |
| 53 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000); | 53 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000); |
| 54 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); | 54 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); |
| 55 | |||
| 55 | nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval); | 56 | nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval); |
| 56 | mdelay(9); | 57 | mdelay(9); |
| 57 | udelay(500); | 58 | udelay(500); |
| 58 | nv_wr32(priv, 0x61a00c + doff, 0x80000000); | 59 | loadval = nv_mask(priv, 0x61a00c + doff, 0xffffffff, 0x00000000); |
| 59 | load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27; | 60 | |
| 60 | nv_wr32(priv, 0x61a00c + doff, 0x00000000); | ||
| 61 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000); | 61 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000); |
| 62 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); | 62 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); |
| 63 | return load; | 63 | |
| 64 | nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval); | ||
| 65 | if (!(loadval & 0x80000000)) | ||
| 66 | return -ETIMEDOUT; | ||
| 67 | |||
| 68 | return (loadval & 0x38000000) >> 27; | ||
| 64 | } | 69 | } |
| 65 | 70 | ||
| 66 | int | 71 | int |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 7ffe2f309f12..c168ae3eaa97 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
| @@ -628,7 +628,7 @@ nv50_disp_base_init(struct nouveau_object *object) | |||
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | /* ... PIOR caps */ | 630 | /* ... PIOR caps */ |
| 631 | for (i = 0; i < 3; i++) { | 631 | for (i = 0; i < priv->pior.nr; i++) { |
| 632 | tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); | 632 | tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); |
| 633 | nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); | 633 | nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); |
| 634 | } | 634 | } |
| @@ -834,10 +834,11 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
| 834 | u8 ver, hdr, cnt, len; | 834 | u8 ver, hdr, cnt, len; |
| 835 | u16 data; | 835 | u16 data; |
| 836 | u32 ctrl = 0x00000000; | 836 | u32 ctrl = 0x00000000; |
| 837 | u32 reg; | ||
| 837 | int i; | 838 | int i; |
| 838 | 839 | ||
| 839 | /* DAC */ | 840 | /* DAC */ |
| 840 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 841 | for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++) |
| 841 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); | 842 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); |
| 842 | 843 | ||
| 843 | /* SOR */ | 844 | /* SOR */ |
| @@ -845,19 +846,18 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
| 845 | if (nv_device(priv)->chipset < 0x90 || | 846 | if (nv_device(priv)->chipset < 0x90 || |
| 846 | nv_device(priv)->chipset == 0x92 || | 847 | nv_device(priv)->chipset == 0x92 || |
| 847 | nv_device(priv)->chipset == 0xa0) { | 848 | nv_device(priv)->chipset == 0xa0) { |
| 848 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 849 | reg = 0x610b74; |
| 849 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); | ||
| 850 | i += 4; | ||
| 851 | } else { | 850 | } else { |
| 852 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 851 | reg = 0x610798; |
| 853 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); | ||
| 854 | i += 4; | ||
| 855 | } | 852 | } |
| 853 | for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++) | ||
| 854 | ctrl = nv_rd32(priv, reg + (i * 8)); | ||
| 855 | i += 4; | ||
| 856 | } | 856 | } |
| 857 | 857 | ||
| 858 | /* PIOR */ | 858 | /* PIOR */ |
| 859 | if (!(ctrl & (1 << head))) { | 859 | if (!(ctrl & (1 << head))) { |
| 860 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 860 | for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++) |
| 861 | ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); | 861 | ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); |
| 862 | i += 8; | 862 | i += 8; |
| 863 | } | 863 | } |
| @@ -893,10 +893,11 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
| 893 | u8 ver, hdr, cnt, len; | 893 | u8 ver, hdr, cnt, len; |
| 894 | u32 ctrl = 0x00000000; | 894 | u32 ctrl = 0x00000000; |
| 895 | u32 data, conf = ~0; | 895 | u32 data, conf = ~0; |
| 896 | u32 reg; | ||
| 896 | int i; | 897 | int i; |
| 897 | 898 | ||
| 898 | /* DAC */ | 899 | /* DAC */ |
| 899 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 900 | for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++) |
| 900 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); | 901 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); |
| 901 | 902 | ||
| 902 | /* SOR */ | 903 | /* SOR */ |
| @@ -904,19 +905,18 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
| 904 | if (nv_device(priv)->chipset < 0x90 || | 905 | if (nv_device(priv)->chipset < 0x90 || |
| 905 | nv_device(priv)->chipset == 0x92 || | 906 | nv_device(priv)->chipset == 0x92 || |
| 906 | nv_device(priv)->chipset == 0xa0) { | 907 | nv_device(priv)->chipset == 0xa0) { |
| 907 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 908 | reg = 0x610b70; |
| 908 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); | ||
| 909 | i += 4; | ||
| 910 | } else { | 909 | } else { |
| 911 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 910 | reg = 0x610794; |
| 912 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); | ||
| 913 | i += 4; | ||
| 914 | } | 911 | } |
| 912 | for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++) | ||
| 913 | ctrl = nv_rd32(priv, reg + (i * 8)); | ||
| 914 | i += 4; | ||
| 915 | } | 915 | } |
| 916 | 916 | ||
| 917 | /* PIOR */ | 917 | /* PIOR */ |
| 918 | if (!(ctrl & (1 << head))) { | 918 | if (!(ctrl & (1 << head))) { |
| 919 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 919 | for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++) |
| 920 | ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); | 920 | ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); |
| 921 | i += 8; | 921 | i += 8; |
| 922 | } | 922 | } |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index e9b8217d0075..7e5dff51d3c5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <core/engctx.h> | 26 | #include <core/engctx.h> |
| 27 | #include <core/ramht.h> | 27 | #include <core/ramht.h> |
| 28 | #include <core/class.h> | 28 | #include <core/class.h> |
| 29 | #include <core/math.h> | ||
| 30 | 29 | ||
| 31 | #include <subdev/timer.h> | 30 | #include <subdev/timer.h> |
| 32 | #include <subdev/bar.h> | 31 | #include <subdev/bar.h> |
| @@ -278,7 +277,7 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, | |||
| 278 | return ret; | 277 | return ret; |
| 279 | 278 | ||
| 280 | ioffset = args->ioffset; | 279 | ioffset = args->ioffset; |
| 281 | ilength = log2i(args->ilength / 8); | 280 | ilength = order_base_2(args->ilength / 8); |
| 282 | 281 | ||
| 283 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); | 282 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); |
| 284 | nv_wo32(base->ramfc, 0x44, 0x01003fff); | 283 | nv_wo32(base->ramfc, 0x44, 0x01003fff); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 7f53196cff52..91a87cd7195a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <core/ramht.h> | 28 | #include <core/ramht.h> |
| 29 | #include <core/event.h> | 29 | #include <core/event.h> |
| 30 | #include <core/class.h> | 30 | #include <core/class.h> |
| 31 | #include <core/math.h> | ||
| 32 | 31 | ||
| 33 | #include <subdev/timer.h> | 32 | #include <subdev/timer.h> |
| 34 | #include <subdev/bar.h> | 33 | #include <subdev/bar.h> |
| @@ -57,6 +56,7 @@ nv84_fifo_context_attach(struct nouveau_object *parent, | |||
| 57 | case NVDEV_ENGINE_SW : return 0; | 56 | case NVDEV_ENGINE_SW : return 0; |
| 58 | case NVDEV_ENGINE_GR : addr = 0x0020; break; | 57 | case NVDEV_ENGINE_GR : addr = 0x0020; break; |
| 59 | case NVDEV_ENGINE_VP : addr = 0x0040; break; | 58 | case NVDEV_ENGINE_VP : addr = 0x0040; break; |
| 59 | case NVDEV_ENGINE_PPP : | ||
| 60 | case NVDEV_ENGINE_MPEG : addr = 0x0060; break; | 60 | case NVDEV_ENGINE_MPEG : addr = 0x0060; break; |
| 61 | case NVDEV_ENGINE_BSP : addr = 0x0080; break; | 61 | case NVDEV_ENGINE_BSP : addr = 0x0080; break; |
| 62 | case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; | 62 | case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; |
| @@ -92,6 +92,7 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
| 92 | case NVDEV_ENGINE_SW : return 0; | 92 | case NVDEV_ENGINE_SW : return 0; |
| 93 | case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break; | 93 | case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break; |
| 94 | case NVDEV_ENGINE_VP : engn = 3; addr = 0x0040; break; | 94 | case NVDEV_ENGINE_VP : engn = 3; addr = 0x0040; break; |
| 95 | case NVDEV_ENGINE_PPP : | ||
| 95 | case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break; | 96 | case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break; |
| 96 | case NVDEV_ENGINE_BSP : engn = 5; addr = 0x0080; break; | 97 | case NVDEV_ENGINE_BSP : engn = 5; addr = 0x0080; break; |
| 97 | case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break; | 98 | case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break; |
| @@ -258,7 +259,7 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, | |||
| 258 | nv_parent(chan)->object_detach = nv50_fifo_object_detach; | 259 | nv_parent(chan)->object_detach = nv50_fifo_object_detach; |
| 259 | 260 | ||
| 260 | ioffset = args->ioffset; | 261 | ioffset = args->ioffset; |
| 261 | ilength = log2i(args->ilength / 8); | 262 | ilength = order_base_2(args->ilength / 8); |
| 262 | 263 | ||
| 263 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); | 264 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); |
| 264 | nv_wo32(base->ramfc, 0x44, 0x01003fff); | 265 | nv_wo32(base->ramfc, 0x44, 0x01003fff); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 46dfa68c47bb..ce92f289e751 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <core/engctx.h> | 29 | #include <core/engctx.h> |
| 30 | #include <core/event.h> | 30 | #include <core/event.h> |
| 31 | #include <core/class.h> | 31 | #include <core/class.h> |
| 32 | #include <core/math.h> | ||
| 33 | #include <core/enum.h> | 32 | #include <core/enum.h> |
| 34 | 33 | ||
| 35 | #include <subdev/timer.h> | 34 | #include <subdev/timer.h> |
| @@ -200,7 +199,7 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent, | |||
| 200 | 199 | ||
| 201 | usermem = chan->base.chid * 0x1000; | 200 | usermem = chan->base.chid * 0x1000; |
| 202 | ioffset = args->ioffset; | 201 | ioffset = args->ioffset; |
| 203 | ilength = log2i(args->ilength / 8); | 202 | ilength = order_base_2(args->ilength / 8); |
| 204 | 203 | ||
| 205 | for (i = 0; i < 0x1000; i += 4) | 204 | for (i = 0; i < 0x1000; i += 4) |
| 206 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); | 205 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 09644fa9602c..8e8121abe31b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <core/engctx.h> | 29 | #include <core/engctx.h> |
| 30 | #include <core/event.h> | 30 | #include <core/event.h> |
| 31 | #include <core/class.h> | 31 | #include <core/class.h> |
| 32 | #include <core/math.h> | ||
| 33 | #include <core/enum.h> | 32 | #include <core/enum.h> |
| 34 | 33 | ||
| 35 | #include <subdev/timer.h> | 34 | #include <subdev/timer.h> |
| @@ -240,7 +239,7 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent, | |||
| 240 | 239 | ||
| 241 | usermem = chan->base.chid * 0x200; | 240 | usermem = chan->base.chid * 0x200; |
| 242 | ioffset = args->ioffset; | 241 | ioffset = args->ioffset; |
| 243 | ilength = log2i(args->ilength / 8); | 242 | ilength = order_base_2(args->ilength / 8); |
| 244 | 243 | ||
| 245 | for (i = 0; i < 0x200; i += 4) | 244 | for (i = 0; i < 0x200; i += 4) |
| 246 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); | 245 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h index 7da35a4e7970..ad8209377529 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | #ifndef __NV40_GRAPH_H__ | 1 | #ifndef __NV40_GRAPH_H__ |
| 2 | #define __NV40_GRAPH_H__ | 2 | #define __NV40_GRAPH_H__ |
| 3 | 3 | ||
| 4 | #include <core/device.h> | ||
| 5 | #include <core/gpuobj.h> | ||
| 6 | |||
| 4 | /* returns 1 if device is one of the nv4x using the 0x4497 object class, | 7 | /* returns 1 if device is one of the nv4x using the 0x4497 object class, |
| 5 | * helpful to determine a number of other hardware features | 8 | * helpful to determine a number of other hardware features |
| 6 | */ | 9 | */ |
diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c index 5a5b2a773ed7..13bf31c40aa1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | |||
| @@ -19,21 +19,14 @@ | |||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| 21 | * | 21 | * |
| 22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin |
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include <core/engine.h> | 25 | #include <engine/falcon.h> |
| 26 | #include <core/engctx.h> | ||
| 27 | #include <core/class.h> | ||
| 28 | |||
| 29 | #include <engine/ppp.h> | 26 | #include <engine/ppp.h> |
| 30 | 27 | ||
| 31 | struct nv98_ppp_priv { | 28 | struct nv98_ppp_priv { |
| 32 | struct nouveau_engine base; | 29 | struct nouveau_falcon base; |
| 33 | }; | ||
| 34 | |||
| 35 | struct nv98_ppp_chan { | ||
| 36 | struct nouveau_engctx base; | ||
| 37 | }; | 30 | }; |
| 38 | 31 | ||
| 39 | /******************************************************************************* | 32 | /******************************************************************************* |
| @@ -42,6 +35,8 @@ struct nv98_ppp_chan { | |||
| 42 | 35 | ||
| 43 | static struct nouveau_oclass | 36 | static struct nouveau_oclass |
| 44 | nv98_ppp_sclass[] = { | 37 | nv98_ppp_sclass[] = { |
| 38 | { 0x88b3, &nouveau_object_ofuncs }, | ||
| 39 | { 0x85b3, &nouveau_object_ofuncs }, | ||
| 45 | {}, | 40 | {}, |
| 46 | }; | 41 | }; |
| 47 | 42 | ||
| @@ -53,12 +48,12 @@ static struct nouveau_oclass | |||
| 53 | nv98_ppp_cclass = { | 48 | nv98_ppp_cclass = { |
| 54 | .handle = NV_ENGCTX(PPP, 0x98), | 49 | .handle = NV_ENGCTX(PPP, 0x98), |
| 55 | .ofuncs = &(struct nouveau_ofuncs) { | 50 | .ofuncs = &(struct nouveau_ofuncs) { |
| 56 | .ctor = _nouveau_engctx_ctor, | 51 | .ctor = _nouveau_falcon_context_ctor, |
| 57 | .dtor = _nouveau_engctx_dtor, | 52 | .dtor = _nouveau_falcon_context_dtor, |
| 58 | .init = _nouveau_engctx_init, | 53 | .init = _nouveau_falcon_context_init, |
| 59 | .fini = _nouveau_engctx_fini, | 54 | .fini = _nouveau_falcon_context_fini, |
| 60 | .rd32 = _nouveau_engctx_rd32, | 55 | .rd32 = _nouveau_falcon_context_rd32, |
| 61 | .wr32 = _nouveau_engctx_wr32, | 56 | .wr32 = _nouveau_falcon_context_wr32, |
| 62 | }, | 57 | }, |
| 63 | }; | 58 | }; |
| 64 | 59 | ||
| @@ -67,6 +62,21 @@ nv98_ppp_cclass = { | |||
| 67 | ******************************************************************************/ | 62 | ******************************************************************************/ |
| 68 | 63 | ||
| 69 | static int | 64 | static int |
| 65 | nv98_ppp_init(struct nouveau_object *object) | ||
| 66 | { | ||
| 67 | struct nv98_ppp_priv *priv = (void *)object; | ||
| 68 | int ret; | ||
| 69 | |||
| 70 | ret = nouveau_falcon_init(&priv->base); | ||
| 71 | if (ret) | ||
| 72 | return ret; | ||
| 73 | |||
| 74 | nv_wr32(priv, 0x086010, 0x0000ffd2); | ||
| 75 | nv_wr32(priv, 0x08601c, 0x0000fff2); | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int | ||
| 70 | nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 80 | nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
| 71 | struct nouveau_oclass *oclass, void *data, u32 size, | 81 | struct nouveau_oclass *oclass, void *data, u32 size, |
| 72 | struct nouveau_object **pobject) | 82 | struct nouveau_object **pobject) |
| @@ -74,7 +84,7 @@ nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 74 | struct nv98_ppp_priv *priv; | 84 | struct nv98_ppp_priv *priv; |
| 75 | int ret; | 85 | int ret; |
| 76 | 86 | ||
| 77 | ret = nouveau_engine_create(parent, engine, oclass, true, | 87 | ret = nouveau_falcon_create(parent, engine, oclass, 0x086000, true, |
| 78 | "PPPP", "ppp", &priv); | 88 | "PPPP", "ppp", &priv); |
| 79 | *pobject = nv_object(priv); | 89 | *pobject = nv_object(priv); |
| 80 | if (ret) | 90 | if (ret) |
| @@ -91,8 +101,10 @@ nv98_ppp_oclass = { | |||
| 91 | .handle = NV_ENGINE(PPP, 0x98), | 101 | .handle = NV_ENGINE(PPP, 0x98), |
| 92 | .ofuncs = &(struct nouveau_ofuncs) { | 102 | .ofuncs = &(struct nouveau_ofuncs) { |
| 93 | .ctor = nv98_ppp_ctor, | 103 | .ctor = nv98_ppp_ctor, |
| 94 | .dtor = _nouveau_engine_dtor, | 104 | .dtor = _nouveau_falcon_dtor, |
| 95 | .init = _nouveau_engine_init, | 105 | .init = nv98_ppp_init, |
| 96 | .fini = _nouveau_engine_fini, | 106 | .fini = _nouveau_falcon_fini, |
| 107 | .rd32 = _nouveau_falcon_rd32, | ||
| 108 | .wr32 = _nouveau_falcon_wr32, | ||
| 97 | }, | 109 | }, |
| 98 | }; | 110 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c index 8a8236bc84de..fc9ae0ff1ef5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c | |||
| @@ -19,16 +19,14 @@ | |||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
| 21 | * | 21 | * |
| 22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin |
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include <core/engctx.h> | 25 | #include <engine/falcon.h> |
| 26 | #include <core/class.h> | ||
| 27 | |||
| 28 | #include <engine/vp.h> | 26 | #include <engine/vp.h> |
| 29 | 27 | ||
| 30 | struct nv98_vp_priv { | 28 | struct nv98_vp_priv { |
| 31 | struct nouveau_engine base; | 29 | struct nouveau_falcon base; |
| 32 | }; | 30 | }; |
| 33 | 31 | ||
| 34 | /******************************************************************************* | 32 | /******************************************************************************* |
| @@ -37,6 +35,8 @@ struct nv98_vp_priv { | |||
| 37 | 35 | ||
| 38 | static struct nouveau_oclass | 36 | static struct nouveau_oclass |
| 39 | nv98_vp_sclass[] = { | 37 | nv98_vp_sclass[] = { |
| 38 | { 0x88b2, &nouveau_object_ofuncs }, | ||
| 39 | { 0x85b2, &nouveau_object_ofuncs }, | ||
| 40 | {}, | 40 | {}, |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| @@ -48,12 +48,12 @@ static struct nouveau_oclass | |||
| 48 | nv98_vp_cclass = { | 48 | nv98_vp_cclass = { |
| 49 | .handle = NV_ENGCTX(VP, 0x98), | 49 | .handle = NV_ENGCTX(VP, 0x98), |
| 50 | .ofuncs = &(struct nouveau_ofuncs) { | 50 | .ofuncs = &(struct nouveau_ofuncs) { |
| 51 | .ctor = _nouveau_engctx_ctor, | 51 | .ctor = _nouveau_falcon_context_ctor, |
| 52 | .dtor = _nouveau_engctx_dtor, | 52 | .dtor = _nouveau_falcon_context_dtor, |
| 53 | .init = _nouveau_engctx_init, | 53 | .init = _nouveau_falcon_context_init, |
| 54 | .fini = _nouveau_engctx_fini, | 54 | .fini = _nouveau_falcon_context_fini, |
| 55 | .rd32 = _nouveau_engctx_rd32, | 55 | .rd32 = _nouveau_falcon_context_rd32, |
| 56 | .wr32 = _nouveau_engctx_wr32, | 56 | .wr32 = _nouveau_falcon_context_wr32, |
| 57 | }, | 57 | }, |
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| @@ -62,6 +62,21 @@ nv98_vp_cclass = { | |||
| 62 | ******************************************************************************/ | 62 | ******************************************************************************/ |
| 63 | 63 | ||
| 64 | static int | 64 | static int |
| 65 | nv98_vp_init(struct nouveau_object *object) | ||
| 66 | { | ||
| 67 | struct nv98_vp_priv *priv = (void *)object; | ||
| 68 | int ret; | ||
| 69 | |||
| 70 | ret = nouveau_falcon_init(&priv->base); | ||
| 71 | if (ret) | ||
| 72 | return ret; | ||
| 73 | |||
| 74 | nv_wr32(priv, 0x085010, 0x0000ffd2); | ||
| 75 | nv_wr32(priv, 0x08501c, 0x0000fff2); | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int | ||
| 65 | nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 80 | nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
| 66 | struct nouveau_oclass *oclass, void *data, u32 size, | 81 | struct nouveau_oclass *oclass, void *data, u32 size, |
| 67 | struct nouveau_object **pobject) | 82 | struct nouveau_object **pobject) |
| @@ -69,7 +84,7 @@ nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 69 | struct nv98_vp_priv *priv; | 84 | struct nv98_vp_priv *priv; |
| 70 | int ret; | 85 | int ret; |
| 71 | 86 | ||
| 72 | ret = nouveau_engine_create(parent, engine, oclass, true, | 87 | ret = nouveau_falcon_create(parent, engine, oclass, 0x085000, true, |
| 73 | "PVP", "vp", &priv); | 88 | "PVP", "vp", &priv); |
| 74 | *pobject = nv_object(priv); | 89 | *pobject = nv_object(priv); |
| 75 | if (ret) | 90 | if (ret) |
| @@ -86,8 +101,10 @@ nv98_vp_oclass = { | |||
| 86 | .handle = NV_ENGINE(VP, 0x98), | 101 | .handle = NV_ENGINE(VP, 0x98), |
| 87 | .ofuncs = &(struct nouveau_ofuncs) { | 102 | .ofuncs = &(struct nouveau_ofuncs) { |
| 88 | .ctor = nv98_vp_ctor, | 103 | .ctor = nv98_vp_ctor, |
| 89 | .dtor = _nouveau_engine_dtor, | 104 | .dtor = _nouveau_falcon_dtor, |
| 90 | .init = _nouveau_engine_init, | 105 | .init = nv98_vp_init, |
| 91 | .fini = _nouveau_engine_fini, | 106 | .fini = _nouveau_falcon_fini, |
| 107 | .rd32 = _nouveau_falcon_rd32, | ||
| 108 | .wr32 = _nouveau_falcon_wr32, | ||
| 92 | }, | 109 | }, |
| 93 | }; | 110 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/math.h b/drivers/gpu/drm/nouveau/core/include/core/math.h deleted file mode 100644 index f808131c5cd8..000000000000 --- a/drivers/gpu/drm/nouveau/core/include/core/math.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | #ifndef __NOUVEAU_MATH_H__ | ||
| 2 | #define __NOUVEAU_MATH_H__ | ||
| 3 | |||
| 4 | static inline int | ||
| 5 | log2i(u64 base) | ||
| 6 | { | ||
| 7 | u64 temp = base >> 1; | ||
| 8 | int log2; | ||
| 9 | |||
| 10 | for (log2 = 0; temp; log2++, temp >>= 1) { | ||
| 11 | } | ||
| 12 | |||
| 13 | return (base & (base - 1)) ? log2 + 1: log2; | ||
| 14 | } | ||
| 15 | |||
| 16 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 888384c0bed8..7e4e2775f249 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | |||
| @@ -39,8 +39,8 @@ struct nouveau_i2c_func { | |||
| 39 | int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); | 39 | int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); |
| 40 | }; | 40 | }; |
| 41 | 41 | ||
| 42 | #define nouveau_i2c_port_create(p,e,o,i,a,d) \ | 42 | #define nouveau_i2c_port_create(p,e,o,i,a,f,d) \ |
| 43 | nouveau_i2c_port_create_((p), (e), (o), (i), (a), \ | 43 | nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f), \ |
| 44 | sizeof(**d), (void **)d) | 44 | sizeof(**d), (void **)d) |
| 45 | #define nouveau_i2c_port_destroy(p) ({ \ | 45 | #define nouveau_i2c_port_destroy(p) ({ \ |
| 46 | struct nouveau_i2c_port *port = (p); \ | 46 | struct nouveau_i2c_port *port = (p); \ |
| @@ -53,7 +53,9 @@ struct nouveau_i2c_func { | |||
| 53 | 53 | ||
| 54 | int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, | 54 | int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, |
| 55 | struct nouveau_oclass *, u8, | 55 | struct nouveau_oclass *, u8, |
| 56 | const struct i2c_algorithm *, int, void **); | 56 | const struct i2c_algorithm *, |
| 57 | const struct nouveau_i2c_func *, | ||
| 58 | int, void **); | ||
| 57 | void _nouveau_i2c_port_dtor(struct nouveau_object *); | 59 | void _nouveau_i2c_port_dtor(struct nouveau_object *); |
| 58 | #define _nouveau_i2c_port_init nouveau_object_init | 60 | #define _nouveau_i2c_port_init nouveau_object_init |
| 59 | #define _nouveau_i2c_port_fini nouveau_object_fini | 61 | #define _nouveau_i2c_port_fini nouveau_object_fini |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index 9d2cd2006250..ce6569f365a7 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h | |||
| @@ -12,6 +12,7 @@ struct nouveau_mc_intr { | |||
| 12 | struct nouveau_mc { | 12 | struct nouveau_mc { |
| 13 | struct nouveau_subdev base; | 13 | struct nouveau_subdev base; |
| 14 | const struct nouveau_mc_intr *intr_map; | 14 | const struct nouveau_mc_intr *intr_map; |
| 15 | bool use_msi; | ||
| 15 | }; | 16 | }; |
| 16 | 17 | ||
| 17 | static inline struct nouveau_mc * | 18 | static inline struct nouveau_mc * |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index e465d158d352..9ab70dfe5b02 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h | |||
| @@ -22,6 +22,7 @@ bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); | |||
| 22 | bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); | 22 | bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); |
| 23 | bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); | 23 | bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); |
| 24 | void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); | 24 | void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); |
| 25 | void nouveau_timer_alarm_cancel(void *, struct nouveau_alarm *); | ||
| 25 | 26 | ||
| 26 | #define NV_WAIT_DEFAULT 2000000000ULL | 27 | #define NV_WAIT_DEFAULT 2000000000ULL |
| 27 | #define nv_wait(o,a,m,v) \ | 28 | #define nv_wait(o,a,m,v) \ |
| @@ -35,6 +36,7 @@ struct nouveau_timer { | |||
| 35 | struct nouveau_subdev base; | 36 | struct nouveau_subdev base; |
| 36 | u64 (*read)(struct nouveau_timer *); | 37 | u64 (*read)(struct nouveau_timer *); |
| 37 | void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *); | 38 | void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *); |
| 39 | void (*alarm_cancel)(struct nouveau_timer *, struct nouveau_alarm *); | ||
| 38 | }; | 40 | }; |
| 39 | 41 | ||
| 40 | static inline struct nouveau_timer * | 42 | static inline struct nouveau_timer * |
diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 3bd9be2ab37f..191e739f30d1 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h | |||
| @@ -13,11 +13,13 @@ | |||
| 13 | #include <linux/i2c-algo-bit.h> | 13 | #include <linux/i2c-algo-bit.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/io-mapping.h> | 15 | #include <linux/io-mapping.h> |
| 16 | #include <linux/vmalloc.h> | ||
| 17 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
| 17 | #include <linux/vmalloc.h> | ||
| 18 | #include <linux/dmi.h> | 18 | #include <linux/dmi.h> |
| 19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/log2.h> | ||
| 22 | #include <linux/pm_runtime.h> | ||
| 21 | 23 | ||
| 22 | #include <asm/unaligned.h> | 24 | #include <asm/unaligned.h> |
| 23 | 25 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c index 22a20573ed1b..22ac6dbd6c8f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c | |||
| @@ -184,7 +184,8 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios, | |||
| 184 | cur_trip->fan_duty = value; | 184 | cur_trip->fan_duty = value; |
| 185 | break; | 185 | break; |
| 186 | case 0x26: | 186 | case 0x26: |
| 187 | fan->pwm_freq = value; | 187 | if (!fan->pwm_freq) |
| 188 | fan->pwm_freq = value; | ||
| 188 | break; | 189 | break; |
| 189 | case 0x3b: | 190 | case 0x3b: |
| 190 | fan->bump_period = value; | 191 | fan->bump_period = value; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c index dec94e9d776a..4b195ac4da66 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c | |||
| @@ -118,7 +118,8 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent, | |||
| 118 | int ret; | 118 | int ret; |
| 119 | 119 | ||
| 120 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 120 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 121 | &nouveau_i2c_aux_algo, &chan); | 121 | &nouveau_i2c_aux_algo, &anx9805_aux_func, |
| 122 | &chan); | ||
| 122 | *pobject = nv_object(chan); | 123 | *pobject = nv_object(chan); |
| 123 | if (ret) | 124 | if (ret) |
| 124 | return ret; | 125 | return ret; |
| @@ -140,8 +141,6 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent, | |||
| 140 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; | 141 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; |
| 141 | algo->udelay = max(algo->udelay, 40); | 142 | algo->udelay = max(algo->udelay, 40); |
| 142 | } | 143 | } |
| 143 | |||
| 144 | chan->base.func = &anx9805_aux_func; | ||
| 145 | return 0; | 144 | return 0; |
| 146 | } | 145 | } |
| 147 | 146 | ||
| @@ -234,7 +233,8 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent, | |||
| 234 | int ret; | 233 | int ret; |
| 235 | 234 | ||
| 236 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 235 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 237 | &anx9805_i2c_algo, &port); | 236 | &anx9805_i2c_algo, &anx9805_i2c_func, |
| 237 | &port); | ||
| 238 | *pobject = nv_object(port); | 238 | *pobject = nv_object(port); |
| 239 | if (ret) | 239 | if (ret) |
| 240 | return ret; | 240 | return ret; |
| @@ -256,8 +256,6 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent, | |||
| 256 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; | 256 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; |
| 257 | algo->udelay = max(algo->udelay, 40); | 257 | algo->udelay = max(algo->udelay, 40); |
| 258 | } | 258 | } |
| 259 | |||
| 260 | port->base.func = &anx9805_i2c_func; | ||
| 261 | return 0; | 259 | return 0; |
| 262 | } | 260 | } |
| 263 | 261 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 8ae2625415e1..2895c19bb152 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | |||
| @@ -95,6 +95,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent, | |||
| 95 | struct nouveau_object *engine, | 95 | struct nouveau_object *engine, |
| 96 | struct nouveau_oclass *oclass, u8 index, | 96 | struct nouveau_oclass *oclass, u8 index, |
| 97 | const struct i2c_algorithm *algo, | 97 | const struct i2c_algorithm *algo, |
| 98 | const struct nouveau_i2c_func *func, | ||
| 98 | int size, void **pobject) | 99 | int size, void **pobject) |
| 99 | { | 100 | { |
| 100 | struct nouveau_device *device = nv_device(parent); | 101 | struct nouveau_device *device = nv_device(parent); |
| @@ -112,6 +113,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent, | |||
| 112 | port->adapter.owner = THIS_MODULE; | 113 | port->adapter.owner = THIS_MODULE; |
| 113 | port->adapter.dev.parent = &device->pdev->dev; | 114 | port->adapter.dev.parent = &device->pdev->dev; |
| 114 | port->index = index; | 115 | port->index = index; |
| 116 | port->func = func; | ||
| 115 | i2c_set_adapdata(&port->adapter, i2c); | 117 | i2c_set_adapdata(&port->adapter, i2c); |
| 116 | 118 | ||
| 117 | if ( algo == &nouveau_i2c_bit_algo && | 119 | if ( algo == &nouveau_i2c_bit_algo && |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c index 2ad18840fe63..860d5d2365da 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c | |||
| @@ -91,12 +91,12 @@ nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 91 | int ret; | 91 | int ret; |
| 92 | 92 | ||
| 93 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 93 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 94 | &nouveau_i2c_bit_algo, &port); | 94 | &nouveau_i2c_bit_algo, &nv04_i2c_func, |
| 95 | &port); | ||
| 95 | *pobject = nv_object(port); | 96 | *pobject = nv_object(port); |
| 96 | if (ret) | 97 | if (ret) |
| 97 | return ret; | 98 | return ret; |
| 98 | 99 | ||
| 99 | port->base.func = &nv04_i2c_func; | ||
| 100 | port->drive = info->drive; | 100 | port->drive = info->drive; |
| 101 | port->sense = info->sense; | 101 | port->sense = info->sense; |
| 102 | return 0; | 102 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c index f501ae25dbb3..0c2655a03bb4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c | |||
| @@ -84,12 +84,12 @@ nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 84 | int ret; | 84 | int ret; |
| 85 | 85 | ||
| 86 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 86 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 87 | &nouveau_i2c_bit_algo, &port); | 87 | &nouveau_i2c_bit_algo, &nv4e_i2c_func, |
| 88 | &port); | ||
| 88 | *pobject = nv_object(port); | 89 | *pobject = nv_object(port); |
| 89 | if (ret) | 90 | if (ret) |
| 90 | return ret; | 91 | return ret; |
| 91 | 92 | ||
| 92 | port->base.func = &nv4e_i2c_func; | ||
| 93 | port->addr = 0x600800 + info->drive; | 93 | port->addr = 0x600800 + info->drive; |
| 94 | return 0; | 94 | return 0; |
| 95 | } | 95 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c index 378dfa324e5f..a8d67a287704 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c | |||
| @@ -85,7 +85,8 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 85 | int ret; | 85 | int ret; |
| 86 | 86 | ||
| 87 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 87 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 88 | &nouveau_i2c_bit_algo, &port); | 88 | &nouveau_i2c_bit_algo, &nv50_i2c_func, |
| 89 | &port); | ||
| 89 | *pobject = nv_object(port); | 90 | *pobject = nv_object(port); |
| 90 | if (ret) | 91 | if (ret) |
| 91 | return ret; | 92 | return ret; |
| @@ -93,7 +94,6 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 93 | if (info->drive >= nv50_i2c_addr_nr) | 94 | if (info->drive >= nv50_i2c_addr_nr) |
| 94 | return -EINVAL; | 95 | return -EINVAL; |
| 95 | 96 | ||
| 96 | port->base.func = &nv50_i2c_func; | ||
| 97 | port->state = 0x00000007; | 97 | port->state = 0x00000007; |
| 98 | port->addr = nv50_i2c_addr[info->drive]; | 98 | port->addr = nv50_i2c_addr[info->drive]; |
| 99 | return 0; | 99 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c index 61b771670bfe..df6d3e4b68be 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c | |||
| @@ -186,7 +186,8 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 186 | int ret; | 186 | int ret; |
| 187 | 187 | ||
| 188 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 188 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 189 | &nouveau_i2c_bit_algo, &port); | 189 | &nouveau_i2c_bit_algo, &nv94_i2c_func, |
| 190 | &port); | ||
| 190 | *pobject = nv_object(port); | 191 | *pobject = nv_object(port); |
| 191 | if (ret) | 192 | if (ret) |
| 192 | return ret; | 193 | return ret; |
| @@ -194,7 +195,6 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 194 | if (info->drive >= nv50_i2c_addr_nr) | 195 | if (info->drive >= nv50_i2c_addr_nr) |
| 195 | return -EINVAL; | 196 | return -EINVAL; |
| 196 | 197 | ||
| 197 | port->base.func = &nv94_i2c_func; | ||
| 198 | port->state = 7; | 198 | port->state = 7; |
| 199 | port->addr = nv50_i2c_addr[info->drive]; | 199 | port->addr = nv50_i2c_addr[info->drive]; |
| 200 | if (info->share != DCB_I2C_UNUSED) { | 200 | if (info->share != DCB_I2C_UNUSED) { |
| @@ -221,12 +221,12 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 221 | int ret; | 221 | int ret; |
| 222 | 222 | ||
| 223 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 223 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 224 | &nouveau_i2c_aux_algo, &port); | 224 | &nouveau_i2c_aux_algo, &nv94_aux_func, |
| 225 | &port); | ||
| 225 | *pobject = nv_object(port); | 226 | *pobject = nv_object(port); |
| 226 | if (ret) | 227 | if (ret) |
| 227 | return ret; | 228 | return ret; |
| 228 | 229 | ||
| 229 | port->base.func = &nv94_aux_func; | ||
| 230 | port->addr = info->drive; | 230 | port->addr = info->drive; |
| 231 | if (info->share != DCB_I2C_UNUSED) { | 231 | if (info->share != DCB_I2C_UNUSED) { |
| 232 | port->ctrl = 0x00e500 + (info->drive * 0x50); | 232 | port->ctrl = 0x00e500 + (info->drive * 0x50); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c index f761b8a610f1..29967d30f97c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c | |||
| @@ -60,12 +60,12 @@ nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 60 | int ret; | 60 | int ret; |
| 61 | 61 | ||
| 62 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 62 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
| 63 | &nouveau_i2c_bit_algo, &port); | 63 | &nouveau_i2c_bit_algo, &nvd0_i2c_func, |
| 64 | &port); | ||
| 64 | *pobject = nv_object(port); | 65 | *pobject = nv_object(port); |
| 65 | if (ret) | 66 | if (ret) |
| 66 | return ret; | 67 | return ret; |
| 67 | 68 | ||
| 68 | port->base.func = &nvd0_i2c_func; | ||
| 69 | port->state = 0x00000007; | 69 | port->state = 0x00000007; |
| 70 | port->addr = 0x00d014 + (info->drive * 0x20); | 70 | port->addr = 0x00d014 + (info->drive * 0x20); |
| 71 | if (info->share != DCB_I2C_UNUSED) { | 71 | if (info->share != DCB_I2C_UNUSED) { |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 716bf41bc3c1..b10a143787a7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | |||
| @@ -22,15 +22,9 @@ | |||
| 22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include "nv04.h" | 25 | #include <engine/graph/nv40.h> |
| 26 | 26 | ||
| 27 | static inline int | 27 | #include "nv04.h" |
| 28 | nv44_graph_class(struct nv04_instmem_priv *priv) | ||
| 29 | { | ||
| 30 | if ((nv_device(priv)->chipset & 0xf0) == 0x60) | ||
| 31 | return 1; | ||
| 32 | return !(0x0baf & (1 << (nv_device(priv)->chipset & 0x0f))); | ||
| 33 | } | ||
| 34 | 28 | ||
| 35 | static int | 29 | static int |
| 36 | nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 30 | nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 20f9a538746e..37712a6df923 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | */ | 23 | */ |
| 24 | 24 | ||
| 25 | #include <subdev/mc.h> | 25 | #include <subdev/mc.h> |
| 26 | #include <linux/pm_runtime.h> | 26 | #include <core/option.h> |
| 27 | 27 | ||
| 28 | static irqreturn_t | 28 | static irqreturn_t |
| 29 | nouveau_mc_intr(int irq, void *arg) | 29 | nouveau_mc_intr(int irq, void *arg) |
| @@ -47,6 +47,9 @@ nouveau_mc_intr(int irq, void *arg) | |||
| 47 | map++; | 47 | map++; |
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | if (pmc->use_msi) | ||
| 51 | nv_wr08(pmc->base.base.parent, 0x00088068, 0xff); | ||
| 52 | |||
| 50 | if (intr) { | 53 | if (intr) { |
| 51 | nv_error(pmc, "unknown intr 0x%08x\n", stat); | 54 | nv_error(pmc, "unknown intr 0x%08x\n", stat); |
| 52 | } | 55 | } |
| @@ -81,6 +84,8 @@ _nouveau_mc_dtor(struct nouveau_object *object) | |||
| 81 | struct nouveau_device *device = nv_device(object); | 84 | struct nouveau_device *device = nv_device(object); |
| 82 | struct nouveau_mc *pmc = (void *)object; | 85 | struct nouveau_mc *pmc = (void *)object; |
| 83 | free_irq(device->pdev->irq, pmc); | 86 | free_irq(device->pdev->irq, pmc); |
| 87 | if (pmc->use_msi) | ||
| 88 | pci_disable_msi(device->pdev); | ||
| 84 | nouveau_subdev_destroy(&pmc->base); | 89 | nouveau_subdev_destroy(&pmc->base); |
| 85 | } | 90 | } |
| 86 | 91 | ||
| @@ -102,6 +107,23 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 102 | 107 | ||
| 103 | pmc->intr_map = intr_map; | 108 | pmc->intr_map = intr_map; |
| 104 | 109 | ||
| 110 | switch (device->pdev->device & 0x0ff0) { | ||
| 111 | case 0x00f0: /* BR02? */ | ||
| 112 | case 0x02e0: /* BR02? */ | ||
| 113 | pmc->use_msi = false; | ||
| 114 | break; | ||
| 115 | default: | ||
| 116 | pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", true); | ||
| 117 | if (pmc->use_msi) { | ||
| 118 | pmc->use_msi = pci_enable_msi(device->pdev) == 0; | ||
| 119 | if (pmc->use_msi) { | ||
| 120 | nv_info(pmc, "MSI interrupts enabled\n"); | ||
| 121 | nv_wr08(device, 0x00088068, 0xff); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | break; | ||
| 125 | } | ||
| 126 | |||
| 105 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, | 127 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, |
| 106 | IRQF_SHARED, "nouveau", pmc); | 128 | IRQF_SHARED, "nouveau", pmc); |
| 107 | if (ret < 0) | 129 | if (ret < 0) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index 0d57b4d3e001..06710419a59b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | |||
| @@ -35,6 +35,7 @@ nv98_mc_intr[] = { | |||
| 35 | { 0x00001000, NVDEV_ENGINE_GR }, | 35 | { 0x00001000, NVDEV_ENGINE_GR }, |
| 36 | { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ | 36 | { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ |
| 37 | { 0x00008000, NVDEV_ENGINE_BSP }, | 37 | { 0x00008000, NVDEV_ENGINE_BSP }, |
| 38 | { 0x00020000, NVDEV_ENGINE_VP }, | ||
| 38 | { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ | 39 | { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ |
| 39 | { 0x00100000, NVDEV_SUBDEV_TIMER }, | 40 | { 0x00100000, NVDEV_SUBDEV_TIMER }, |
| 40 | { 0x00200000, NVDEV_SUBDEV_GPIO }, | 41 | { 0x00200000, NVDEV_SUBDEV_GPIO }, |
| @@ -42,7 +43,7 @@ nv98_mc_intr[] = { | |||
| 42 | { 0x04000000, NVDEV_ENGINE_DISP }, | 43 | { 0x04000000, NVDEV_ENGINE_DISP }, |
| 43 | { 0x10000000, NVDEV_SUBDEV_BUS }, | 44 | { 0x10000000, NVDEV_SUBDEV_BUS }, |
| 44 | { 0x80000000, NVDEV_ENGINE_SW }, | 45 | { 0x80000000, NVDEV_ENGINE_SW }, |
| 45 | { 0x0040d101, NVDEV_SUBDEV_FB }, | 46 | { 0x0042d101, NVDEV_SUBDEV_FB }, |
| 46 | {}, | 47 | {}, |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index a00a5a76e2d6..f1de7a9c572b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c | |||
| @@ -95,12 +95,14 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) | |||
| 95 | int duty; | 95 | int duty; |
| 96 | 96 | ||
| 97 | spin_lock_irqsave(&priv->lock, flags); | 97 | spin_lock_irqsave(&priv->lock, flags); |
| 98 | nv_debug(therm, "FAN speed check\n"); | ||
| 98 | if (mode < 0) | 99 | if (mode < 0) |
| 99 | mode = priv->mode; | 100 | mode = priv->mode; |
| 100 | priv->mode = mode; | 101 | priv->mode = mode; |
| 101 | 102 | ||
| 102 | switch (mode) { | 103 | switch (mode) { |
| 103 | case NOUVEAU_THERM_CTRL_MANUAL: | 104 | case NOUVEAU_THERM_CTRL_MANUAL: |
| 105 | ptimer->alarm_cancel(ptimer, &priv->alarm); | ||
| 104 | duty = nouveau_therm_fan_get(therm); | 106 | duty = nouveau_therm_fan_get(therm); |
| 105 | if (duty < 0) | 107 | if (duty < 0) |
| 106 | duty = 100; | 108 | duty = 100; |
| @@ -113,6 +115,7 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) | |||
| 113 | break; | 115 | break; |
| 114 | case NOUVEAU_THERM_CTRL_NONE: | 116 | case NOUVEAU_THERM_CTRL_NONE: |
| 115 | default: | 117 | default: |
| 118 | ptimer->alarm_cancel(ptimer, &priv->alarm); | ||
| 116 | goto done; | 119 | goto done; |
| 117 | } | 120 | } |
| 118 | 121 | ||
| @@ -122,6 +125,8 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) | |||
| 122 | done: | 125 | done: |
| 123 | if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) | 126 | if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) |
| 124 | ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); | 127 | ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); |
| 128 | else if (!list_empty(&priv->alarm.head)) | ||
| 129 | nv_debug(therm, "therm fan alarm list is not empty\n"); | ||
| 125 | spin_unlock_irqrestore(&priv->lock, flags); | 130 | spin_unlock_irqrestore(&priv->lock, flags); |
| 126 | } | 131 | } |
| 127 | 132 | ||
| @@ -267,9 +272,15 @@ _nouveau_therm_init(struct nouveau_object *object) | |||
| 267 | if (ret) | 272 | if (ret) |
| 268 | return ret; | 273 | return ret; |
| 269 | 274 | ||
| 270 | if (priv->suspend >= 0) | 275 | if (priv->suspend >= 0) { |
| 271 | nouveau_therm_fan_mode(therm, priv->mode); | 276 | /* restore the pwm value only when on manual or auto mode */ |
| 272 | priv->sensor.program_alarms(therm); | 277 | if (priv->suspend > 0) |
| 278 | nouveau_therm_fan_set(therm, true, priv->fan->percent); | ||
| 279 | |||
| 280 | nouveau_therm_fan_mode(therm, priv->suspend); | ||
| 281 | } | ||
| 282 | nouveau_therm_sensor_init(therm); | ||
| 283 | nouveau_therm_fan_init(therm); | ||
| 273 | return 0; | 284 | return 0; |
| 274 | } | 285 | } |
| 275 | 286 | ||
| @@ -279,6 +290,8 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend) | |||
| 279 | struct nouveau_therm *therm = (void *)object; | 290 | struct nouveau_therm *therm = (void *)object; |
| 280 | struct nouveau_therm_priv *priv = (void *)therm; | 291 | struct nouveau_therm_priv *priv = (void *)therm; |
| 281 | 292 | ||
| 293 | nouveau_therm_fan_fini(therm, suspend); | ||
| 294 | nouveau_therm_sensor_fini(therm, suspend); | ||
| 282 | if (suspend) { | 295 | if (suspend) { |
| 283 | priv->suspend = priv->mode; | 296 | priv->suspend = priv->mode; |
| 284 | priv->mode = NOUVEAU_THERM_CTRL_NONE; | 297 | priv->mode = NOUVEAU_THERM_CTRL_NONE; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index c728380d3d62..39f47b950ad1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | |||
| @@ -204,6 +204,23 @@ nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) | |||
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | int | 206 | int |
| 207 | nouveau_therm_fan_init(struct nouveau_therm *therm) | ||
| 208 | { | ||
| 209 | return 0; | ||
| 210 | } | ||
| 211 | |||
| 212 | int | ||
| 213 | nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend) | ||
| 214 | { | ||
| 215 | struct nouveau_therm_priv *priv = (void *)therm; | ||
| 216 | struct nouveau_timer *ptimer = nouveau_timer(therm); | ||
| 217 | |||
| 218 | if (suspend) | ||
| 219 | ptimer->alarm_cancel(ptimer, &priv->fan->alarm); | ||
| 220 | return 0; | ||
| 221 | } | ||
| 222 | |||
| 223 | int | ||
| 207 | nouveau_therm_fan_ctor(struct nouveau_therm *therm) | 224 | nouveau_therm_fan_ctor(struct nouveau_therm *therm) |
| 208 | { | 225 | { |
| 209 | struct nouveau_therm_priv *priv = (void *)therm; | 226 | struct nouveau_therm_priv *priv = (void *)therm; |
| @@ -234,6 +251,9 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm) | |||
| 234 | 251 | ||
| 235 | nv_info(therm, "FAN control: %s\n", priv->fan->type); | 252 | nv_info(therm, "FAN control: %s\n", priv->fan->type); |
| 236 | 253 | ||
| 254 | /* read the current speed, it is useful when resuming */ | ||
| 255 | priv->fan->percent = nouveau_therm_fan_get(therm); | ||
| 256 | |||
| 237 | /* attempt to detect a tachometer connection */ | 257 | /* attempt to detect a tachometer connection */ |
| 238 | ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); | 258 | ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); |
| 239 | if (ret) | 259 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index 15ca64e481f1..dd38529262fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | |||
| @@ -113,6 +113,8 @@ void nouveau_therm_ic_ctor(struct nouveau_therm *therm); | |||
| 113 | int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); | 113 | int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); |
| 114 | 114 | ||
| 115 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); | 115 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); |
| 116 | int nouveau_therm_fan_init(struct nouveau_therm *therm); | ||
| 117 | int nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend); | ||
| 116 | int nouveau_therm_fan_get(struct nouveau_therm *therm); | 118 | int nouveau_therm_fan_get(struct nouveau_therm *therm); |
| 117 | int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); | 119 | int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); |
| 118 | int nouveau_therm_fan_user_get(struct nouveau_therm *therm); | 120 | int nouveau_therm_fan_user_get(struct nouveau_therm *therm); |
| @@ -122,6 +124,8 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm); | |||
| 122 | 124 | ||
| 123 | int nouveau_therm_preinit(struct nouveau_therm *); | 125 | int nouveau_therm_preinit(struct nouveau_therm *); |
| 124 | 126 | ||
| 127 | int nouveau_therm_sensor_init(struct nouveau_therm *therm); | ||
| 128 | int nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend); | ||
| 125 | void nouveau_therm_sensor_preinit(struct nouveau_therm *); | 129 | void nouveau_therm_sensor_preinit(struct nouveau_therm *); |
| 126 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, | 130 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, |
| 127 | enum nouveau_therm_thrs thrs, | 131 | enum nouveau_therm_thrs thrs, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index dde746c78c8a..b80a33011b93 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | |||
| @@ -180,6 +180,8 @@ alarm_timer_callback(struct nouveau_alarm *alarm) | |||
| 180 | 180 | ||
| 181 | spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); | 181 | spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); |
| 182 | 182 | ||
| 183 | nv_debug(therm, "polling the internal temperature\n"); | ||
| 184 | |||
| 183 | nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, | 185 | nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, |
| 184 | NOUVEAU_THERM_THRS_FANBOOST); | 186 | NOUVEAU_THERM_THRS_FANBOOST); |
| 185 | 187 | ||
| @@ -216,6 +218,25 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) | |||
| 216 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); | 218 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); |
| 217 | } | 219 | } |
| 218 | 220 | ||
| 221 | int | ||
| 222 | nouveau_therm_sensor_init(struct nouveau_therm *therm) | ||
| 223 | { | ||
| 224 | struct nouveau_therm_priv *priv = (void *)therm; | ||
| 225 | priv->sensor.program_alarms(therm); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | int | ||
| 230 | nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend) | ||
| 231 | { | ||
| 232 | struct nouveau_therm_priv *priv = (void *)therm; | ||
| 233 | struct nouveau_timer *ptimer = nouveau_timer(therm); | ||
| 234 | |||
| 235 | if (suspend) | ||
| 236 | ptimer->alarm_cancel(ptimer, &priv->sensor.therm_poll_alarm); | ||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 219 | void | 240 | void |
| 220 | nouveau_therm_sensor_preinit(struct nouveau_therm *therm) | 241 | nouveau_therm_sensor_preinit(struct nouveau_therm *therm) |
| 221 | { | 242 | { |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c index 5d417cc9949b..cf8a0e0f8ee3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c | |||
| @@ -85,3 +85,10 @@ nouveau_timer_alarm(void *obj, u32 nsec, struct nouveau_alarm *alarm) | |||
| 85 | struct nouveau_timer *ptimer = nouveau_timer(obj); | 85 | struct nouveau_timer *ptimer = nouveau_timer(obj); |
| 86 | ptimer->alarm(ptimer, nsec, alarm); | 86 | ptimer->alarm(ptimer, nsec, alarm); |
| 87 | } | 87 | } |
| 88 | |||
| 89 | void | ||
| 90 | nouveau_timer_alarm_cancel(void *obj, struct nouveau_alarm *alarm) | ||
| 91 | { | ||
| 92 | struct nouveau_timer *ptimer = nouveau_timer(obj); | ||
| 93 | ptimer->alarm_cancel(ptimer, alarm); | ||
| 94 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 9469b8275675..57711ecb566c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | |||
| @@ -36,6 +36,7 @@ struct nv04_timer_priv { | |||
| 36 | struct nouveau_timer base; | 36 | struct nouveau_timer base; |
| 37 | struct list_head alarms; | 37 | struct list_head alarms; |
| 38 | spinlock_t lock; | 38 | spinlock_t lock; |
| 39 | u64 suspend_time; | ||
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 41 | static u64 | 42 | static u64 |
| @@ -113,6 +114,25 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time, | |||
| 113 | } | 114 | } |
| 114 | 115 | ||
| 115 | static void | 116 | static void |
| 117 | nv04_timer_alarm_cancel(struct nouveau_timer *ptimer, | ||
| 118 | struct nouveau_alarm *alarm) | ||
| 119 | { | ||
| 120 | struct nv04_timer_priv *priv = (void *)ptimer; | ||
| 121 | unsigned long flags; | ||
| 122 | |||
| 123 | /* avoid deleting an entry while the alarm intr is running */ | ||
| 124 | spin_lock_irqsave(&priv->lock, flags); | ||
| 125 | |||
| 126 | /* delete the alarm from the list */ | ||
| 127 | list_del(&alarm->head); | ||
| 128 | |||
| 129 | /* reset the head so as list_empty returns 1 */ | ||
| 130 | INIT_LIST_HEAD(&alarm->head); | ||
| 131 | |||
| 132 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void | ||
| 116 | nv04_timer_intr(struct nouveau_subdev *subdev) | 136 | nv04_timer_intr(struct nouveau_subdev *subdev) |
| 117 | { | 137 | { |
| 118 | struct nv04_timer_priv *priv = (void *)subdev; | 138 | struct nv04_timer_priv *priv = (void *)subdev; |
| @@ -146,6 +166,8 @@ nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
| 146 | priv->base.base.intr = nv04_timer_intr; | 166 | priv->base.base.intr = nv04_timer_intr; |
| 147 | priv->base.read = nv04_timer_read; | 167 | priv->base.read = nv04_timer_read; |
| 148 | priv->base.alarm = nv04_timer_alarm; | 168 | priv->base.alarm = nv04_timer_alarm; |
| 169 | priv->base.alarm_cancel = nv04_timer_alarm_cancel; | ||
| 170 | priv->suspend_time = 0; | ||
| 149 | 171 | ||
| 150 | INIT_LIST_HEAD(&priv->alarms); | 172 | INIT_LIST_HEAD(&priv->alarms); |
| 151 | spin_lock_init(&priv->lock); | 173 | spin_lock_init(&priv->lock); |
| @@ -164,7 +186,7 @@ nv04_timer_init(struct nouveau_object *object) | |||
| 164 | { | 186 | { |
| 165 | struct nouveau_device *device = nv_device(object); | 187 | struct nouveau_device *device = nv_device(object); |
| 166 | struct nv04_timer_priv *priv = (void *)object; | 188 | struct nv04_timer_priv *priv = (void *)object; |
| 167 | u32 m = 1, f, n, d; | 189 | u32 m = 1, f, n, d, lo, hi; |
| 168 | int ret; | 190 | int ret; |
| 169 | 191 | ||
| 170 | ret = nouveau_timer_init(&priv->base); | 192 | ret = nouveau_timer_init(&priv->base); |
| @@ -221,16 +243,25 @@ nv04_timer_init(struct nouveau_object *object) | |||
| 221 | d >>= 1; | 243 | d >>= 1; |
| 222 | } | 244 | } |
| 223 | 245 | ||
| 246 | /* restore the time before suspend */ | ||
| 247 | lo = priv->suspend_time; | ||
| 248 | hi = (priv->suspend_time >> 32); | ||
| 249 | |||
| 224 | nv_debug(priv, "input frequency : %dHz\n", f); | 250 | nv_debug(priv, "input frequency : %dHz\n", f); |
| 225 | nv_debug(priv, "input multiplier: %d\n", m); | 251 | nv_debug(priv, "input multiplier: %d\n", m); |
| 226 | nv_debug(priv, "numerator : 0x%08x\n", n); | 252 | nv_debug(priv, "numerator : 0x%08x\n", n); |
| 227 | nv_debug(priv, "denominator : 0x%08x\n", d); | 253 | nv_debug(priv, "denominator : 0x%08x\n", d); |
| 228 | nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); | 254 | nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); |
| 255 | nv_debug(priv, "time low : 0x%08x\n", lo); | ||
| 256 | nv_debug(priv, "time high : 0x%08x\n", hi); | ||
| 229 | 257 | ||
| 230 | nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); | 258 | nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); |
| 231 | nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); | 259 | nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); |
| 232 | nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); | 260 | nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); |
| 233 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); | 261 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); |
| 262 | nv_wr32(priv, NV04_PTIMER_TIME_1, hi); | ||
| 263 | nv_wr32(priv, NV04_PTIMER_TIME_0, lo); | ||
| 264 | |||
| 234 | return 0; | 265 | return 0; |
| 235 | } | 266 | } |
| 236 | 267 | ||
| @@ -238,6 +269,8 @@ static int | |||
| 238 | nv04_timer_fini(struct nouveau_object *object, bool suspend) | 269 | nv04_timer_fini(struct nouveau_object *object, bool suspend) |
| 239 | { | 270 | { |
| 240 | struct nv04_timer_priv *priv = (void *)object; | 271 | struct nv04_timer_priv *priv = (void *)object; |
| 272 | if (suspend) | ||
| 273 | priv->suspend_time = nv04_timer_read(&priv->base); | ||
| 241 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); | 274 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); |
| 242 | return nouveau_timer_fini(&priv->base, suspend); | 275 | return nouveau_timer_fini(&priv->base, suspend); |
| 243 | } | 276 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 07dd1fe2d6fb..a4aa81a2173b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | |||
| @@ -174,6 +174,7 @@ nv50_vm_flush(struct nouveau_vm *vm) | |||
| 174 | case NVDEV_ENGINE_GR : vme = 0x00; break; | 174 | case NVDEV_ENGINE_GR : vme = 0x00; break; |
| 175 | case NVDEV_ENGINE_VP : vme = 0x01; break; | 175 | case NVDEV_ENGINE_VP : vme = 0x01; break; |
| 176 | case NVDEV_SUBDEV_BAR : vme = 0x06; break; | 176 | case NVDEV_SUBDEV_BAR : vme = 0x06; break; |
| 177 | case NVDEV_ENGINE_PPP : | ||
| 177 | case NVDEV_ENGINE_MPEG : vme = 0x08; break; | 178 | case NVDEV_ENGINE_MPEG : vme = 0x08; break; |
| 178 | case NVDEV_ENGINE_BSP : vme = 0x09; break; | 179 | case NVDEV_ENGINE_BSP : vme = 0x09; break; |
| 179 | case NVDEV_ENGINE_CRYPT: vme = 0x0a; break; | 180 | case NVDEV_ENGINE_CRYPT: vme = 0x0a; break; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 77ffded68837..d2712e6e5d31 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
| @@ -107,6 +107,11 @@ nouveau_framebuffer_init(struct drm_device *dev, | |||
| 107 | return -EINVAL; | 107 | return -EINVAL; |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) { | ||
| 111 | NV_ERROR(drm, "framebuffer requires contiguous bo\n"); | ||
| 112 | return -EINVAL; | ||
| 113 | } | ||
| 114 | |||
| 110 | if (nv_device(drm->device)->chipset == 0x50) | 115 | if (nv_device(drm->device)->chipset == 0x50) |
| 111 | nv_fb->r_format |= (tile_flags << 8); | 116 | nv_fb->r_format |= (tile_flags << 8); |
| 112 | 117 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 487242fb3fdc..f32b71238c03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -579,18 +579,31 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, | |||
| 579 | return 0; | 579 | return 0; |
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | static inline void | ||
| 583 | u_free(void *addr) | ||
| 584 | { | ||
| 585 | if (!is_vmalloc_addr(addr)) | ||
| 586 | kfree(addr); | ||
| 587 | else | ||
| 588 | vfree(addr); | ||
| 589 | } | ||
| 590 | |||
| 582 | static inline void * | 591 | static inline void * |
| 583 | u_memcpya(uint64_t user, unsigned nmemb, unsigned size) | 592 | u_memcpya(uint64_t user, unsigned nmemb, unsigned size) |
| 584 | { | 593 | { |
| 585 | void *mem; | 594 | void *mem; |
| 586 | void __user *userptr = (void __force __user *)(uintptr_t)user; | 595 | void __user *userptr = (void __force __user *)(uintptr_t)user; |
| 587 | 596 | ||
| 588 | mem = kmalloc(nmemb * size, GFP_KERNEL); | 597 | size *= nmemb; |
| 598 | |||
| 599 | mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); | ||
| 600 | if (!mem) | ||
| 601 | mem = vmalloc(size); | ||
| 589 | if (!mem) | 602 | if (!mem) |
| 590 | return ERR_PTR(-ENOMEM); | 603 | return ERR_PTR(-ENOMEM); |
| 591 | 604 | ||
| 592 | if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) { | 605 | if (DRM_COPY_FROM_USER(mem, userptr, size)) { |
| 593 | kfree(mem); | 606 | u_free(mem); |
| 594 | return ERR_PTR(-EFAULT); | 607 | return ERR_PTR(-EFAULT); |
| 595 | } | 608 | } |
| 596 | 609 | ||
| @@ -676,7 +689,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
| 676 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); | 689 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); |
| 677 | } | 690 | } |
| 678 | 691 | ||
| 679 | kfree(reloc); | 692 | u_free(reloc); |
| 680 | return ret; | 693 | return ret; |
| 681 | } | 694 | } |
| 682 | 695 | ||
| @@ -738,7 +751,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
| 738 | 751 | ||
| 739 | bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); | 752 | bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); |
| 740 | if (IS_ERR(bo)) { | 753 | if (IS_ERR(bo)) { |
| 741 | kfree(push); | 754 | u_free(push); |
| 742 | return nouveau_abi16_put(abi16, PTR_ERR(bo)); | 755 | return nouveau_abi16_put(abi16, PTR_ERR(bo)); |
| 743 | } | 756 | } |
| 744 | 757 | ||
| @@ -849,8 +862,8 @@ out: | |||
| 849 | nouveau_fence_unref(&fence); | 862 | nouveau_fence_unref(&fence); |
| 850 | 863 | ||
| 851 | out_prevalid: | 864 | out_prevalid: |
| 852 | kfree(bo); | 865 | u_free(bo); |
| 853 | kfree(push); | 866 | u_free(push); |
| 854 | 867 | ||
| 855 | out_next: | 868 | out_next: |
| 856 | if (chan->dma.ib_max) { | 869 | if (chan->dma.ib_max) { |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 9d2092a5ed38..f8e66c08b11a 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
| @@ -1583,7 +1583,7 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
| 1583 | load = 340; | 1583 | load = 340; |
| 1584 | 1584 | ||
| 1585 | ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load)); | 1585 | ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load)); |
| 1586 | if (ret || load != 7) | 1586 | if (ret || !load) |
| 1587 | return connector_status_disconnected; | 1587 | return connector_status_disconnected; |
| 1588 | 1588 | ||
| 1589 | return connector_status_connected; | 1589 | return connector_status_connected; |
