diff options
| author | Ben Skeggs <bskeggs@redhat.com> | 2010-09-26 21:18:14 -0400 |
|---|---|---|
| committer | Ben Skeggs <bskeggs@redhat.com> | 2010-10-04 19:57:54 -0400 |
| commit | fade7ad56d929e168ead0f75e591468afa2fe97c (patch) | |
| tree | 486c401dd30e8f3b5d35e97972822e81994cd446 /drivers/gpu/drm/nouveau | |
| parent | aee582de806c7008756df23aa444c8e7d58004a9 (diff) | |
drm/nva3: split pm backend out from nv50
This will end up quite different, it makes sense for it to be completely
separate.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau')
| -rw-r--r-- | drivers/gpu/drm/nouveau/Makefile | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_pm.h | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_pm.c | 56 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nva3_pm.c | 95 |
5 files changed, 137 insertions, 42 deletions
diff --git a/drivers/gpu/drm/nouveau/Makefile b/drivers/gpu/drm/nouveau/Makefile index bdbde726778e..23fa82d667d6 100644 --- a/drivers/gpu/drm/nouveau/Makefile +++ b/drivers/gpu/drm/nouveau/Makefile | |||
| @@ -10,7 +10,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
| 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ | 10 | nouveau_hw.o nouveau_calc.o nouveau_bios.o nouveau_i2c.o \ |
| 11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ | 11 | nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ |
| 12 | nouveau_dp.o nouveau_ramht.o \ | 12 | nouveau_dp.o nouveau_ramht.o \ |
| 13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o \ | 13 | nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ |
| 14 | nv04_timer.o \ | 14 | nv04_timer.o \ |
| 15 | nv04_mc.o nv40_mc.o nv50_mc.o \ | 15 | nv04_mc.o nv40_mc.o nv50_mc.o \ |
| 16 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ | 16 | nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \ |
| @@ -25,7 +25,7 @@ nouveau-y := nouveau_drv.o nouveau_state.o nouveau_channel.o nouveau_mem.o \ | |||
| 25 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ | 25 | nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ |
| 26 | nv10_gpio.o nv50_gpio.o \ | 26 | nv10_gpio.o nv50_gpio.o \ |
| 27 | nv50_calc.o \ | 27 | nv50_calc.o \ |
| 28 | nv04_pm.o nv50_pm.o nouveau_temp.o | 28 | nv04_pm.o nv50_pm.o nva3_pm.o |
| 29 | 29 | ||
| 30 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o | 30 | nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o |
| 31 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o | 31 | nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.h b/drivers/gpu/drm/nouveau/nouveau_pm.h index babe64ac33c0..4a9838ddacec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.h +++ b/drivers/gpu/drm/nouveau/nouveau_pm.h | |||
| @@ -58,6 +58,12 @@ void *nv50_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | |||
| 58 | u32 id, int khz); | 58 | u32 id, int khz); |
| 59 | void nv50_pm_clock_set(struct drm_device *, void *); | 59 | void nv50_pm_clock_set(struct drm_device *, void *); |
| 60 | 60 | ||
| 61 | /* nva3_pm.c */ | ||
| 62 | int nva3_pm_clock_get(struct drm_device *, u32 id); | ||
| 63 | void *nva3_pm_clock_pre(struct drm_device *, struct nouveau_pm_level *, | ||
| 64 | u32 id, int khz); | ||
| 65 | void nva3_pm_clock_set(struct drm_device *, void *); | ||
| 66 | |||
| 61 | /* nouveau_temp.c */ | 67 | /* nouveau_temp.c */ |
| 62 | void nouveau_temp_init(struct drm_device *dev); | 68 | void nouveau_temp_init(struct drm_device *dev); |
| 63 | void nouveau_temp_fini(struct drm_device *dev); | 69 | void nouveau_temp_fini(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index affcfc2fae19..75bce914e7b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
| @@ -375,9 +375,21 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) | |||
| 375 | engine->gpio.get = nv50_gpio_get; | 375 | engine->gpio.get = nv50_gpio_get; |
| 376 | engine->gpio.set = nv50_gpio_set; | 376 | engine->gpio.set = nv50_gpio_set; |
| 377 | engine->gpio.irq_enable = nv50_gpio_irq_enable; | 377 | engine->gpio.irq_enable = nv50_gpio_irq_enable; |
| 378 | engine->pm.clock_get = nv50_pm_clock_get; | 378 | switch (dev_priv->chipset) { |
| 379 | engine->pm.clock_pre = nv50_pm_clock_pre; | 379 | case 0xa3: |
| 380 | engine->pm.clock_set = nv50_pm_clock_set; | 380 | case 0xa5: |
| 381 | case 0xa8: | ||
| 382 | case 0xaf: | ||
| 383 | engine->pm.clock_get = nva3_pm_clock_get; | ||
| 384 | engine->pm.clock_pre = nva3_pm_clock_pre; | ||
| 385 | engine->pm.clock_set = nva3_pm_clock_set; | ||
| 386 | break; | ||
| 387 | default: | ||
| 388 | engine->pm.clock_get = nv50_pm_clock_get; | ||
| 389 | engine->pm.clock_pre = nv50_pm_clock_pre; | ||
| 390 | engine->pm.clock_set = nv50_pm_clock_set; | ||
| 391 | break; | ||
| 392 | } | ||
| 381 | engine->pm.voltage_get = nouveau_voltage_gpio_get; | 393 | engine->pm.voltage_get = nouveau_voltage_gpio_get; |
| 382 | engine->pm.voltage_set = nouveau_voltage_gpio_set; | 394 | engine->pm.voltage_set = nouveau_voltage_gpio_set; |
| 383 | if (dev_priv->chipset >= 0x84) | 395 | if (dev_priv->chipset >= 0x84) |
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c index 2a9fabdf1b75..7dbb305d7e63 100644 --- a/drivers/gpu/drm/nouveau/nv50_pm.c +++ b/drivers/gpu/drm/nouveau/nv50_pm.c | |||
| @@ -27,12 +27,6 @@ | |||
| 27 | #include "nouveau_bios.h" | 27 | #include "nouveau_bios.h" |
| 28 | #include "nouveau_pm.h" | 28 | #include "nouveau_pm.h" |
| 29 | 29 | ||
| 30 | /*XXX: boards using limits 0x40 need fixing, the register layout | ||
| 31 | * is correct here, but, there's some other funny magic | ||
| 32 | * that modifies things, so it's not likely we'll set/read | ||
| 33 | * the correct timings yet.. working on it... | ||
| 34 | */ | ||
| 35 | |||
| 36 | struct nv50_pm_state { | 30 | struct nv50_pm_state { |
| 37 | struct nouveau_pm_level *perflvl; | 31 | struct nouveau_pm_level *perflvl; |
| 38 | struct pll_lims pll; | 32 | struct pll_lims pll; |
| @@ -51,21 +45,13 @@ nv50_pm_clock_get(struct drm_device *dev, u32 id) | |||
| 51 | if (ret) | 45 | if (ret) |
| 52 | return ret; | 46 | return ret; |
| 53 | 47 | ||
| 54 | if (pll.vco2.maxfreq) { | 48 | reg0 = nv_rd32(dev, pll.reg + 0); |
| 55 | reg0 = nv_rd32(dev, pll.reg + 0); | 49 | reg1 = nv_rd32(dev, pll.reg + 4); |
| 56 | reg1 = nv_rd32(dev, pll.reg + 4); | 50 | P = (reg0 & 0x00070000) >> 16; |
| 57 | P = (reg0 & 0x00070000) >> 16; | 51 | N = (reg1 & 0x0000ff00) >> 8; |
| 58 | N = (reg1 & 0x0000ff00) >> 8; | 52 | M = (reg1 & 0x000000ff); |
| 59 | M = (reg1 & 0x000000ff); | ||
| 60 | |||
| 61 | return ((pll.refclk * N / M) >> P); | ||
| 62 | } | ||
| 63 | 53 | ||
| 64 | reg0 = nv_rd32(dev, pll.reg + 4); | 54 | return ((pll.refclk * N / M) >> P); |
| 65 | P = (reg0 & 0x003f0000) >> 16; | ||
| 66 | N = (reg0 & 0x0000ff00) >> 8; | ||
| 67 | M = (reg0 & 0x000000ff); | ||
| 68 | return pll.refclk * N / M / P; | ||
| 69 | } | 55 | } |
| 70 | 56 | ||
| 71 | void * | 57 | void * |
| @@ -125,23 +111,19 @@ nv50_pm_clock_set(struct drm_device *dev, void *pre_state) | |||
| 125 | nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); | 111 | nouveau_bios_run_init_table(dev, perflvl->memscript, NULL); |
| 126 | } | 112 | } |
| 127 | 113 | ||
| 128 | if (state->pll.vco2.maxfreq) { | 114 | if (state->type == PLL_MEMORY) { |
| 129 | if (state->type == PLL_MEMORY) { | 115 | nv_wr32(dev, 0x100210, 0); |
| 130 | nv_wr32(dev, 0x100210, 0); | 116 | nv_wr32(dev, 0x1002dc, 1); |
| 131 | nv_wr32(dev, 0x1002dc, 1); | 117 | } |
| 132 | } | 118 | |
| 133 | 119 | tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; | |
| 134 | tmp = nv_rd32(dev, reg + 0) & 0xfff8ffff; | 120 | tmp |= 0x80000000 | (P << 16); |
| 135 | tmp |= 0x80000000 | (P << 16); | 121 | nv_wr32(dev, reg + 0, tmp); |
| 136 | nv_wr32(dev, reg + 0, tmp); | 122 | nv_wr32(dev, reg + 4, (N << 8) | M); |
| 137 | nv_wr32(dev, reg + 4, (N << 8) | M); | 123 | |
| 138 | 124 | if (state->type == PLL_MEMORY) { | |
| 139 | if (state->type == PLL_MEMORY) { | 125 | nv_wr32(dev, 0x1002dc, 0); |
| 140 | nv_wr32(dev, 0x1002dc, 0); | 126 | nv_wr32(dev, 0x100210, 0x80000000); |
| 141 | nv_wr32(dev, 0x100210, 0x80000000); | ||
| 142 | } | ||
| 143 | } else { | ||
| 144 | nv_wr32(dev, reg + 4, (P << 16) | (N << 8) | M); | ||
| 145 | } | 127 | } |
| 146 | 128 | ||
| 147 | kfree(state); | 129 | kfree(state); |
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c new file mode 100644 index 000000000000..dbbafed36406 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nva3_pm.c | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2010 Red Hat Inc. | ||
| 3 | * | ||
| 4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
| 5 | * copy of this software and associated documentation files (the "Software"), | ||
| 6 | * to deal in the Software without restriction, including without limitation | ||
| 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
| 8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
| 9 | * Software is furnished to do so, subject to the following conditions: | ||
| 10 | * | ||
| 11 | * The above copyright notice and this permission notice shall be included in | ||
| 12 | * all copies or substantial portions of the Software. | ||
| 13 | * | ||
| 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
| 17 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | ||
| 18 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | ||
| 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
| 20 | * OTHER DEALINGS IN THE SOFTWARE. | ||
| 21 | * | ||
| 22 | * Authors: Ben Skeggs | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include "drmP.h" | ||
| 26 | #include "nouveau_drv.h" | ||
| 27 | #include "nouveau_bios.h" | ||
| 28 | #include "nouveau_pm.h" | ||
| 29 | |||
| 30 | /*XXX: boards using limits 0x40 need fixing, the register layout | ||
| 31 | * is correct here, but, there's some other funny magic | ||
| 32 | * that modifies things, so it's not likely we'll set/read | ||
| 33 | * the correct timings yet.. working on it... | ||
| 34 | */ | ||
| 35 | |||
| 36 | struct nva3_pm_state { | ||
| 37 | struct pll_lims pll; | ||
| 38 | int N, M, P; | ||
| 39 | }; | ||
| 40 | |||
| 41 | int | ||
| 42 | nva3_pm_clock_get(struct drm_device *dev, u32 id) | ||
| 43 | { | ||
| 44 | struct pll_lims pll; | ||
| 45 | int P, N, M, ret; | ||
| 46 | u32 reg; | ||
| 47 | |||
| 48 | ret = get_pll_limits(dev, id, &pll); | ||
| 49 | if (ret) | ||
| 50 | return ret; | ||
| 51 | |||
| 52 | reg = nv_rd32(dev, pll.reg + 4); | ||
| 53 | P = (reg & 0x003f0000) >> 16; | ||
| 54 | N = (reg & 0x0000ff00) >> 8; | ||
| 55 | M = (reg & 0x000000ff); | ||
| 56 | return pll.refclk * N / M / P; | ||
| 57 | } | ||
| 58 | |||
| 59 | void * | ||
| 60 | nva3_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl, | ||
| 61 | u32 id, int khz) | ||
| 62 | { | ||
| 63 | struct nva3_pm_state *state; | ||
| 64 | int dummy, ret; | ||
| 65 | |||
| 66 | state = kzalloc(sizeof(*state), GFP_KERNEL); | ||
| 67 | if (!state) | ||
| 68 | return ERR_PTR(-ENOMEM); | ||
| 69 | |||
| 70 | ret = get_pll_limits(dev, id, &state->pll); | ||
| 71 | if (ret < 0) { | ||
| 72 | kfree(state); | ||
| 73 | return (ret == -ENOENT) ? NULL : ERR_PTR(ret); | ||
| 74 | } | ||
| 75 | |||
| 76 | ret = nv50_calc_pll2(dev, &state->pll, khz, &state->N, &dummy, | ||
| 77 | &state->M, &state->P); | ||
| 78 | if (ret < 0) { | ||
| 79 | kfree(state); | ||
| 80 | return ERR_PTR(ret); | ||
| 81 | } | ||
| 82 | |||
| 83 | return state; | ||
| 84 | } | ||
| 85 | |||
| 86 | void | ||
| 87 | nva3_pm_clock_set(struct drm_device *dev, void *pre_state) | ||
| 88 | { | ||
| 89 | struct nva3_pm_state *state = pre_state; | ||
| 90 | u32 reg = state->pll.reg; | ||
| 91 | |||
| 92 | nv_wr32(dev, reg + 4, (state->P << 16) | (state->N << 8) | state->M); | ||
| 93 | kfree(state); | ||
| 94 | } | ||
| 95 | |||
