Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-next

Nothing terribly exciting in here probably:
- reworked thermal stuff from mupuf/I, has a chance of possibly working
well enough when we get to being able to reclock..
- driver will report mmio access faults on chipsets where it's supported
- will now sleep waiting on fences on nv84+ rather than polling
- some cleanup of the internal fencing, looking towards sli/dmabuf sync
- initial support for anx9805 dp/tmds encoder
- nv50+ display fixes related to the above, and also might fix a few
other issues
- nicer error reporting (will log process names with channel errors)
- various other random fixes

* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (87 commits)
nouveau: ACPI support depends on X86 and X86_PLATFORM_DEVICES
drm/nouveau/i2c: add support for ddc/aux, and dp link training on anx9805
drm/nv50: initial kms support for off-chip TMDS/DP encoders
drm/nv50-/disp: initial supervisor support for off-chip encoders
drm/nv50-/disp: initial work towards supporting external encoders
drm/nv50-/kms: remove unnecessary wait-for-completion points
drm/nv50-/disp: move DP link training to core and train from supervisor
drm/nv50-/disp: handle supervisor tasks from workqueue
drm/nouveau/i2c: create proper chipset-specific class implementations
drm/nv50-/disp: 0x0000 is a valid udisp config value
drm/nv50/devinit: reverse the logic for running encoder init scripts
drm/nouveau/bios: store a type/mask hash in parsed dcb data
drm/nouveau/i2c: extend type to 16-bits, add lookup-by-type function
drm/nouveau/i2c: aux channels not necessarily on nvio
drm/nouveau/i2c: fix a bit of a thinko in nv_wri2cr helper functions
drm/nouveau/bios: parse external transmitter type if off-chip
drm/nouveau: store i2c port pointer directly in nouveau_encoder
drm/nouveau/i2c: handle i2c/aux mux outside of port lookup function
drm/nv50/graph: avoid touching 400724, it doesn't exist
drm/nouveau: Fix DPMS 1 on G4 Snowball, from snow white to coal black.
...

+7017 -2753
+81
Documentation/thermal/nouveau_thermal
··· 1 + Kernel driver nouveau 2 + =================== 3 + 4 + Supported chips: 5 + * NV43+ 6 + 7 + Authors: Martin Peres (mupuf) <martin.peres@labri.fr> 8 + 9 + Description 10 + --------- 11 + 12 + This driver allows to read the GPU core temperature, drive the GPU fan and 13 + set temperature alarms. 14 + 15 + Currently, due to the absence of in-kernel API to access HWMON drivers, Nouveau 16 + cannot access any of the i2c external monitoring chips it may find. If you 17 + have one of those, temperature and/or fan management through Nouveau's HWMON 18 + interface is likely not to work. This document may then not cover your situation 19 + entirely. 20 + 21 + Temperature management 22 + -------------------- 23 + 24 + Temperature is exposed under as a read-only HWMON attribute temp1_input. 25 + 26 + In order to protect the GPU from overheating, Nouveau supports 4 configurable 27 + temperature thresholds: 28 + 29 + * Fan_boost: Fan speed is set to 100% when reaching this temperature; 30 + * Downclock: The GPU will be downclocked to reduce its power dissipation; 31 + * Critical: The GPU is put on hold to further lower power dissipation; 32 + * Shutdown: Shut the computer down to protect your GPU. 33 + 34 + WARNING: Some of these thresholds may not be used by Nouveau depending 35 + on your chipset. 36 + 37 + The default value for these thresholds comes from the GPU's vbios. These 38 + thresholds can be configured thanks to the following HWMON attributes: 39 + 40 + * Fan_boost: temp1_auto_point1_temp and temp1_auto_point1_temp_hyst; 41 + * Downclock: temp1_max and temp1_max_hyst; 42 + * Critical: temp1_crit and temp1_crit_hyst; 43 + * Shutdown: temp1_emergency and temp1_emergency_hyst. 44 + 45 + NOTE: Remember that the values are stored as milli degrees Celcius. Don't forget 46 + to multiply! 47 + 48 + Fan management 49 + ------------ 50 + 51 + Not all cards have a drivable fan. If you do, then the following HWMON 52 + attributes should be available: 53 + 54 + * pwm1_enable: Current fan management mode (NONE, MANUAL or AUTO); 55 + * pwm1: Current PWM value (power percentage); 56 + * pwm1_min: The minimum PWM speed allowed; 57 + * pwm1_max: The maximum PWM speed allowed (bypassed when hitting Fan_boost); 58 + 59 + You may also have the following attribute: 60 + 61 + * fan1_input: Speed in RPM of your fan. 62 + 63 + Your fan can be driven in different modes: 64 + 65 + * 0: The fan is left untouched; 66 + * 1: The fan can be driven in manual (use pwm1 to change the speed); 67 + * 2; The fan is driven automatically depending on the temperature. 68 + 69 + NOTE: Be sure to use the manual mode if you want to drive the fan speed manually 70 + 71 + NOTE2: Not all fan management modes may be supported on all chipsets. We are 72 + working on it. 73 + 74 + Bug reports 75 + --------- 76 + 77 + Thermal management on Nouveau is new and may not work on all cards. If you have 78 + inquiries, please ping mupuf on IRC (#nouveau, freenode). 79 + 80 + Bug reports should be filled on Freedesktop's bug tracker. Please follow 81 + http://nouveau.freedesktop.org/wiki/Bugs
+3 -2
drivers/gpu/drm/nouveau/Kconfig
··· 11 11 select FRAMEBUFFER_CONSOLE if !EXPERT 12 12 select FB_BACKLIGHT if DRM_NOUVEAU_BACKLIGHT 13 13 select ACPI_VIDEO if ACPI && X86 && BACKLIGHT_CLASS_DEVICE && VIDEO_OUTPUT_CONTROL && INPUT 14 - select ACPI_WMI if ACPI 15 - select MXM_WMI if ACPI 14 + select X86_PLATFORM_DEVICES if ACPI && X86 15 + select ACPI_WMI if ACPI && X86 16 + select MXM_WMI if ACPI && X86 16 17 select POWER_SUPPLY 17 18 help 18 19 Choose this option for open-source nVidia support.
+26 -2
drivers/gpu/drm/nouveau/Makefile
··· 11 11 nouveau-y += core/core/engctx.o 12 12 nouveau-y += core/core/engine.o 13 13 nouveau-y += core/core/enum.o 14 + nouveau-y += core/core/event.o 14 15 nouveau-y += core/core/falcon.o 15 16 nouveau-y += core/core/gpuobj.o 16 17 nouveau-y += core/core/handle.o ··· 41 40 nouveau-y += core/subdev/bios/perf.o 42 41 nouveau-y += core/subdev/bios/pll.o 43 42 nouveau-y += core/subdev/bios/therm.o 43 + nouveau-y += core/subdev/bios/xpio.o 44 + nouveau-y += core/subdev/bus/nv04.o 45 + nouveau-y += core/subdev/bus/nv31.o 46 + nouveau-y += core/subdev/bus/nv50.o 47 + nouveau-y += core/subdev/bus/nvc0.o 44 48 nouveau-y += core/subdev/clock/nv04.o 45 49 nouveau-y += core/subdev/clock/nv40.o 46 50 nouveau-y += core/subdev/clock/nv50.o ··· 91 85 nouveau-y += core/subdev/gpio/nv10.o 92 86 nouveau-y += core/subdev/gpio/nv50.o 93 87 nouveau-y += core/subdev/gpio/nvd0.o 88 + nouveau-y += core/subdev/gpio/nve0.o 94 89 nouveau-y += core/subdev/i2c/base.o 90 + nouveau-y += core/subdev/i2c/anx9805.o 95 91 nouveau-y += core/subdev/i2c/aux.o 96 92 nouveau-y += core/subdev/i2c/bit.o 93 + nouveau-y += core/subdev/i2c/nv04.o 94 + nouveau-y += core/subdev/i2c/nv4e.o 95 + nouveau-y += core/subdev/i2c/nv50.o 96 + nouveau-y += core/subdev/i2c/nv94.o 97 + nouveau-y += core/subdev/i2c/nvd0.o 97 98 nouveau-y += core/subdev/ibus/nvc0.o 98 99 nouveau-y += core/subdev/ibus/nve0.o 99 100 nouveau-y += core/subdev/instmem/base.o ··· 119 106 nouveau-y += core/subdev/mxm/nv50.o 120 107 nouveau-y += core/subdev/therm/base.o 121 108 nouveau-y += core/subdev/therm/fan.o 109 + nouveau-y += core/subdev/therm/fannil.o 110 + nouveau-y += core/subdev/therm/fanpwm.o 111 + nouveau-y += core/subdev/therm/fantog.o 122 112 nouveau-y += core/subdev/therm/ic.o 113 + nouveau-y += core/subdev/therm/temp.o 123 114 nouveau-y += core/subdev/therm/nv40.o 124 115 nouveau-y += core/subdev/therm/nv50.o 125 - nouveau-y += core/subdev/therm/temp.o 116 + nouveau-y += core/subdev/therm/nva3.o 117 + nouveau-y += core/subdev/therm/nvd0.o 126 118 nouveau-y += core/subdev/timer/base.o 127 119 nouveau-y += core/subdev/timer/nv04.o 128 120 nouveau-y += core/subdev/vm/base.o ··· 150 132 nouveau-y += core/engine/copy/nve0.o 151 133 nouveau-y += core/engine/crypt/nv84.o 152 134 nouveau-y += core/engine/crypt/nv98.o 135 + nouveau-y += core/engine/disp/base.o 153 136 nouveau-y += core/engine/disp/nv04.o 154 137 nouveau-y += core/engine/disp/nv50.o 155 138 nouveau-y += core/engine/disp/nv84.o ··· 160 141 nouveau-y += core/engine/disp/nvd0.o 161 142 nouveau-y += core/engine/disp/nve0.o 162 143 nouveau-y += core/engine/disp/dacnv50.o 144 + nouveau-y += core/engine/disp/dport.o 163 145 nouveau-y += core/engine/disp/hdanva3.o 164 146 nouveau-y += core/engine/disp/hdanvd0.o 165 147 nouveau-y += core/engine/disp/hdminv84.o 166 148 nouveau-y += core/engine/disp/hdminva3.o 167 149 nouveau-y += core/engine/disp/hdminvd0.o 150 + nouveau-y += core/engine/disp/piornv50.o 168 151 nouveau-y += core/engine/disp/sornv50.o 169 152 nouveau-y += core/engine/disp/sornv94.o 170 153 nouveau-y += core/engine/disp/sornvd0.o ··· 215 194 nouveau-y += nouveau_irq.o nouveau_vga.o nouveau_agp.o 216 195 nouveau-y += nouveau_ttm.o nouveau_sgdma.o nouveau_bo.o nouveau_gem.o 217 196 nouveau-y += nouveau_prime.o nouveau_abi16.o 218 - nouveau-y += nv04_fence.o nv10_fence.o nv50_fence.o nv84_fence.o nvc0_fence.o 197 + nouveau-y += nv04_fence.o nv10_fence.o nv17_fence.o 198 + nouveau-y += nv50_fence.o nv84_fence.o nvc0_fence.o 219 199 220 200 # drm/kms 221 201 nouveau-y += nouveau_bios.o nouveau_fbcon.o nouveau_display.o ··· 238 216 239 217 # other random bits 240 218 nouveau-$(CONFIG_COMPAT) += nouveau_ioc32.o 219 + ifdef CONFIG_X86 241 220 nouveau-$(CONFIG_ACPI) += nouveau_acpi.o 221 + endif 242 222 nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o 243 223 244 224 obj-$(CONFIG_DRM_NOUVEAU)+= nouveau.o
+10
drivers/gpu/drm/nouveau/core/core/client.c
··· 99 99 nv_debug(client, "%s completed with %d\n", name[suspend], ret); 100 100 return ret; 101 101 } 102 + 103 + const char * 104 + nouveau_client_name(void *obj) 105 + { 106 + const char *client_name = "unknown"; 107 + struct nouveau_client *client = nouveau_client(obj); 108 + if (client) 109 + client_name = client->name; 110 + return client_name; 111 + }
+6 -5
drivers/gpu/drm/nouveau/core/core/enum.c
··· 40 40 return NULL; 41 41 } 42 42 43 - void 43 + const struct nouveau_enum * 44 44 nouveau_enum_print(const struct nouveau_enum *en, u32 value) 45 45 { 46 46 en = nouveau_enum_find(en, value); 47 47 if (en) 48 - printk("%s", en->name); 48 + pr_cont("%s", en->name); 49 49 else 50 - printk("(unknown enum 0x%08x)", value); 50 + pr_cont("(unknown enum 0x%08x)", value); 51 + return en; 51 52 } 52 53 53 54 void ··· 56 55 { 57 56 while (bf->name) { 58 57 if (value & bf->mask) { 59 - printk(" %s", bf->name); 58 + pr_cont(" %s", bf->name); 60 59 value &= ~bf->mask; 61 60 } 62 61 ··· 64 63 } 65 64 66 65 if (value) 67 - printk(" (unknown bits 0x%08x)", value); 66 + pr_cont(" (unknown bits 0x%08x)", value); 68 67 }
+106
drivers/gpu/drm/nouveau/core/core/event.c
··· 1 + /* 2 + * Copyright 2013 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 + 23 + #include <core/os.h> 24 + #include <core/event.h> 25 + 26 + static void 27 + nouveau_event_put_locked(struct nouveau_event *event, int index, 28 + struct nouveau_eventh *handler) 29 + { 30 + if (!--event->index[index].refs) 31 + event->disable(event, index); 32 + list_del(&handler->head); 33 + } 34 + 35 + void 36 + nouveau_event_put(struct nouveau_event *event, int index, 37 + struct nouveau_eventh *handler) 38 + { 39 + unsigned long flags; 40 + 41 + spin_lock_irqsave(&event->lock, flags); 42 + if (index < event->index_nr) 43 + nouveau_event_put_locked(event, index, handler); 44 + spin_unlock_irqrestore(&event->lock, flags); 45 + } 46 + 47 + void 48 + nouveau_event_get(struct nouveau_event *event, int index, 49 + struct nouveau_eventh *handler) 50 + { 51 + unsigned long flags; 52 + 53 + spin_lock_irqsave(&event->lock, flags); 54 + if (index < event->index_nr) { 55 + list_add(&handler->head, &event->index[index].list); 56 + if (!event->index[index].refs++) 57 + event->enable(event, index); 58 + } 59 + spin_unlock_irqrestore(&event->lock, flags); 60 + } 61 + 62 + void 63 + nouveau_event_trigger(struct nouveau_event *event, int index) 64 + { 65 + struct nouveau_eventh *handler, *temp; 66 + unsigned long flags; 67 + 68 + if (index >= event->index_nr) 69 + return; 70 + 71 + spin_lock_irqsave(&event->lock, flags); 72 + list_for_each_entry_safe(handler, temp, &event->index[index].list, head) { 73 + if (handler->func(handler, index) == NVKM_EVENT_DROP) { 74 + nouveau_event_put_locked(event, index, handler); 75 + } 76 + } 77 + spin_unlock_irqrestore(&event->lock, flags); 78 + } 79 + 80 + void 81 + nouveau_event_destroy(struct nouveau_event **pevent) 82 + { 83 + struct nouveau_event *event = *pevent; 84 + if (event) { 85 + kfree(event); 86 + *pevent = NULL; 87 + } 88 + } 89 + 90 + int 91 + nouveau_event_create(int index_nr, struct nouveau_event **pevent) 92 + { 93 + struct nouveau_event *event; 94 + int i; 95 + 96 + event = *pevent = kzalloc(sizeof(*event) + index_nr * 97 + sizeof(event->index[0]), GFP_KERNEL); 98 + if (!event) 99 + return -ENOMEM; 100 + 101 + spin_lock_init(&event->lock); 102 + for (i = 0; i < index_nr; i++) 103 + INIT_LIST_HEAD(&event->index[i].list); 104 + event->index_nr = index_nr; 105 + return 0; 106 + }
+4 -2
drivers/gpu/drm/nouveau/core/engine/copy/nva3.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/falcon.h> 26 27 #include <core/class.h> 27 28 #include <core/enum.h> ··· 101 100 if (stat & 0x00000040) { 102 101 nv_error(falcon, "DISPATCH_ERROR ["); 103 102 nouveau_enum_print(nva3_copy_isr_error_name, ssta); 104 - printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", 105 - chid, inst << 12, subc, mthd, data); 103 + pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n", 104 + chid, inst << 12, nouveau_client_name(engctx), subc, 105 + mthd, data); 106 106 nv_wo32(falcon, 0x004, 0x00000040); 107 107 stat &= ~0x00000040; 108 108 }
+5 -3
drivers/gpu/drm/nouveau/core/engine/crypt/nv84.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/os.h> 26 27 #include <core/enum.h> 27 28 #include <core/class.h> ··· 127 126 chid = pfifo->chid(pfifo, engctx); 128 127 129 128 if (stat) { 130 - nv_error(priv, ""); 129 + nv_error(priv, "%s", ""); 131 130 nouveau_bitfield_print(nv84_crypt_intr_mask, stat); 132 - printk(" ch %d [0x%010llx] mthd 0x%04x data 0x%08x\n", 133 - chid, (u64)inst << 12, mthd, data); 131 + pr_cont(" ch %d [0x%010llx %s] mthd 0x%04x data 0x%08x\n", 132 + chid, (u64)inst << 12, nouveau_client_name(engctx), 133 + mthd, data); 134 134 } 135 135 136 136 nv_wr32(priv, 0x102130, stat);
+4 -2
drivers/gpu/drm/nouveau/core/engine/crypt/nv98.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/os.h> 26 27 #include <core/enum.h> 27 28 #include <core/class.h> ··· 103 102 if (stat & 0x00000040) { 104 103 nv_error(priv, "DISPATCH_ERROR ["); 105 104 nouveau_enum_print(nv98_crypt_isr_error_name, ssta); 106 - printk("] ch %d [0x%010llx] subc %d mthd 0x%04x data 0x%08x\n", 107 - chid, (u64)inst << 12, subc, mthd, data); 105 + pr_cont("] ch %d [0x%010llx %s] subc %d mthd 0x%04x data 0x%08x\n", 106 + chid, (u64)inst << 12, nouveau_client_name(engctx), 107 + subc, mthd, data); 108 108 nv_wr32(priv, 0x087004, 0x00000040); 109 109 stat &= ~0x00000040; 110 110 }
+52
drivers/gpu/drm/nouveau/core/engine/disp/base.c
··· 1 + /* 2 + * Copyright 2013 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 <engine/disp.h> 26 + 27 + void 28 + _nouveau_disp_dtor(struct nouveau_object *object) 29 + { 30 + struct nouveau_disp *disp = (void *)object; 31 + nouveau_event_destroy(&disp->vblank); 32 + nouveau_engine_destroy(&disp->base); 33 + } 34 + 35 + int 36 + nouveau_disp_create_(struct nouveau_object *parent, 37 + struct nouveau_object *engine, 38 + struct nouveau_oclass *oclass, int heads, 39 + const char *intname, const char *extname, 40 + int length, void **pobject) 41 + { 42 + struct nouveau_disp *disp; 43 + int ret; 44 + 45 + ret = nouveau_engine_create_(parent, engine, oclass, true, 46 + intname, extname, length, pobject); 47 + disp = *pobject; 48 + if (ret) 49 + return ret; 50 + 51 + return nouveau_event_create(heads, &disp->vblank); 52 + }
+346
drivers/gpu/drm/nouveau/core/engine/disp/dport.c
··· 1 + /* 2 + * Copyright 2013 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 <subdev/bios.h> 26 + #include <subdev/bios/dcb.h> 27 + #include <subdev/bios/dp.h> 28 + #include <subdev/bios/init.h> 29 + #include <subdev/i2c.h> 30 + 31 + #include <engine/disp.h> 32 + 33 + #include "dport.h" 34 + 35 + #define DBG(fmt, args...) nv_debug(dp->disp, "DP:%04x:%04x: " fmt, \ 36 + dp->outp->hasht, dp->outp->hashm, ##args) 37 + #define ERR(fmt, args...) nv_error(dp->disp, "DP:%04x:%04x: " fmt, \ 38 + dp->outp->hasht, dp->outp->hashm, ##args) 39 + 40 + /****************************************************************************** 41 + * link training 42 + *****************************************************************************/ 43 + struct dp_state { 44 + const struct nouveau_dp_func *func; 45 + struct nouveau_disp *disp; 46 + struct dcb_output *outp; 47 + struct nvbios_dpout info; 48 + u8 version; 49 + struct nouveau_i2c_port *aux; 50 + int head; 51 + u8 dpcd[4]; 52 + int link_nr; 53 + u32 link_bw; 54 + u8 stat[6]; 55 + u8 conf[4]; 56 + }; 57 + 58 + static int 59 + dp_set_link_config(struct dp_state *dp) 60 + { 61 + struct nouveau_disp *disp = dp->disp; 62 + struct nouveau_bios *bios = nouveau_bios(disp); 63 + struct nvbios_init init = { 64 + .subdev = nv_subdev(dp->disp), 65 + .bios = bios, 66 + .offset = 0x0000, 67 + .outp = dp->outp, 68 + .crtc = dp->head, 69 + .execute = 1, 70 + }; 71 + u32 lnkcmp; 72 + u8 sink[2]; 73 + 74 + DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); 75 + 76 + /* set desired link configuration on the sink */ 77 + sink[0] = dp->link_bw / 27000; 78 + sink[1] = dp->link_nr; 79 + if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) 80 + sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; 81 + 82 + nv_wraux(dp->aux, DPCD_LC00, sink, 2); 83 + 84 + /* set desired link configuration on the source */ 85 + if ((lnkcmp = dp->info.lnkcmp)) { 86 + if (dp->version < 0x30) { 87 + while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp)) 88 + lnkcmp += 4; 89 + init.offset = nv_ro16(bios, lnkcmp + 2); 90 + } else { 91 + while ((dp->link_bw / 27000) < nv_ro08(bios, lnkcmp)) 92 + lnkcmp += 3; 93 + init.offset = nv_ro16(bios, lnkcmp + 1); 94 + } 95 + 96 + nvbios_exec(&init); 97 + } 98 + 99 + return dp->func->lnk_ctl(dp->disp, dp->outp, dp->head, 100 + dp->link_nr, dp->link_bw / 27000, 101 + dp->dpcd[DPCD_RC02] & 102 + DPCD_RC02_ENHANCED_FRAME_CAP); 103 + } 104 + 105 + static void 106 + dp_set_training_pattern(struct dp_state *dp, u8 pattern) 107 + { 108 + u8 sink_tp; 109 + 110 + DBG("training pattern %d\n", pattern); 111 + dp->func->pattern(dp->disp, dp->outp, dp->head, pattern); 112 + 113 + nv_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1); 114 + sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; 115 + sink_tp |= pattern; 116 + nv_wraux(dp->aux, DPCD_LC02, &sink_tp, 1); 117 + } 118 + 119 + static int 120 + dp_link_train_commit(struct dp_state *dp) 121 + { 122 + int i; 123 + 124 + for (i = 0; i < dp->link_nr; i++) { 125 + u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; 126 + u8 lpre = (lane & 0x0c) >> 2; 127 + u8 lvsw = (lane & 0x03) >> 0; 128 + 129 + dp->conf[i] = (lpre << 3) | lvsw; 130 + if (lvsw == 3) 131 + dp->conf[i] |= DPCD_LC03_MAX_SWING_REACHED; 132 + if (lpre == 3) 133 + dp->conf[i] |= DPCD_LC03_MAX_PRE_EMPHASIS_REACHED; 134 + 135 + DBG("config lane %d %02x\n", i, dp->conf[i]); 136 + dp->func->drv_ctl(dp->disp, dp->outp, dp->head, i, lvsw, lpre); 137 + } 138 + 139 + return nv_wraux(dp->aux, DPCD_LC03(0), dp->conf, 4); 140 + } 141 + 142 + static int 143 + dp_link_train_update(struct dp_state *dp, u32 delay) 144 + { 145 + int ret; 146 + 147 + udelay(delay); 148 + 149 + ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6); 150 + if (ret) 151 + return ret; 152 + 153 + DBG("status %*ph\n", 6, dp->stat); 154 + return 0; 155 + } 156 + 157 + static int 158 + dp_link_train_cr(struct dp_state *dp) 159 + { 160 + bool cr_done = false, abort = false; 161 + int voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET; 162 + int tries = 0, i; 163 + 164 + dp_set_training_pattern(dp, 1); 165 + 166 + do { 167 + if (dp_link_train_commit(dp) || 168 + dp_link_train_update(dp, 100)) 169 + break; 170 + 171 + cr_done = true; 172 + for (i = 0; i < dp->link_nr; i++) { 173 + u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; 174 + if (!(lane & DPCD_LS02_LANE0_CR_DONE)) { 175 + cr_done = false; 176 + if (dp->conf[i] & DPCD_LC03_MAX_SWING_REACHED) 177 + abort = true; 178 + break; 179 + } 180 + } 181 + 182 + if ((dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET) != voltage) { 183 + voltage = dp->conf[0] & DPCD_LC03_VOLTAGE_SWING_SET; 184 + tries = 0; 185 + } 186 + } while (!cr_done && !abort && ++tries < 5); 187 + 188 + return cr_done ? 0 : -1; 189 + } 190 + 191 + static int 192 + dp_link_train_eq(struct dp_state *dp) 193 + { 194 + bool eq_done, cr_done = true; 195 + int tries = 0, i; 196 + 197 + dp_set_training_pattern(dp, 2); 198 + 199 + do { 200 + if (dp_link_train_update(dp, 400)) 201 + break; 202 + 203 + eq_done = !!(dp->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); 204 + for (i = 0; i < dp->link_nr && eq_done; i++) { 205 + u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; 206 + if (!(lane & DPCD_LS02_LANE0_CR_DONE)) 207 + cr_done = false; 208 + if (!(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || 209 + !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) 210 + eq_done = false; 211 + } 212 + 213 + if (dp_link_train_commit(dp)) 214 + break; 215 + } while (!eq_done && cr_done && ++tries <= 5); 216 + 217 + return eq_done ? 0 : -1; 218 + } 219 + 220 + static void 221 + dp_link_train_init(struct dp_state *dp, bool spread) 222 + { 223 + struct nvbios_init init = { 224 + .subdev = nv_subdev(dp->disp), 225 + .bios = nouveau_bios(dp->disp), 226 + .outp = dp->outp, 227 + .crtc = dp->head, 228 + .execute = 1, 229 + }; 230 + 231 + /* set desired spread */ 232 + if (spread) 233 + init.offset = dp->info.script[2]; 234 + else 235 + init.offset = dp->info.script[3]; 236 + nvbios_exec(&init); 237 + 238 + /* pre-train script */ 239 + init.offset = dp->info.script[0]; 240 + nvbios_exec(&init); 241 + } 242 + 243 + static void 244 + dp_link_train_fini(struct dp_state *dp) 245 + { 246 + struct nvbios_init init = { 247 + .subdev = nv_subdev(dp->disp), 248 + .bios = nouveau_bios(dp->disp), 249 + .outp = dp->outp, 250 + .crtc = dp->head, 251 + .execute = 1, 252 + }; 253 + 254 + /* post-train script */ 255 + init.offset = dp->info.script[1], 256 + nvbios_exec(&init); 257 + } 258 + 259 + int 260 + nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func, 261 + struct dcb_output *outp, int head, u32 datarate) 262 + { 263 + struct nouveau_bios *bios = nouveau_bios(disp); 264 + struct nouveau_i2c *i2c = nouveau_i2c(disp); 265 + struct dp_state _dp = { 266 + .disp = disp, 267 + .func = func, 268 + .outp = outp, 269 + .head = head, 270 + }, *dp = &_dp; 271 + const u32 bw_list[] = { 270000, 162000, 0 }; 272 + const u32 *link_bw = bw_list; 273 + u8 hdr, cnt, len; 274 + u32 data; 275 + int ret; 276 + 277 + /* find the bios displayport data relevant to this output */ 278 + data = nvbios_dpout_match(bios, outp->hasht, outp->hashm, &dp->version, 279 + &hdr, &cnt, &len, &dp->info); 280 + if (!data) { 281 + ERR("bios data not found\n"); 282 + return -EINVAL; 283 + } 284 + 285 + /* acquire the aux channel and fetch some info about the display */ 286 + if (outp->location) 287 + dp->aux = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); 288 + else 289 + dp->aux = i2c->find(i2c, NV_I2C_TYPE_DCBI2C(outp->i2c_index)); 290 + if (!dp->aux) { 291 + ERR("no aux channel?!\n"); 292 + return -ENODEV; 293 + } 294 + 295 + ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd)); 296 + if (ret) { 297 + ERR("failed to read DPCD\n"); 298 + return ret; 299 + } 300 + 301 + /* adjust required bandwidth for 8B/10B coding overhead */ 302 + datarate = (datarate / 8) * 10; 303 + 304 + /* enable down-spreading and execute pre-train script from vbios */ 305 + dp_link_train_init(dp, dp->dpcd[3] & 0x01); 306 + 307 + /* start off at highest link rate supported by encoder and display */ 308 + while (*link_bw > (dp->dpcd[1] * 27000)) 309 + link_bw++; 310 + 311 + while (link_bw[0]) { 312 + /* find minimum required lane count at this link rate */ 313 + dp->link_nr = dp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT; 314 + while ((dp->link_nr >> 1) * link_bw[0] > datarate) 315 + dp->link_nr >>= 1; 316 + 317 + /* drop link rate to minimum with this lane count */ 318 + while ((link_bw[1] * dp->link_nr) > datarate) 319 + link_bw++; 320 + dp->link_bw = link_bw[0]; 321 + 322 + /* program selected link configuration */ 323 + ret = dp_set_link_config(dp); 324 + if (ret == 0) { 325 + /* attempt to train the link at this configuration */ 326 + memset(dp->stat, 0x00, sizeof(dp->stat)); 327 + if (!dp_link_train_cr(dp) && 328 + !dp_link_train_eq(dp)) 329 + break; 330 + } else 331 + if (ret >= 1) { 332 + /* dp_set_link_config() handled training */ 333 + break; 334 + } 335 + 336 + /* retry at lower rate */ 337 + link_bw++; 338 + } 339 + 340 + /* finish link training */ 341 + dp_set_training_pattern(dp, 0); 342 + 343 + /* execute post-train script from vbios */ 344 + dp_link_train_fini(dp); 345 + return true; 346 + }
+78
drivers/gpu/drm/nouveau/core/engine/disp/dport.h
··· 1 + #ifndef __NVKM_DISP_DPORT_H__ 2 + #define __NVKM_DISP_DPORT_H__ 3 + 4 + /* DPCD Receiver Capabilities */ 5 + #define DPCD_RC00 0x00000 6 + #define DPCD_RC00_DPCD_REV 0xff 7 + #define DPCD_RC01 0x00001 8 + #define DPCD_RC01_MAX_LINK_RATE 0xff 9 + #define DPCD_RC02 0x00002 10 + #define DPCD_RC02_ENHANCED_FRAME_CAP 0x80 11 + #define DPCD_RC02_MAX_LANE_COUNT 0x1f 12 + #define DPCD_RC03 0x00003 13 + #define DPCD_RC03_MAX_DOWNSPREAD 0x01 14 + 15 + /* DPCD Link Configuration */ 16 + #define DPCD_LC00 0x00100 17 + #define DPCD_LC00_LINK_BW_SET 0xff 18 + #define DPCD_LC01 0x00101 19 + #define DPCD_LC01_ENHANCED_FRAME_EN 0x80 20 + #define DPCD_LC01_LANE_COUNT_SET 0x1f 21 + #define DPCD_LC02 0x00102 22 + #define DPCD_LC02_TRAINING_PATTERN_SET 0x03 23 + #define DPCD_LC03(l) ((l) + 0x00103) 24 + #define DPCD_LC03_MAX_PRE_EMPHASIS_REACHED 0x20 25 + #define DPCD_LC03_PRE_EMPHASIS_SET 0x18 26 + #define DPCD_LC03_MAX_SWING_REACHED 0x04 27 + #define DPCD_LC03_VOLTAGE_SWING_SET 0x03 28 + 29 + /* DPCD Link/Sink Status */ 30 + #define DPCD_LS02 0x00202 31 + #define DPCD_LS02_LANE1_SYMBOL_LOCKED 0x40 32 + #define DPCD_LS02_LANE1_CHANNEL_EQ_DONE 0x20 33 + #define DPCD_LS02_LANE1_CR_DONE 0x10 34 + #define DPCD_LS02_LANE0_SYMBOL_LOCKED 0x04 35 + #define DPCD_LS02_LANE0_CHANNEL_EQ_DONE 0x02 36 + #define DPCD_LS02_LANE0_CR_DONE 0x01 37 + #define DPCD_LS03 0x00203 38 + #define DPCD_LS03_LANE3_SYMBOL_LOCKED 0x40 39 + #define DPCD_LS03_LANE3_CHANNEL_EQ_DONE 0x20 40 + #define DPCD_LS03_LANE3_CR_DONE 0x10 41 + #define DPCD_LS03_LANE2_SYMBOL_LOCKED 0x04 42 + #define DPCD_LS03_LANE2_CHANNEL_EQ_DONE 0x02 43 + #define DPCD_LS03_LANE2_CR_DONE 0x01 44 + #define DPCD_LS04 0x00204 45 + #define DPCD_LS04_LINK_STATUS_UPDATED 0x80 46 + #define DPCD_LS04_DOWNSTREAM_PORT_STATUS_CHANGED 0x40 47 + #define DPCD_LS04_INTERLANE_ALIGN_DONE 0x01 48 + #define DPCD_LS06 0x00206 49 + #define DPCD_LS06_LANE1_PRE_EMPHASIS 0xc0 50 + #define DPCD_LS06_LANE1_VOLTAGE_SWING 0x30 51 + #define DPCD_LS06_LANE0_PRE_EMPHASIS 0x0c 52 + #define DPCD_LS06_LANE0_VOLTAGE_SWING 0x03 53 + #define DPCD_LS07 0x00207 54 + #define DPCD_LS07_LANE3_PRE_EMPHASIS 0xc0 55 + #define DPCD_LS07_LANE3_VOLTAGE_SWING 0x30 56 + #define DPCD_LS07_LANE2_PRE_EMPHASIS 0x0c 57 + #define DPCD_LS07_LANE2_VOLTAGE_SWING 0x03 58 + 59 + struct nouveau_disp; 60 + struct dcb_output; 61 + 62 + struct nouveau_dp_func { 63 + int (*pattern)(struct nouveau_disp *, struct dcb_output *, 64 + int head, int pattern); 65 + int (*lnk_ctl)(struct nouveau_disp *, struct dcb_output *, int head, 66 + int link_nr, int link_bw, bool enh_frame); 67 + int (*drv_ctl)(struct nouveau_disp *, struct dcb_output *, int head, 68 + int lane, int swing, int preem); 69 + }; 70 + 71 + extern const struct nouveau_dp_func nv94_sor_dp_func; 72 + extern const struct nouveau_dp_func nvd0_sor_dp_func; 73 + extern const struct nouveau_dp_func nv50_pior_dp_func; 74 + 75 + int nouveau_dp_train(struct nouveau_disp *, const struct nouveau_dp_func *, 76 + struct dcb_output *, int, u32); 77 + 78 + #endif
+24 -9
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
··· 24 24 25 25 #include <engine/disp.h> 26 26 27 + #include <core/event.h> 28 + #include <core/class.h> 29 + 27 30 struct nv04_disp_priv { 28 31 struct nouveau_disp base; 29 32 }; 30 33 31 34 static struct nouveau_oclass 32 35 nv04_disp_sclass[] = { 36 + { NV04_DISP_CLASS, &nouveau_object_ofuncs }, 33 37 {}, 34 38 }; 35 39 40 + /******************************************************************************* 41 + * Display engine implementation 42 + ******************************************************************************/ 43 + 36 44 static void 37 - nv04_disp_intr_vblank(struct nv04_disp_priv *priv, int crtc) 45 + nv04_disp_vblank_enable(struct nouveau_event *event, int head) 38 46 { 39 - struct nouveau_disp *disp = &priv->base; 40 - if (disp->vblank.notify) 41 - disp->vblank.notify(disp->vblank.data, crtc); 47 + nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001); 48 + } 49 + 50 + static void 51 + nv04_disp_vblank_disable(struct nouveau_event *event, int head) 52 + { 53 + nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000); 42 54 } 43 55 44 56 static void ··· 61 49 u32 crtc1 = nv_rd32(priv, 0x602100); 62 50 63 51 if (crtc0 & 0x00000001) { 64 - nv04_disp_intr_vblank(priv, 0); 52 + nouveau_event_trigger(priv->base.vblank, 0); 65 53 nv_wr32(priv, 0x600100, 0x00000001); 66 54 } 67 55 68 56 if (crtc1 & 0x00000001) { 69 - nv04_disp_intr_vblank(priv, 1); 57 + nouveau_event_trigger(priv->base.vblank, 1); 70 58 nv_wr32(priv, 0x602100, 0x00000001); 71 59 } 72 60 } 73 61 74 62 static int 75 63 nv04_disp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 76 - struct nouveau_oclass *oclass, void *data, u32 size, 77 - struct nouveau_object **pobject) 64 + struct nouveau_oclass *oclass, void *data, u32 size, 65 + struct nouveau_object **pobject) 78 66 { 79 67 struct nv04_disp_priv *priv; 80 68 int ret; 81 69 82 - ret = nouveau_disp_create(parent, engine, oclass, "DISPLAY", 70 + ret = nouveau_disp_create(parent, engine, oclass, 2, "DISPLAY", 83 71 "display", &priv); 84 72 *pobject = nv_object(priv); 85 73 if (ret) ··· 87 75 88 76 nv_engine(priv)->sclass = nv04_disp_sclass; 89 77 nv_subdev(priv)->intr = nv04_disp_intr; 78 + priv->base.vblank->priv = priv; 79 + priv->base.vblank->enable = nv04_disp_vblank_enable; 80 + priv->base.vblank->disable = nv04_disp_vblank_disable; 90 81 return 0; 91 82 } 92 83
+161 -108
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
··· 27 27 #include <core/handle.h> 28 28 #include <core/class.h> 29 29 30 - #include <engine/software.h> 31 30 #include <engine/disp.h> 32 31 33 32 #include <subdev/bios.h> ··· 36 37 #include <subdev/bios/pll.h> 37 38 #include <subdev/timer.h> 38 39 #include <subdev/fb.h> 39 - #include <subdev/bar.h> 40 40 #include <subdev/clock.h> 41 41 42 42 #include "nv50.h" ··· 333 335 struct nv50_disp_dmac *dmac; 334 336 int ret; 335 337 336 - if (size < sizeof(*data) || args->head > 1) 338 + if (size < sizeof(*args) || args->head > 1) 337 339 return -EINVAL; 338 340 339 341 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, ··· 372 374 struct nv50_disp_dmac *dmac; 373 375 int ret; 374 376 375 - if (size < sizeof(*data) || args->head > 1) 377 + if (size < sizeof(*args) || args->head > 1) 376 378 return -EINVAL; 377 379 378 380 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, ··· 541 543 * Base display object 542 544 ******************************************************************************/ 543 545 546 + static void 547 + nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) 548 + { 549 + nv_mask(event->priv, 0x61002c, (1 << head), (1 << head)); 550 + } 551 + 552 + static void 553 + nv50_disp_base_vblank_disable(struct nouveau_event *event, int head) 554 + { 555 + nv_mask(event->priv, 0x61002c, (1 << head), (0 << head)); 556 + } 557 + 544 558 static int 545 559 nv50_disp_base_ctor(struct nouveau_object *parent, 546 560 struct nouveau_object *engine, ··· 569 559 if (ret) 570 560 return ret; 571 561 562 + priv->base.vblank->priv = priv; 563 + priv->base.vblank->enable = nv50_disp_base_vblank_enable; 564 + priv->base.vblank->disable = nv50_disp_base_vblank_disable; 572 565 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht); 573 566 } 574 567 ··· 626 613 nv_wr32(priv, 0x6101e0 + (i * 0x04), tmp); 627 614 } 628 615 629 - /* ... EXT caps */ 616 + /* ... PIOR caps */ 630 617 for (i = 0; i < 3; i++) { 631 618 tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); 632 619 nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); ··· 678 665 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 679 666 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 680 667 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 668 + { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 669 + { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 670 + { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, 681 671 {}, 682 672 }; 683 673 ··· 772 756 } 773 757 } 774 758 775 - static void 776 - nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) 777 - { 778 - struct nouveau_bar *bar = nouveau_bar(priv); 779 - struct nouveau_disp *disp = &priv->base; 780 - struct nouveau_software_chan *chan, *temp; 781 - unsigned long flags; 782 - 783 - spin_lock_irqsave(&disp->vblank.lock, flags); 784 - list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { 785 - if (chan->vblank.crtc != crtc) 786 - continue; 787 - 788 - if (nv_device(priv)->chipset >= 0xc0) { 789 - nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); 790 - bar->flush(bar); 791 - nv_wr32(priv, 0x06000c, 792 - upper_32_bits(chan->vblank.offset)); 793 - nv_wr32(priv, 0x060010, 794 - lower_32_bits(chan->vblank.offset)); 795 - nv_wr32(priv, 0x060014, chan->vblank.value); 796 - } else { 797 - nv_wr32(priv, 0x001704, chan->vblank.channel); 798 - nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); 799 - bar->flush(bar); 800 - if (nv_device(priv)->chipset == 0x50) { 801 - nv_wr32(priv, 0x001570, chan->vblank.offset); 802 - nv_wr32(priv, 0x001574, chan->vblank.value); 803 - } else { 804 - nv_wr32(priv, 0x060010, chan->vblank.offset); 805 - nv_wr32(priv, 0x060014, chan->vblank.value); 806 - } 807 - } 808 - 809 - list_del(&chan->vblank.head); 810 - if (disp->vblank.put) 811 - disp->vblank.put(disp->vblank.data, crtc); 812 - } 813 - spin_unlock_irqrestore(&disp->vblank.lock, flags); 814 - 815 - if (disp->vblank.notify) 816 - disp->vblank.notify(disp->vblank.data, crtc); 817 - } 818 - 819 759 static u16 820 760 exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, 821 761 struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, ··· 783 811 if (outp < 4) { 784 812 type = DCB_OUTPUT_ANALOG; 785 813 mask = 0; 786 - } else { 787 - outp -= 4; 814 + } else 815 + if (outp < 8) { 788 816 switch (ctrl & 0x00000f00) { 789 817 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; 790 818 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; ··· 796 824 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); 797 825 return 0x0000; 798 826 } 827 + outp -= 4; 828 + } else { 829 + outp = outp - 8; 830 + type = 0x0010; 831 + mask = 0; 832 + switch (ctrl & 0x00000f00) { 833 + case 0x00000000: type |= priv->pior.type[outp]; break; 834 + default: 835 + nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl); 836 + return 0x0000; 837 + } 799 838 } 800 839 801 840 mask = 0x00c0 & (mask << 6); ··· 816 833 data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); 817 834 if (!data) 818 835 return 0x0000; 836 + 837 + /* off-chip encoders require matching the exact encoder type */ 838 + if (dcb->location != 0) 839 + type |= dcb->extdev << 8; 819 840 820 841 return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); 821 842 } ··· 835 848 u32 ctrl = 0x00000000; 836 849 int i; 837 850 851 + /* DAC */ 838 852 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) 839 853 ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); 840 854 855 + /* SOR */ 841 856 if (!(ctrl & (1 << head))) { 842 857 if (nv_device(priv)->chipset < 0x90 || 843 858 nv_device(priv)->chipset == 0x92 || ··· 852 863 ctrl = nv_rd32(priv, 0x610798 + (i * 8)); 853 864 i += 4; 854 865 } 866 + } 867 + 868 + /* PIOR */ 869 + if (!(ctrl & (1 << head))) { 870 + for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) 871 + ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); 872 + i += 8; 855 873 } 856 874 857 875 if (!(ctrl & (1 << head))) ··· 890 894 struct nvbios_outp info1; 891 895 struct nvbios_ocfg info2; 892 896 u8 ver, hdr, cnt, len; 893 - u16 data, conf; 894 897 u32 ctrl = 0x00000000; 898 + u32 data, conf = ~0; 895 899 int i; 896 900 901 + /* DAC */ 897 902 for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) 898 903 ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); 899 904 905 + /* SOR */ 900 906 if (!(ctrl & (1 << head))) { 901 907 if (nv_device(priv)->chipset < 0x90 || 902 908 nv_device(priv)->chipset == 0x92 || ··· 913 915 } 914 916 } 915 917 918 + /* PIOR */ 919 + if (!(ctrl & (1 << head))) { 920 + for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) 921 + ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); 922 + i += 8; 923 + } 924 + 916 925 if (!(ctrl & (1 << head))) 917 - return 0x0000; 926 + return conf; 918 927 i--; 919 928 920 929 data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); 921 930 if (!data) 922 - return 0x0000; 931 + return conf; 923 932 924 - switch (outp->type) { 925 - case DCB_OUTPUT_TMDS: 933 + if (outp->location == 0) { 934 + switch (outp->type) { 935 + case DCB_OUTPUT_TMDS: 936 + conf = (ctrl & 0x00000f00) >> 8; 937 + if (pclk >= 165000) 938 + conf |= 0x0100; 939 + break; 940 + case DCB_OUTPUT_LVDS: 941 + conf = priv->sor.lvdsconf; 942 + break; 943 + case DCB_OUTPUT_DP: 944 + conf = (ctrl & 0x00000f00) >> 8; 945 + break; 946 + case DCB_OUTPUT_ANALOG: 947 + default: 948 + conf = 0x00ff; 949 + break; 950 + } 951 + } else { 926 952 conf = (ctrl & 0x00000f00) >> 8; 927 - if (pclk >= 165000) 928 - conf |= 0x0100; 929 - break; 930 - case DCB_OUTPUT_LVDS: 931 - conf = priv->sor.lvdsconf; 932 - break; 933 - case DCB_OUTPUT_DP: 934 - conf = (ctrl & 0x00000f00) >> 8; 935 - break; 936 - case DCB_OUTPUT_ANALOG: 937 - default: 938 - conf = 0x00ff; 939 - break; 953 + pclk = pclk / 2; 940 954 } 941 955 942 956 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 943 - if (data) { 957 + if (data && id < 0xff) { 944 958 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 945 959 if (data) { 946 960 struct nvbios_init init = { ··· 964 954 .execute = 1, 965 955 }; 966 956 967 - if (nvbios_exec(&init)) 968 - return 0x0000; 969 - return conf; 957 + nvbios_exec(&init); 970 958 } 971 959 } 972 960 973 - return 0x0000; 961 + return conf; 974 962 } 975 963 976 964 static void ··· 981 973 exec_script(priv, head, 1); 982 974 } 983 975 984 - nv_wr32(priv, 0x610024, 0x00000010); 985 976 nv_wr32(priv, 0x610030, 0x80000000); 986 977 } 987 978 ··· 1095 1088 nv50_disp_intr_unk20(struct nv50_disp_priv *priv, u32 super) 1096 1089 { 1097 1090 struct dcb_output outp; 1098 - u32 addr, mask, data; 1099 1091 int head; 1100 1092 1101 1093 /* finish detaching encoder? */ ··· 1110 1104 struct nouveau_clock *clk = nouveau_clock(priv); 1111 1105 clk->pll_set(clk, PLL_VPLL0 + head, pclk); 1112 1106 } 1113 - 1114 - nv_mask(priv, 0x614200 + head * 0x800, 0x0000000f, 0x00000000); 1115 1107 } 1116 1108 1117 1109 /* (re)attach the relevant OR to the head */ 1118 1110 head = ffs((super & 0x00000180) >> 7) - 1; 1119 1111 if (head >= 0) { 1120 1112 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; 1121 - u32 conf = exec_clkcmp(priv, head, 0, pclk, &outp); 1122 - if (conf) { 1123 - if (outp.type == DCB_OUTPUT_ANALOG) { 1124 - addr = 0x614280 + (ffs(outp.or) - 1) * 0x800; 1125 - mask = 0xffffffff; 1126 - data = 0x00000000; 1127 - } else { 1128 - if (outp.type == DCB_OUTPUT_DP) 1129 - nv50_disp_intr_unk20_dp(priv, &outp, pclk); 1130 - addr = 0x614300 + (ffs(outp.or) - 1) * 0x800; 1131 - mask = 0x00000707; 1132 - data = (conf & 0x0100) ? 0x0101 : 0x0000; 1113 + u32 hval, hreg = 0x614200 + (head * 0x800); 1114 + u32 oval, oreg; 1115 + u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); 1116 + if (conf != ~0) { 1117 + if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { 1118 + u32 soff = (ffs(outp.or) - 1) * 0x08; 1119 + u32 ctrl = nv_rd32(priv, 0x610798 + soff); 1120 + u32 datarate; 1121 + 1122 + switch ((ctrl & 0x000f0000) >> 16) { 1123 + case 6: datarate = pclk * 30 / 8; break; 1124 + case 5: datarate = pclk * 24 / 8; break; 1125 + case 2: 1126 + default: 1127 + datarate = pclk * 18 / 8; 1128 + break; 1129 + } 1130 + 1131 + nouveau_dp_train(&priv->base, priv->sor.dp, 1132 + &outp, head, datarate); 1133 1133 } 1134 1134 1135 - nv_mask(priv, addr, mask, data); 1135 + exec_clkcmp(priv, head, 0, pclk, &outp); 1136 + 1137 + if (!outp.location && outp.type == DCB_OUTPUT_ANALOG) { 1138 + oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800; 1139 + oval = 0x00000000; 1140 + hval = 0x00000000; 1141 + } else 1142 + if (!outp.location) { 1143 + if (outp.type == DCB_OUTPUT_DP) 1144 + nv50_disp_intr_unk20_dp(priv, &outp, pclk); 1145 + oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800; 1146 + oval = (conf & 0x0100) ? 0x0101 : 0x0000; 1147 + hval = 0x00000000; 1148 + } else { 1149 + oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800; 1150 + oval = 0x00000001; 1151 + hval = 0x00000001; 1152 + } 1153 + 1154 + nv_mask(priv, hreg, 0x0000000f, hval); 1155 + nv_mask(priv, oreg, 0x00000707, oval); 1136 1156 } 1137 1157 } 1138 1158 1139 - nv_wr32(priv, 0x610024, 0x00000020); 1140 1159 nv_wr32(priv, 0x610030, 0x80000000); 1141 1160 } 1142 1161 ··· 1194 1163 if (head >= 0) { 1195 1164 struct dcb_output outp; 1196 1165 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; 1197 - if (pclk && exec_clkcmp(priv, head, 1, pclk, &outp)) { 1198 - if (outp.type == DCB_OUTPUT_TMDS) 1166 + if (exec_clkcmp(priv, head, 1, pclk, &outp) != ~0) { 1167 + if (outp.location == 0 && outp.type == DCB_OUTPUT_TMDS) 1199 1168 nv50_disp_intr_unk40_tmds(priv, &outp); 1169 + else 1170 + if (outp.location == 1 && outp.type == DCB_OUTPUT_DP) { 1171 + u32 soff = (ffs(outp.or) - 1) * 0x08; 1172 + u32 ctrl = nv_rd32(priv, 0x610b84 + soff); 1173 + u32 datarate; 1174 + 1175 + switch ((ctrl & 0x000f0000) >> 16) { 1176 + case 6: datarate = pclk * 30 / 8; break; 1177 + case 5: datarate = pclk * 24 / 8; break; 1178 + case 2: 1179 + default: 1180 + datarate = pclk * 18 / 8; 1181 + break; 1182 + } 1183 + 1184 + nouveau_dp_train(&priv->base, priv->pior.dp, 1185 + &outp, head, datarate); 1186 + } 1200 1187 } 1201 1188 } 1202 1189 1203 - nv_wr32(priv, 0x610024, 0x00000040); 1204 1190 nv_wr32(priv, 0x610030, 0x80000000); 1205 1191 } 1206 1192 1207 - static void 1208 - nv50_disp_intr_super(struct nv50_disp_priv *priv, u32 intr1) 1193 + void 1194 + nv50_disp_intr_supervisor(struct work_struct *work) 1209 1195 { 1196 + struct nv50_disp_priv *priv = 1197 + container_of(work, struct nv50_disp_priv, supervisor); 1210 1198 u32 super = nv_rd32(priv, 0x610030); 1211 1199 1212 - nv_debug(priv, "supervisor 0x%08x 0x%08x\n", intr1, super); 1200 + nv_debug(priv, "supervisor 0x%08x 0x%08x\n", priv->super, super); 1213 1201 1214 - if (intr1 & 0x00000010) 1202 + if (priv->super & 0x00000010) 1215 1203 nv50_disp_intr_unk10(priv, super); 1216 - if (intr1 & 0x00000020) 1204 + if (priv->super & 0x00000020) 1217 1205 nv50_disp_intr_unk20(priv, super); 1218 - if (intr1 & 0x00000040) 1206 + if (priv->super & 0x00000040) 1219 1207 nv50_disp_intr_unk40(priv, super); 1220 1208 } 1221 1209 ··· 1251 1201 } 1252 1202 1253 1203 if (intr1 & 0x00000004) { 1254 - nv50_disp_intr_vblank(priv, 0); 1204 + nouveau_event_trigger(priv->base.vblank, 0); 1255 1205 nv_wr32(priv, 0x610024, 0x00000004); 1256 1206 intr1 &= ~0x00000004; 1257 1207 } 1258 1208 1259 1209 if (intr1 & 0x00000008) { 1260 - nv50_disp_intr_vblank(priv, 1); 1210 + nouveau_event_trigger(priv->base.vblank, 1); 1261 1211 nv_wr32(priv, 0x610024, 0x00000008); 1262 1212 intr1 &= ~0x00000008; 1263 1213 } 1264 1214 1265 1215 if (intr1 & 0x00000070) { 1266 - nv50_disp_intr_super(priv, intr1); 1216 + priv->super = (intr1 & 0x00000070); 1217 + schedule_work(&priv->supervisor); 1218 + nv_wr32(priv, 0x610024, priv->super); 1267 1219 intr1 &= ~0x00000070; 1268 1220 } 1269 1221 } ··· 1278 1226 struct nv50_disp_priv *priv; 1279 1227 int ret; 1280 1228 1281 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 1229 + ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", 1282 1230 "display", &priv); 1283 1231 *pobject = nv_object(priv); 1284 1232 if (ret) ··· 1287 1235 nv_engine(priv)->sclass = nv50_disp_base_oclass; 1288 1236 nv_engine(priv)->cclass = &nv50_disp_cclass; 1289 1237 nv_subdev(priv)->intr = nv50_disp_intr; 1238 + INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); 1290 1239 priv->sclass = nv50_disp_sclass; 1291 1240 priv->head.nr = 2; 1292 1241 priv->dac.nr = 3; 1293 1242 priv->sor.nr = 2; 1243 + priv->pior.nr = 3; 1294 1244 priv->dac.power = nv50_dac_power; 1295 1245 priv->dac.sense = nv50_dac_sense; 1296 1246 priv->sor.power = nv50_sor_power; 1297 - 1298 - INIT_LIST_HEAD(&priv->base.vblank.list); 1299 - spin_lock_init(&priv->base.vblank.lock); 1247 + priv->pior.power = nv50_pior_power; 1248 + priv->pior.dp = &nv50_pior_dp_func; 1300 1249 return 0; 1301 1250 } 1302 1251
+21 -16
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
··· 3 3 4 4 #include <core/parent.h> 5 5 #include <core/namedb.h> 6 + #include <core/engctx.h> 6 7 #include <core/ramht.h> 8 + #include <core/event.h> 7 9 8 10 #include <engine/dmaobj.h> 9 11 #include <engine/disp.h> 10 12 11 - struct dcb_output; 13 + #include "dport.h" 12 14 13 15 struct nv50_disp_priv { 14 16 struct nouveau_disp base; 15 17 struct nouveau_oclass *sclass; 18 + 19 + struct work_struct supervisor; 20 + u32 super; 21 + 16 22 struct { 17 23 int nr; 18 24 } head; ··· 32 26 int (*power)(struct nv50_disp_priv *, int sor, u32 data); 33 27 int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32); 34 28 int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); 35 - int (*dp_train_init)(struct nv50_disp_priv *, int sor, int link, 36 - int head, u16 type, u16 mask, u32 data, 37 - struct dcb_output *); 38 - int (*dp_train_fini)(struct nv50_disp_priv *, int sor, int link, 39 - int head, u16 type, u16 mask, u32 data, 40 - struct dcb_output *); 41 - int (*dp_train)(struct nv50_disp_priv *, int sor, int link, 42 - u16 type, u16 mask, u32 data, 43 - struct dcb_output *); 44 - int (*dp_lnkctl)(struct nv50_disp_priv *, int sor, int link, 45 - int head, u16 type, u16 mask, u32 data, 46 - struct dcb_output *); 47 - int (*dp_drvctl)(struct nv50_disp_priv *, int sor, int link, 48 - int lane, u16 type, u16 mask, u32 data, 49 - struct dcb_output *); 50 29 u32 lvdsconf; 30 + const struct nouveau_dp_func *dp; 51 31 } sor; 32 + struct { 33 + int nr; 34 + int (*power)(struct nv50_disp_priv *, int ext, u32 data); 35 + u8 type[3]; 36 + const struct nouveau_dp_func *dp; 37 + } pior; 52 38 }; 53 39 54 40 #define DAC_MTHD(n) (n), (n) + 0x03 ··· 78 80 struct dcb_output *); 79 81 int nvd0_sor_dp_drvctl(struct nv50_disp_priv *, int, int, int, u16, u16, u32, 80 82 struct dcb_output *); 83 + 84 + #define PIOR_MTHD(n) (n), (n) + 0x03 85 + 86 + int nv50_pior_mthd(struct nouveau_object *, u32, void *, u32); 87 + int nv50_pior_power(struct nv50_disp_priv *, int, u32); 81 88 82 89 struct nv50_disp_base { 83 90 struct nouveau_parent base; ··· 127 124 extern struct nouveau_ofuncs nv50_disp_curs_ofuncs; 128 125 extern struct nouveau_ofuncs nv50_disp_base_ofuncs; 129 126 extern struct nouveau_oclass nv50_disp_cclass; 127 + void nv50_disp_intr_supervisor(struct work_struct *); 130 128 void nv50_disp_intr(struct nouveau_subdev *); 131 129 132 130 extern struct nouveau_omthds nv84_disp_base_omthds[]; ··· 141 137 extern struct nouveau_ofuncs nvd0_disp_curs_ofuncs; 142 138 extern struct nouveau_ofuncs nvd0_disp_base_ofuncs; 143 139 extern struct nouveau_oclass nvd0_disp_cclass; 140 + void nvd0_disp_intr_supervisor(struct work_struct *); 144 141 void nvd0_disp_intr(struct nouveau_subdev *); 145 142 146 143 #endif
+8 -4
drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
··· 46 46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 47 47 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 48 48 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 49 + { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 50 + { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 51 + { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, 49 52 {}, 50 53 }; 51 54 ··· 66 63 struct nv50_disp_priv *priv; 67 64 int ret; 68 65 69 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 66 + ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", 70 67 "display", &priv); 71 68 *pobject = nv_object(priv); 72 69 if (ret) ··· 75 72 nv_engine(priv)->sclass = nv84_disp_base_oclass; 76 73 nv_engine(priv)->cclass = &nv50_disp_cclass; 77 74 nv_subdev(priv)->intr = nv50_disp_intr; 75 + INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); 78 76 priv->sclass = nv84_disp_sclass; 79 77 priv->head.nr = 2; 80 78 priv->dac.nr = 3; 81 79 priv->sor.nr = 2; 80 + priv->pior.nr = 3; 82 81 priv->dac.power = nv50_dac_power; 83 82 priv->dac.sense = nv50_dac_sense; 84 83 priv->sor.power = nv50_sor_power; 85 84 priv->sor.hdmi = nv84_hdmi_ctrl; 86 - 87 - INIT_LIST_HEAD(&priv->base.vblank.list); 88 - spin_lock_init(&priv->base.vblank.lock); 85 + priv->pior.power = nv50_pior_power; 86 + priv->pior.dp = &nv50_pior_dp_func; 89 87 return 0; 90 88 } 91 89
+9 -15
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
··· 44 44 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 45 45 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 46 46 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 47 - { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, 48 - { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, 49 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, 50 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd }, 51 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd }, 52 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd }, 53 47 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 54 48 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 49 + { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 50 + { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 51 + { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, 55 52 {}, 56 53 }; 57 54 ··· 66 69 struct nv50_disp_priv *priv; 67 70 int ret; 68 71 69 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 72 + ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", 70 73 "display", &priv); 71 74 *pobject = nv_object(priv); 72 75 if (ret) ··· 75 78 nv_engine(priv)->sclass = nv94_disp_base_oclass; 76 79 nv_engine(priv)->cclass = &nv50_disp_cclass; 77 80 nv_subdev(priv)->intr = nv50_disp_intr; 81 + INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); 78 82 priv->sclass = nv94_disp_sclass; 79 83 priv->head.nr = 2; 80 84 priv->dac.nr = 3; 81 85 priv->sor.nr = 4; 86 + priv->pior.nr = 3; 82 87 priv->dac.power = nv50_dac_power; 83 88 priv->dac.sense = nv50_dac_sense; 84 89 priv->sor.power = nv50_sor_power; 85 90 priv->sor.hdmi = nv84_hdmi_ctrl; 86 - priv->sor.dp_train = nv94_sor_dp_train; 87 - priv->sor.dp_train_init = nv94_sor_dp_train_init; 88 - priv->sor.dp_train_fini = nv94_sor_dp_train_fini; 89 - priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl; 90 - priv->sor.dp_drvctl = nv94_sor_dp_drvctl; 91 - 92 - INIT_LIST_HEAD(&priv->base.vblank.list); 93 - spin_lock_init(&priv->base.vblank.lock); 91 + priv->sor.dp = &nv94_sor_dp_func; 92 + priv->pior.power = nv50_pior_power; 93 + priv->pior.dp = &nv50_pior_dp_func; 94 94 return 0; 95 95 } 96 96
+5 -4
drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
··· 53 53 struct nv50_disp_priv *priv; 54 54 int ret; 55 55 56 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 56 + ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", 57 57 "display", &priv); 58 58 *pobject = nv_object(priv); 59 59 if (ret) ··· 62 62 nv_engine(priv)->sclass = nva0_disp_base_oclass; 63 63 nv_engine(priv)->cclass = &nv50_disp_cclass; 64 64 nv_subdev(priv)->intr = nv50_disp_intr; 65 + INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); 65 66 priv->sclass = nva0_disp_sclass; 66 67 priv->head.nr = 2; 67 68 priv->dac.nr = 3; 68 69 priv->sor.nr = 2; 70 + priv->pior.nr = 3; 69 71 priv->dac.power = nv50_dac_power; 70 72 priv->dac.sense = nv50_dac_sense; 71 73 priv->sor.power = nv50_sor_power; 72 74 priv->sor.hdmi = nv84_hdmi_ctrl; 73 - 74 - INIT_LIST_HEAD(&priv->base.vblank.list); 75 - spin_lock_init(&priv->base.vblank.lock); 75 + priv->pior.power = nv50_pior_power; 76 + priv->pior.dp = &nv50_pior_dp_func; 76 77 return 0; 77 78 } 78 79
+9 -15
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
··· 45 45 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, 46 46 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 47 47 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 48 - { SOR_MTHD(NV94_DISP_SOR_DP_TRAIN) , nv50_sor_mthd }, 49 - { SOR_MTHD(NV94_DISP_SOR_DP_LNKCTL) , nv50_sor_mthd }, 50 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(0)), nv50_sor_mthd }, 51 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(1)), nv50_sor_mthd }, 52 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(2)), nv50_sor_mthd }, 53 - { SOR_MTHD(NV94_DISP_SOR_DP_DRVCTL(3)), nv50_sor_mthd }, 54 48 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 55 49 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 50 + { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, 51 + { PIOR_MTHD(NV50_DISP_PIOR_TMDS_PWR) , nv50_pior_mthd }, 52 + { PIOR_MTHD(NV50_DISP_PIOR_DP_PWR) , nv50_pior_mthd }, 56 53 {}, 57 54 }; 58 55 ··· 67 70 struct nv50_disp_priv *priv; 68 71 int ret; 69 72 70 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 73 + ret = nouveau_disp_create(parent, engine, oclass, 2, "PDISP", 71 74 "display", &priv); 72 75 *pobject = nv_object(priv); 73 76 if (ret) ··· 76 79 nv_engine(priv)->sclass = nva3_disp_base_oclass; 77 80 nv_engine(priv)->cclass = &nv50_disp_cclass; 78 81 nv_subdev(priv)->intr = nv50_disp_intr; 82 + INIT_WORK(&priv->supervisor, nv50_disp_intr_supervisor); 79 83 priv->sclass = nva3_disp_sclass; 80 84 priv->head.nr = 2; 81 85 priv->dac.nr = 3; 82 86 priv->sor.nr = 4; 87 + priv->pior.nr = 3; 83 88 priv->dac.power = nv50_dac_power; 84 89 priv->dac.sense = nv50_dac_sense; 85 90 priv->sor.power = nv50_sor_power; 86 91 priv->sor.hda_eld = nva3_hda_eld; 87 92 priv->sor.hdmi = nva3_hdmi_ctrl; 88 - priv->sor.dp_train = nv94_sor_dp_train; 89 - priv->sor.dp_train_init = nv94_sor_dp_train_init; 90 - priv->sor.dp_train_fini = nv94_sor_dp_train_fini; 91 - priv->sor.dp_lnkctl = nv94_sor_dp_lnkctl; 92 - priv->sor.dp_drvctl = nv94_sor_dp_drvctl; 93 - 94 - INIT_LIST_HEAD(&priv->base.vblank.list); 95 - spin_lock_init(&priv->base.vblank.lock); 93 + priv->sor.dp = &nv94_sor_dp_func; 94 + priv->pior.power = nv50_pior_power; 95 + priv->pior.dp = &nv50_pior_dp_func; 96 96 return 0; 97 97 } 98 98
+77 -75
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
··· 27 27 #include <core/handle.h> 28 28 #include <core/class.h> 29 29 30 - #include <engine/software.h> 31 30 #include <engine/disp.h> 32 31 33 32 #include <subdev/timer.h> 34 33 #include <subdev/fb.h> 35 - #include <subdev/bar.h> 36 34 #include <subdev/clock.h> 37 35 38 36 #include <subdev/bios.h> ··· 228 230 struct nv50_disp_dmac *dmac; 229 231 int ret; 230 232 231 - if (size < sizeof(*data) || args->head >= priv->head.nr) 233 + if (size < sizeof(*args) || args->head >= priv->head.nr) 232 234 return -EINVAL; 233 235 234 236 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, ··· 268 270 struct nv50_disp_dmac *dmac; 269 271 int ret; 270 272 271 - if (size < sizeof(*data) || args->head >= priv->head.nr) 273 + if (size < sizeof(*args) || args->head >= priv->head.nr) 272 274 return -EINVAL; 273 275 274 276 ret = nv50_disp_dmac_create_(parent, engine, oclass, args->pushbuf, ··· 441 443 * Base display object 442 444 ******************************************************************************/ 443 445 446 + static void 447 + nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head) 448 + { 449 + nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001); 450 + } 451 + 452 + static void 453 + nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head) 454 + { 455 + nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000); 456 + } 457 + 444 458 static int 445 459 nvd0_disp_base_ctor(struct nouveau_object *parent, 446 460 struct nouveau_object *engine, ··· 468 458 *pobject = nv_object(base); 469 459 if (ret) 470 460 return ret; 461 + 462 + priv->base.vblank->priv = priv; 463 + priv->base.vblank->enable = nvd0_disp_base_vblank_enable; 464 + priv->base.vblank->disable = nvd0_disp_base_vblank_disable; 471 465 472 466 return nouveau_ramht_new(parent, parent, 0x1000, 0, &base->ramht); 473 467 } ··· 650 636 651 637 static u32 652 638 exec_clkcmp(struct nv50_disp_priv *priv, int head, int outp, 653 - u32 ctrl, int id, u32 pclk) 639 + u32 ctrl, int id, u32 pclk, struct dcb_output *dcb) 654 640 { 655 641 struct nouveau_bios *bios = nouveau_bios(priv); 656 642 struct nvbios_outp info1; 657 643 struct nvbios_ocfg info2; 658 - struct dcb_output dcb; 659 644 u8 ver, hdr, cnt, len; 660 - u16 data, conf; 645 + u32 data, conf = ~0; 661 646 662 - data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info1); 647 + data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); 663 648 if (data == 0x0000) 664 - return false; 649 + return conf; 665 650 666 - switch (dcb.type) { 651 + switch (dcb->type) { 667 652 case DCB_OUTPUT_TMDS: 668 653 conf = (ctrl & 0x00000f00) >> 8; 669 654 if (pclk >= 165000) ··· 681 668 } 682 669 683 670 data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 684 - if (data) { 671 + if (data && id < 0xff) { 685 672 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 686 673 if (data) { 687 674 struct nvbios_init init = { 688 675 .subdev = nv_subdev(priv), 689 676 .bios = bios, 690 677 .offset = data, 691 - .outp = &dcb, 678 + .outp = dcb, 692 679 .crtc = head, 693 680 .execute = 1, 694 681 }; 695 682 696 - if (nvbios_exec(&init)) 697 - return 0x0000; 698 - return conf; 683 + nvbios_exec(&init); 699 684 } 700 685 } 701 686 702 - return 0x0000; 687 + return conf; 703 688 } 704 689 705 690 static void ··· 763 752 static void 764 753 nvd0_display_unk2_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) 765 754 { 755 + struct dcb_output outp; 766 756 u32 pclk; 767 757 int i; 768 758 ··· 783 771 nv_wr32(priv, 0x612200 + (head * 0x800), 0x00000000); 784 772 785 773 for (i = 0; mask && i < 8; i++) { 786 - u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)), cfg; 774 + u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)); 787 775 if (mcp & (1 << head)) { 788 - if ((cfg = exec_clkcmp(priv, head, i, mcp, 0, pclk))) { 776 + u32 cfg = exec_clkcmp(priv, head, i, mcp, 0xff, pclk, &outp); 777 + if (cfg != ~0) { 789 778 u32 addr, mask, data = 0x00000000; 779 + 780 + if (outp.type == DCB_OUTPUT_DP) { 781 + switch ((mcp & 0x000f0000) >> 16) { 782 + case 6: pclk = pclk * 30 / 8; break; 783 + case 5: pclk = pclk * 24 / 8; break; 784 + case 2: 785 + default: 786 + pclk = pclk * 18 / 8; 787 + break; 788 + } 789 + 790 + nouveau_dp_train(&priv->base, 791 + priv->sor.dp, 792 + &outp, head, pclk); 793 + } 794 + 795 + exec_clkcmp(priv, head, i, mcp, 0, pclk, &outp); 796 + 790 797 if (i < 4) { 791 798 addr = 0x612280 + ((i - 0) * 0x800); 792 799 mask = 0xffffffff; ··· 838 807 static void 839 808 nvd0_display_unk4_handler(struct nv50_disp_priv *priv, u32 head, u32 mask) 840 809 { 810 + struct dcb_output outp; 841 811 int pclk, i; 842 812 843 813 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; ··· 846 814 for (i = 0; mask && i < 8; i++) { 847 815 u32 mcp = nv_rd32(priv, 0x660180 + (i * 0x20)); 848 816 if (mcp & (1 << head)) 849 - exec_clkcmp(priv, head, i, mcp, 1, pclk); 817 + exec_clkcmp(priv, head, i, mcp, 1, pclk, &outp); 850 818 } 851 819 852 820 nv_wr32(priv, 0x6101d4, 0x00000000); ··· 854 822 nv_wr32(priv, 0x6101d0, 0x80000000); 855 823 } 856 824 857 - static void 858 - nvd0_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc) 825 + void 826 + nvd0_disp_intr_supervisor(struct work_struct *work) 859 827 { 860 - struct nouveau_bar *bar = nouveau_bar(priv); 861 - struct nouveau_disp *disp = &priv->base; 862 - struct nouveau_software_chan *chan, *temp; 863 - unsigned long flags; 828 + struct nv50_disp_priv *priv = 829 + container_of(work, struct nv50_disp_priv, supervisor); 830 + u32 mask = 0, head = ~0; 864 831 865 - spin_lock_irqsave(&disp->vblank.lock, flags); 866 - list_for_each_entry_safe(chan, temp, &disp->vblank.list, vblank.head) { 867 - if (chan->vblank.crtc != crtc) 868 - continue; 832 + while (!mask && ++head < priv->head.nr) 833 + mask = nv_rd32(priv, 0x6101d4 + (head * 0x800)); 869 834 870 - nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); 871 - bar->flush(bar); 872 - nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); 873 - nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); 874 - nv_wr32(priv, 0x060014, chan->vblank.value); 835 + nv_debug(priv, "supervisor %08x %08x %d\n", priv->super, mask, head); 875 836 876 - list_del(&chan->vblank.head); 877 - if (disp->vblank.put) 878 - disp->vblank.put(disp->vblank.data, crtc); 879 - } 880 - spin_unlock_irqrestore(&disp->vblank.lock, flags); 881 - 882 - if (disp->vblank.notify) 883 - disp->vblank.notify(disp->vblank.data, crtc); 837 + if (priv->super & 0x00000001) 838 + nvd0_display_unk1_handler(priv, head, mask); 839 + if (priv->super & 0x00000002) 840 + nvd0_display_unk2_handler(priv, head, mask); 841 + if (priv->super & 0x00000004) 842 + nvd0_display_unk4_handler(priv, head, mask); 884 843 } 885 844 886 845 void ··· 907 884 908 885 if (intr & 0x00100000) { 909 886 u32 stat = nv_rd32(priv, 0x6100ac); 910 - u32 mask = 0, crtc = ~0; 911 - 912 - while (!mask && ++crtc < priv->head.nr) 913 - mask = nv_rd32(priv, 0x6101d4 + (crtc * 0x800)); 914 - 915 - if (stat & 0x00000001) { 916 - nv_wr32(priv, 0x6100ac, 0x00000001); 917 - nvd0_display_unk1_handler(priv, crtc, mask); 918 - stat &= ~0x00000001; 919 - } 920 - 921 - if (stat & 0x00000002) { 922 - nv_wr32(priv, 0x6100ac, 0x00000002); 923 - nvd0_display_unk2_handler(priv, crtc, mask); 924 - stat &= ~0x00000002; 925 - } 926 - 927 - if (stat & 0x00000004) { 928 - nv_wr32(priv, 0x6100ac, 0x00000004); 929 - nvd0_display_unk4_handler(priv, crtc, mask); 930 - stat &= ~0x00000004; 887 + if (stat & 0x00000007) { 888 + priv->super = (stat & 0x00000007); 889 + schedule_work(&priv->supervisor); 890 + nv_wr32(priv, 0x6100ac, priv->super); 891 + stat &= ~0x00000007; 931 892 } 932 893 933 894 if (stat) { ··· 927 920 if (mask & intr) { 928 921 u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); 929 922 if (stat & 0x00000001) 930 - nvd0_disp_intr_vblank(priv, i); 923 + nouveau_event_trigger(priv->base.vblank, i); 931 924 nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); 932 925 nv_rd32(priv, 0x6100c0 + (i * 0x800)); 933 926 } ··· 940 933 struct nouveau_object **pobject) 941 934 { 942 935 struct nv50_disp_priv *priv; 936 + int heads = nv_rd32(parent, 0x022448); 943 937 int ret; 944 938 945 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 946 - "display", &priv); 939 + ret = nouveau_disp_create(parent, engine, oclass, heads, 940 + "PDISP", "display", &priv); 947 941 *pobject = nv_object(priv); 948 942 if (ret) 949 943 return ret; ··· 952 944 nv_engine(priv)->sclass = nvd0_disp_base_oclass; 953 945 nv_engine(priv)->cclass = &nv50_disp_cclass; 954 946 nv_subdev(priv)->intr = nvd0_disp_intr; 947 + INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); 955 948 priv->sclass = nvd0_disp_sclass; 956 - priv->head.nr = nv_rd32(priv, 0x022448); 949 + priv->head.nr = heads; 957 950 priv->dac.nr = 3; 958 951 priv->sor.nr = 4; 959 952 priv->dac.power = nv50_dac_power; ··· 962 953 priv->sor.power = nv50_sor_power; 963 954 priv->sor.hda_eld = nvd0_hda_eld; 964 955 priv->sor.hdmi = nvd0_hdmi_ctrl; 965 - priv->sor.dp_train = nvd0_sor_dp_train; 966 - priv->sor.dp_train_init = nv94_sor_dp_train_init; 967 - priv->sor.dp_train_fini = nv94_sor_dp_train_fini; 968 - priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; 969 - priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; 970 - 971 - INIT_LIST_HEAD(&priv->base.vblank.list); 972 - spin_lock_init(&priv->base.vblank.lock); 956 + priv->sor.dp = &nvd0_sor_dp_func; 973 957 return 0; 974 958 } 975 959
+6 -11
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
··· 51 51 struct nouveau_object **pobject) 52 52 { 53 53 struct nv50_disp_priv *priv; 54 + int heads = nv_rd32(parent, 0x022448); 54 55 int ret; 55 56 56 - ret = nouveau_disp_create(parent, engine, oclass, "PDISP", 57 - "display", &priv); 57 + ret = nouveau_disp_create(parent, engine, oclass, heads, 58 + "PDISP", "display", &priv); 58 59 *pobject = nv_object(priv); 59 60 if (ret) 60 61 return ret; ··· 63 62 nv_engine(priv)->sclass = nve0_disp_base_oclass; 64 63 nv_engine(priv)->cclass = &nv50_disp_cclass; 65 64 nv_subdev(priv)->intr = nvd0_disp_intr; 65 + INIT_WORK(&priv->supervisor, nvd0_disp_intr_supervisor); 66 66 priv->sclass = nve0_disp_sclass; 67 - priv->head.nr = nv_rd32(priv, 0x022448); 67 + priv->head.nr = heads; 68 68 priv->dac.nr = 3; 69 69 priv->sor.nr = 4; 70 70 priv->dac.power = nv50_dac_power; ··· 73 71 priv->sor.power = nv50_sor_power; 74 72 priv->sor.hda_eld = nvd0_hda_eld; 75 73 priv->sor.hdmi = nvd0_hdmi_ctrl; 76 - priv->sor.dp_train = nvd0_sor_dp_train; 77 - priv->sor.dp_train_init = nv94_sor_dp_train_init; 78 - priv->sor.dp_train_fini = nv94_sor_dp_train_fini; 79 - priv->sor.dp_lnkctl = nvd0_sor_dp_lnkctl; 80 - priv->sor.dp_drvctl = nvd0_sor_dp_drvctl; 81 - 82 - INIT_LIST_HEAD(&priv->base.vblank.list); 83 - spin_lock_init(&priv->base.vblank.lock); 74 + priv->sor.dp = &nvd0_sor_dp_func; 84 75 return 0; 85 76 } 86 77
+140
drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
··· 1 + /* 2 + * Copyright 2012 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 <core/os.h> 26 + #include <core/class.h> 27 + 28 + #include <subdev/bios.h> 29 + #include <subdev/bios/dcb.h> 30 + #include <subdev/timer.h> 31 + #include <subdev/i2c.h> 32 + 33 + #include "nv50.h" 34 + 35 + /****************************************************************************** 36 + * DisplayPort 37 + *****************************************************************************/ 38 + static struct nouveau_i2c_port * 39 + nv50_pior_dp_find(struct nouveau_disp *disp, struct dcb_output *outp) 40 + { 41 + struct nouveau_i2c *i2c = nouveau_i2c(disp); 42 + return i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); 43 + } 44 + 45 + static int 46 + nv50_pior_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, 47 + int head, int pattern) 48 + { 49 + struct nouveau_i2c_port *port; 50 + int ret = -EINVAL; 51 + 52 + port = nv50_pior_dp_find(disp, outp); 53 + if (port) { 54 + if (port->func->pattern) 55 + ret = port->func->pattern(port, pattern); 56 + else 57 + ret = 0; 58 + } 59 + 60 + return ret; 61 + } 62 + 63 + static int 64 + nv50_pior_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 65 + int head, int lane_nr, int link_bw, bool enh) 66 + { 67 + struct nouveau_i2c_port *port; 68 + int ret = -EINVAL; 69 + 70 + port = nv50_pior_dp_find(disp, outp); 71 + if (port && port->func->lnk_ctl) 72 + ret = port->func->lnk_ctl(port, lane_nr, link_bw, enh); 73 + 74 + return ret; 75 + } 76 + 77 + static int 78 + nv50_pior_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 79 + int head, int lane, int vsw, int pre) 80 + { 81 + struct nouveau_i2c_port *port; 82 + int ret = -EINVAL; 83 + 84 + port = nv50_pior_dp_find(disp, outp); 85 + if (port) { 86 + if (port->func->drv_ctl) 87 + ret = port->func->drv_ctl(port, lane, vsw, pre); 88 + else 89 + ret = 0; 90 + } 91 + 92 + return ret; 93 + } 94 + 95 + const struct nouveau_dp_func 96 + nv50_pior_dp_func = { 97 + .pattern = nv50_pior_dp_pattern, 98 + .lnk_ctl = nv50_pior_dp_lnk_ctl, 99 + .drv_ctl = nv50_pior_dp_drv_ctl, 100 + }; 101 + 102 + /****************************************************************************** 103 + * General PIOR handling 104 + *****************************************************************************/ 105 + int 106 + nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data) 107 + { 108 + const u32 stat = data & NV50_DISP_PIOR_PWR_STATE; 109 + const u32 soff = (or * 0x800); 110 + nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000); 111 + nv_mask(priv, 0x61e004 + soff, 0x80000101, 0x80000000 | stat); 112 + nv_wait(priv, 0x61e004 + soff, 0x80000000, 0x00000000); 113 + return 0; 114 + } 115 + 116 + int 117 + nv50_pior_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) 118 + { 119 + struct nv50_disp_priv *priv = (void *)object->engine; 120 + const u8 type = (mthd & NV50_DISP_PIOR_MTHD_TYPE) >> 12; 121 + const u8 or = (mthd & NV50_DISP_PIOR_MTHD_OR); 122 + u32 *data = args; 123 + int ret; 124 + 125 + if (size < sizeof(u32)) 126 + return -EINVAL; 127 + 128 + mthd &= ~NV50_DISP_PIOR_MTHD_TYPE; 129 + mthd &= ~NV50_DISP_PIOR_MTHD_OR; 130 + switch (mthd) { 131 + case NV50_DISP_PIOR_PWR: 132 + ret = priv->pior.power(priv, or, data[0]); 133 + priv->pior.type[or] = type; 134 + break; 135 + default: 136 + return -EINVAL; 137 + } 138 + 139 + return ret; 140 + }
-25
drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
··· 79 79 priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; 80 80 ret = 0; 81 81 break; 82 - case NV94_DISP_SOR_DP_TRAIN: 83 - switch (data & NV94_DISP_SOR_DP_TRAIN_OP) { 84 - case NV94_DISP_SOR_DP_TRAIN_OP_PATTERN: 85 - ret = priv->sor.dp_train(priv, or, link, type, mask, data, &outp); 86 - break; 87 - case NV94_DISP_SOR_DP_TRAIN_OP_INIT: 88 - ret = priv->sor.dp_train_init(priv, or, link, head, type, mask, data, &outp); 89 - break; 90 - case NV94_DISP_SOR_DP_TRAIN_OP_FINI: 91 - ret = priv->sor.dp_train_fini(priv, or, link, head, type, mask, data, &outp); 92 - break; 93 - default: 94 - break; 95 - } 96 - break; 97 - case NV94_DISP_SOR_DP_LNKCTL: 98 - ret = priv->sor.dp_lnkctl(priv, or, link, head, type, mask, data, &outp); 99 - break; 100 - case NV94_DISP_SOR_DP_DRVCTL(0): 101 - case NV94_DISP_SOR_DP_DRVCTL(1): 102 - case NV94_DISP_SOR_DP_DRVCTL(2): 103 - case NV94_DISP_SOR_DP_DRVCTL(3): 104 - ret = priv->sor.dp_drvctl(priv, or, link, (mthd & 0xc0) >> 6, 105 - type, mask, data, &outp); 106 - break; 107 82 default: 108 83 BUG_ON(1); 109 84 }
+45 -108
drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
··· 33 33 #include "nv50.h" 34 34 35 35 static inline u32 36 + nv94_sor_soff(struct dcb_output *outp) 37 + { 38 + return (ffs(outp->or) - 1) * 0x800; 39 + } 40 + 41 + static inline u32 42 + nv94_sor_loff(struct dcb_output *outp) 43 + { 44 + return nv94_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; 45 + } 46 + 47 + static inline u32 36 48 nv94_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) 37 49 { 38 50 static const u8 nvaf[] = { 24, 16, 8, 0 }; /* thanks, apple.. */ ··· 54 42 return nv94[lane]; 55 43 } 56 44 57 - int 58 - nv94_sor_dp_train_init(struct nv50_disp_priv *priv, int or, int link, int head, 59 - u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 45 + static int 46 + nv94_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, 47 + int head, int pattern) 60 48 { 61 - struct nouveau_bios *bios = nouveau_bios(priv); 62 - struct nvbios_dpout info; 63 - u8 ver, hdr, cnt, len; 64 - u16 outp; 65 - 66 - outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); 67 - if (outp) { 68 - struct nvbios_init init = { 69 - .subdev = nv_subdev(priv), 70 - .bios = bios, 71 - .outp = dcbo, 72 - .crtc = head, 73 - .execute = 1, 74 - }; 75 - 76 - if (data & NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON) 77 - init.offset = info.script[2]; 78 - else 79 - init.offset = info.script[3]; 80 - nvbios_exec(&init); 81 - 82 - init.offset = info.script[0]; 83 - nvbios_exec(&init); 84 - } 85 - 49 + struct nv50_disp_priv *priv = (void *)disp; 50 + const u32 loff = nv94_sor_loff(outp); 51 + nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24); 86 52 return 0; 87 53 } 88 54 89 - int 90 - nv94_sor_dp_train_fini(struct nv50_disp_priv *priv, int or, int link, int head, 91 - u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 55 + static int 56 + nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 57 + int head, int link_nr, int link_bw, bool enh_frame) 92 58 { 93 - struct nouveau_bios *bios = nouveau_bios(priv); 94 - struct nvbios_dpout info; 95 - u8 ver, hdr, cnt, len; 96 - u16 outp; 97 - 98 - outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); 99 - if (outp) { 100 - struct nvbios_init init = { 101 - .subdev = nv_subdev(priv), 102 - .bios = bios, 103 - .offset = info.script[1], 104 - .outp = dcbo, 105 - .crtc = head, 106 - .execute = 1, 107 - }; 108 - 109 - nvbios_exec(&init); 110 - } 111 - 112 - return 0; 113 - } 114 - 115 - int 116 - nv94_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, 117 - u16 type, u16 mask, u32 data, struct dcb_output *info) 118 - { 119 - const u32 loff = (or * 0x800) + (link * 0x80); 120 - const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); 121 - nv_mask(priv, 0x61c10c + loff, 0x0f000000, patt << 24); 122 - return 0; 123 - } 124 - 125 - int 126 - nv94_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, 127 - u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 128 - { 129 - struct nouveau_bios *bios = nouveau_bios(priv); 130 - const u32 loff = (or * 0x800) + (link * 0x80); 131 - const u32 soff = (or * 0x800); 132 - u16 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8; 133 - u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT); 59 + struct nv50_disp_priv *priv = (void *)disp; 60 + const u32 soff = nv94_sor_soff(outp); 61 + const u32 loff = nv94_sor_loff(outp); 134 62 u32 dpctrl = 0x00000000; 135 63 u32 clksor = 0x00000000; 136 - u32 outp, lane = 0; 137 - u8 ver, hdr, cnt, len; 138 - struct nvbios_dpout info; 64 + u32 lane = 0; 139 65 int i; 140 66 141 - /* -> 10Khz units */ 142 - link_bw *= 2700; 143 - 144 - outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); 145 - if (outp && info.lnkcmp) { 146 - struct nvbios_init init = { 147 - .subdev = nv_subdev(priv), 148 - .bios = bios, 149 - .offset = 0x0000, 150 - .outp = dcbo, 151 - .crtc = head, 152 - .execute = 1, 153 - }; 154 - 155 - while (link_bw < nv_ro16(bios, info.lnkcmp)) 156 - info.lnkcmp += 4; 157 - init.offset = nv_ro16(bios, info.lnkcmp + 2); 158 - 159 - nvbios_exec(&init); 160 - } 161 - 162 67 dpctrl |= ((1 << link_nr) - 1) << 16; 163 - if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) 68 + if (enh_frame) 164 69 dpctrl |= 0x00004000; 165 - if (link_bw > 16200) 70 + if (link_bw > 0x06) 166 71 clksor |= 0x00040000; 167 72 168 73 for (i = 0; i < link_nr; i++) ··· 91 162 return 0; 92 163 } 93 164 94 - int 95 - nv94_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, 96 - u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 165 + static int 166 + nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 167 + int head, int lane, int swing, int preem) 97 168 { 98 - struct nouveau_bios *bios = nouveau_bios(priv); 99 - const u32 loff = (or * 0x800) + (link * 0x80); 100 - const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; 101 - const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE); 169 + struct nouveau_bios *bios = nouveau_bios(disp); 170 + struct nv50_disp_priv *priv = (void *)disp; 171 + const u32 loff = nv94_sor_loff(outp); 102 172 u32 addr, shift = nv94_sor_dp_lane_map(priv, lane); 103 173 u8 ver, hdr, cnt, len; 104 - struct nvbios_dpout outp; 174 + struct nvbios_dpout info; 105 175 struct nvbios_dpcfg ocfg; 106 176 107 - addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); 177 + addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, 178 + &ver, &hdr, &cnt, &len, &info); 108 179 if (!addr) 109 180 return -ENODEV; 110 181 111 - addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); 182 + addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, 183 + &ver, &hdr, &cnt, &len, &ocfg); 112 184 if (!addr) 113 185 return -EINVAL; 114 186 ··· 118 188 nv_mask(priv, 0x61c130 + loff, 0x0000ff00, ocfg.unk << 8); 119 189 return 0; 120 190 } 191 + 192 + const struct nouveau_dp_func 193 + nv94_sor_dp_func = { 194 + .pattern = nv94_sor_dp_pattern, 195 + .lnk_ctl = nv94_sor_dp_lnk_ctl, 196 + .drv_ctl = nv94_sor_dp_drv_ctl, 197 + };
+44 -46
drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
··· 33 33 #include "nv50.h" 34 34 35 35 static inline u32 36 + nvd0_sor_soff(struct dcb_output *outp) 37 + { 38 + return (ffs(outp->or) - 1) * 0x800; 39 + } 40 + 41 + static inline u32 42 + nvd0_sor_loff(struct dcb_output *outp) 43 + { 44 + return nvd0_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; 45 + } 46 + 47 + static inline u32 36 48 nvd0_sor_dp_lane_map(struct nv50_disp_priv *priv, u8 lane) 37 49 { 38 50 static const u8 nvd0[] = { 16, 8, 0, 24 }; 39 51 return nvd0[lane]; 40 52 } 41 53 42 - int 43 - nvd0_sor_dp_train(struct nv50_disp_priv *priv, int or, int link, 44 - u16 type, u16 mask, u32 data, struct dcb_output *info) 54 + static int 55 + nvd0_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, 56 + int head, int pattern) 45 57 { 46 - const u32 loff = (or * 0x800) + (link * 0x80); 47 - const u32 patt = (data & NV94_DISP_SOR_DP_TRAIN_PATTERN); 48 - nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * patt); 58 + struct nv50_disp_priv *priv = (void *)disp; 59 + const u32 loff = nvd0_sor_loff(outp); 60 + nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); 49 61 return 0; 50 62 } 51 63 52 - int 53 - nvd0_sor_dp_lnkctl(struct nv50_disp_priv *priv, int or, int link, int head, 54 - u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 64 + static int 65 + nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 66 + int head, int link_nr, int link_bw, bool enh_frame) 55 67 { 56 - struct nouveau_bios *bios = nouveau_bios(priv); 57 - const u32 loff = (or * 0x800) + (link * 0x80); 58 - const u32 soff = (or * 0x800); 59 - const u8 link_bw = (data & NV94_DISP_SOR_DP_LNKCTL_WIDTH) >> 8; 60 - const u8 link_nr = (data & NV94_DISP_SOR_DP_LNKCTL_COUNT); 68 + struct nv50_disp_priv *priv = (void *)disp; 69 + const u32 soff = nvd0_sor_soff(outp); 70 + const u32 loff = nvd0_sor_loff(outp); 61 71 u32 dpctrl = 0x00000000; 62 72 u32 clksor = 0x00000000; 63 - u32 outp, lane = 0; 64 - u8 ver, hdr, cnt, len; 65 - struct nvbios_dpout info; 73 + u32 lane = 0; 66 74 int i; 67 - 68 - outp = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &info); 69 - if (outp && info.lnkcmp) { 70 - struct nvbios_init init = { 71 - .subdev = nv_subdev(priv), 72 - .bios = bios, 73 - .offset = 0x0000, 74 - .outp = dcbo, 75 - .crtc = head, 76 - .execute = 1, 77 - }; 78 - 79 - while (nv_ro08(bios, info.lnkcmp) < link_bw) 80 - info.lnkcmp += 3; 81 - init.offset = nv_ro16(bios, info.lnkcmp + 1); 82 - 83 - nvbios_exec(&init); 84 - } 85 75 86 76 clksor |= link_bw << 18; 87 77 dpctrl |= ((1 << link_nr) - 1) << 16; 88 - if (data & NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH) 78 + if (enh_frame) 89 79 dpctrl |= 0x00004000; 90 80 91 81 for (i = 0; i < link_nr; i++) ··· 87 97 return 0; 88 98 } 89 99 90 - int 91 - nvd0_sor_dp_drvctl(struct nv50_disp_priv *priv, int or, int link, int lane, 92 - u16 type, u16 mask, u32 data, struct dcb_output *dcbo) 100 + static int 101 + nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 102 + int head, int lane, int swing, int preem) 93 103 { 94 - struct nouveau_bios *bios = nouveau_bios(priv); 95 - const u32 loff = (or * 0x800) + (link * 0x80); 96 - const u8 swing = (data & NV94_DISP_SOR_DP_DRVCTL_VS) >> 8; 97 - const u8 preem = (data & NV94_DISP_SOR_DP_DRVCTL_PE); 104 + struct nouveau_bios *bios = nouveau_bios(disp); 105 + struct nv50_disp_priv *priv = (void *)disp; 106 + const u32 loff = nvd0_sor_loff(outp); 98 107 u32 addr, shift = nvd0_sor_dp_lane_map(priv, lane); 99 108 u8 ver, hdr, cnt, len; 100 - struct nvbios_dpout outp; 109 + struct nvbios_dpout info; 101 110 struct nvbios_dpcfg ocfg; 102 111 103 - addr = nvbios_dpout_match(bios, type, mask, &ver, &hdr, &cnt, &len, &outp); 112 + addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, 113 + &ver, &hdr, &cnt, &len, &info); 104 114 if (!addr) 105 115 return -ENODEV; 106 116 107 - addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, &ver, &hdr, &cnt, &len, &ocfg); 117 + addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, 118 + &ver, &hdr, &cnt, &len, &ocfg); 108 119 if (!addr) 109 120 return -EINVAL; 110 121 ··· 115 124 nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000); 116 125 return 0; 117 126 } 127 + 128 + const struct nouveau_dp_func 129 + nvd0_sor_dp_func = { 130 + .pattern = nvd0_sor_dp_pattern, 131 + .lnk_ctl = nvd0_sor_dp_lnk_ctl, 132 + .drv_ctl = nvd0_sor_dp_drv_ctl, 133 + };
+21
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/object.h> 26 27 #include <core/handle.h> 28 + #include <core/event.h> 27 29 #include <core/class.h> 28 30 29 31 #include <engine/dmaobj.h> ··· 148 146 return -1; 149 147 } 150 148 149 + const char * 150 + nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid) 151 + { 152 + struct nouveau_fifo_chan *chan = NULL; 153 + unsigned long flags; 154 + 155 + spin_lock_irqsave(&fifo->lock, flags); 156 + if (chid >= fifo->min && chid <= fifo->max) 157 + chan = (void *)fifo->channel[chid]; 158 + spin_unlock_irqrestore(&fifo->lock, flags); 159 + 160 + return nouveau_client_name(chan); 161 + } 162 + 151 163 void 152 164 nouveau_fifo_destroy(struct nouveau_fifo *priv) 153 165 { 154 166 kfree(priv->channel); 167 + nouveau_event_destroy(&priv->uevent); 155 168 nouveau_engine_destroy(&priv->base); 156 169 } 157 170 ··· 190 173 priv->channel = kzalloc(sizeof(*priv->channel) * (max + 1), GFP_KERNEL); 191 174 if (!priv->channel) 192 175 return -ENOMEM; 176 + 177 + ret = nouveau_event_create(1, &priv->uevent); 178 + if (ret) 179 + return ret; 193 180 194 181 priv->chid = nouveau_fifo_chid; 195 182 spin_lock_init(&priv->lock);
+101 -86
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
··· 28 28 #include <core/namedb.h> 29 29 #include <core/handle.h> 30 30 #include <core/ramht.h> 31 + #include <core/event.h> 31 32 32 33 #include <subdev/instmem.h> 33 34 #include <subdev/instmem/nv04.h> ··· 399 398 return handled; 400 399 } 401 400 401 + static void 402 + nv04_fifo_cache_error(struct nouveau_device *device, 403 + struct nv04_fifo_priv *priv, u32 chid, u32 get) 404 + { 405 + u32 mthd, data; 406 + int ptr; 407 + 408 + /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before wrapping on my 409 + * G80 chips, but CACHE1 isn't big enough for this much data.. Tests 410 + * show that it wraps around to the start at GET=0x800.. No clue as to 411 + * why.. 412 + */ 413 + ptr = (get & 0x7ff) >> 2; 414 + 415 + if (device->card_type < NV_40) { 416 + mthd = nv_rd32(priv, NV04_PFIFO_CACHE1_METHOD(ptr)); 417 + data = nv_rd32(priv, NV04_PFIFO_CACHE1_DATA(ptr)); 418 + } else { 419 + mthd = nv_rd32(priv, NV40_PFIFO_CACHE1_METHOD(ptr)); 420 + data = nv_rd32(priv, NV40_PFIFO_CACHE1_DATA(ptr)); 421 + } 422 + 423 + if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { 424 + const char *client_name = 425 + nouveau_client_name_for_fifo_chid(&priv->base, chid); 426 + nv_error(priv, 427 + "CACHE_ERROR - ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", 428 + chid, client_name, (mthd >> 13) & 7, mthd & 0x1ffc, 429 + data); 430 + } 431 + 432 + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); 433 + nv_wr32(priv, NV03_PFIFO_INTR_0, NV_PFIFO_INTR_CACHE_ERROR); 434 + 435 + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 436 + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); 437 + nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); 438 + nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 439 + nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); 440 + nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); 441 + 442 + nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 443 + nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); 444 + nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); 445 + } 446 + 447 + static void 448 + nv04_fifo_dma_pusher(struct nouveau_device *device, struct nv04_fifo_priv *priv, 449 + u32 chid) 450 + { 451 + const char *client_name; 452 + u32 dma_get = nv_rd32(priv, 0x003244); 453 + u32 dma_put = nv_rd32(priv, 0x003240); 454 + u32 push = nv_rd32(priv, 0x003220); 455 + u32 state = nv_rd32(priv, 0x003228); 456 + 457 + client_name = nouveau_client_name_for_fifo_chid(&priv->base, chid); 458 + 459 + if (device->card_type == NV_50) { 460 + u32 ho_get = nv_rd32(priv, 0x003328); 461 + u32 ho_put = nv_rd32(priv, 0x003320); 462 + u32 ib_get = nv_rd32(priv, 0x003334); 463 + u32 ib_put = nv_rd32(priv, 0x003330); 464 + 465 + nv_error(priv, 466 + "DMA_PUSHER - ch %d [%s] get 0x%02x%08x put 0x%02x%08x ib_get 0x%08x ib_put 0x%08x state 0x%08x (err: %s) push 0x%08x\n", 467 + chid, client_name, ho_get, dma_get, ho_put, dma_put, 468 + ib_get, ib_put, state, nv_dma_state_err(state), push); 469 + 470 + /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ 471 + nv_wr32(priv, 0x003364, 0x00000000); 472 + if (dma_get != dma_put || ho_get != ho_put) { 473 + nv_wr32(priv, 0x003244, dma_put); 474 + nv_wr32(priv, 0x003328, ho_put); 475 + } else 476 + if (ib_get != ib_put) 477 + nv_wr32(priv, 0x003334, ib_put); 478 + } else { 479 + nv_error(priv, 480 + "DMA_PUSHER - ch %d [%s] get 0x%08x put 0x%08x state 0x%08x (err: %s) push 0x%08x\n", 481 + chid, client_name, dma_get, dma_put, state, 482 + nv_dma_state_err(state), push); 483 + 484 + if (dma_get != dma_put) 485 + nv_wr32(priv, 0x003244, dma_put); 486 + } 487 + 488 + nv_wr32(priv, 0x003228, 0x00000000); 489 + nv_wr32(priv, 0x003220, 0x00000001); 490 + nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); 491 + } 492 + 402 493 void 403 494 nv04_fifo_intr(struct nouveau_subdev *subdev) 404 495 { ··· 509 416 get = nv_rd32(priv, NV03_PFIFO_CACHE1_GET); 510 417 511 418 if (status & NV_PFIFO_INTR_CACHE_ERROR) { 512 - uint32_t mthd, data; 513 - int ptr; 514 - 515 - /* NV_PFIFO_CACHE1_GET actually goes to 0xffc before 516 - * wrapping on my G80 chips, but CACHE1 isn't big 517 - * enough for this much data.. Tests show that it 518 - * wraps around to the start at GET=0x800.. No clue 519 - * as to why.. 520 - */ 521 - ptr = (get & 0x7ff) >> 2; 522 - 523 - if (device->card_type < NV_40) { 524 - mthd = nv_rd32(priv, 525 - NV04_PFIFO_CACHE1_METHOD(ptr)); 526 - data = nv_rd32(priv, 527 - NV04_PFIFO_CACHE1_DATA(ptr)); 528 - } else { 529 - mthd = nv_rd32(priv, 530 - NV40_PFIFO_CACHE1_METHOD(ptr)); 531 - data = nv_rd32(priv, 532 - NV40_PFIFO_CACHE1_DATA(ptr)); 533 - } 534 - 535 - if (!nv04_fifo_swmthd(priv, chid, mthd, data)) { 536 - nv_error(priv, "CACHE_ERROR - Ch %d/%d " 537 - "Mthd 0x%04x Data 0x%08x\n", 538 - chid, (mthd >> 13) & 7, mthd & 0x1ffc, 539 - data); 540 - } 541 - 542 - nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 0); 543 - nv_wr32(priv, NV03_PFIFO_INTR_0, 544 - NV_PFIFO_INTR_CACHE_ERROR); 545 - 546 - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 547 - nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) & ~1); 548 - nv_wr32(priv, NV03_PFIFO_CACHE1_GET, get + 4); 549 - nv_wr32(priv, NV03_PFIFO_CACHE1_PUSH0, 550 - nv_rd32(priv, NV03_PFIFO_CACHE1_PUSH0) | 1); 551 - nv_wr32(priv, NV04_PFIFO_CACHE1_HASH, 0); 552 - 553 - nv_wr32(priv, NV04_PFIFO_CACHE1_DMA_PUSH, 554 - nv_rd32(priv, NV04_PFIFO_CACHE1_DMA_PUSH) | 1); 555 - nv_wr32(priv, NV04_PFIFO_CACHE1_PULL0, 1); 556 - 419 + nv04_fifo_cache_error(device, priv, chid, get); 557 420 status &= ~NV_PFIFO_INTR_CACHE_ERROR; 558 421 } 559 422 560 423 if (status & NV_PFIFO_INTR_DMA_PUSHER) { 561 - u32 dma_get = nv_rd32(priv, 0x003244); 562 - u32 dma_put = nv_rd32(priv, 0x003240); 563 - u32 push = nv_rd32(priv, 0x003220); 564 - u32 state = nv_rd32(priv, 0x003228); 565 - 566 - if (device->card_type == NV_50) { 567 - u32 ho_get = nv_rd32(priv, 0x003328); 568 - u32 ho_put = nv_rd32(priv, 0x003320); 569 - u32 ib_get = nv_rd32(priv, 0x003334); 570 - u32 ib_put = nv_rd32(priv, 0x003330); 571 - 572 - nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%02x%08x " 573 - "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x " 574 - "State 0x%08x (err: %s) Push 0x%08x\n", 575 - chid, ho_get, dma_get, ho_put, 576 - dma_put, ib_get, ib_put, state, 577 - nv_dma_state_err(state), 578 - push); 579 - 580 - /* METHOD_COUNT, in DMA_STATE on earlier chipsets */ 581 - nv_wr32(priv, 0x003364, 0x00000000); 582 - if (dma_get != dma_put || ho_get != ho_put) { 583 - nv_wr32(priv, 0x003244, dma_put); 584 - nv_wr32(priv, 0x003328, ho_put); 585 - } else 586 - if (ib_get != ib_put) { 587 - nv_wr32(priv, 0x003334, ib_put); 588 - } 589 - } else { 590 - nv_error(priv, "DMA_PUSHER - Ch %d Get 0x%08x " 591 - "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n", 592 - chid, dma_get, dma_put, state, 593 - nv_dma_state_err(state), push); 594 - 595 - if (dma_get != dma_put) 596 - nv_wr32(priv, 0x003244, dma_put); 597 - } 598 - 599 - nv_wr32(priv, 0x003228, 0x00000000); 600 - nv_wr32(priv, 0x003220, 0x00000001); 601 - nv_wr32(priv, 0x002100, NV_PFIFO_INTR_DMA_PUSHER); 424 + nv04_fifo_dma_pusher(device, priv, chid); 602 425 status &= ~NV_PFIFO_INTR_DMA_PUSHER; 603 426 } 604 427 ··· 536 527 if (status & 0x00000010) { 537 528 status &= ~0x00000010; 538 529 nv_wr32(priv, 0x002100, 0x00000010); 530 + } 531 + 532 + if (status & 0x40000000) { 533 + nouveau_event_trigger(priv->base.uevent, 0); 534 + nv_wr32(priv, 0x002100, 0x40000000); 535 + status &= ~0x40000000; 539 536 } 540 537 } 541 538
+3 -2
drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c
··· 129 129 /* do the kickoff... */ 130 130 nv_wr32(priv, 0x0032fc, nv_gpuobj(base)->addr >> 12); 131 131 if (!nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff)) { 132 - nv_error(priv, "channel %d unload timeout\n", chan->base.chid); 132 + nv_error(priv, "channel %d [%s] unload timeout\n", 133 + chan->base.chid, nouveau_client_name(chan)); 133 134 if (suspend) 134 135 ret = -EBUSY; 135 136 } ··· 481 480 nv_wr32(priv, 0x002044, 0x01003fff); 482 481 483 482 nv_wr32(priv, 0x002100, 0xffffffff); 484 - nv_wr32(priv, 0x002140, 0xffffffff); 483 + nv_wr32(priv, 0x002140, 0xbfffffff); 485 484 486 485 for (i = 0; i < 128; i++) 487 486 nv_wr32(priv, 0x002600 + (i * 4), 0x00000000);
+21 -1
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
··· 26 26 #include <core/client.h> 27 27 #include <core/engctx.h> 28 28 #include <core/ramht.h> 29 + #include <core/event.h> 29 30 #include <core/class.h> 30 31 #include <core/math.h> 31 32 ··· 101 100 done = nv_wait_ne(priv, 0x0032fc, 0xffffffff, 0xffffffff); 102 101 nv_wr32(priv, 0x002520, save); 103 102 if (!done) { 104 - nv_error(priv, "channel %d unload timeout\n", chan->base.chid); 103 + nv_error(priv, "channel %d [%s] unload timeout\n", 104 + chan->base.chid, nouveau_client_name(chan)); 105 105 if (suspend) 106 106 return -EBUSY; 107 107 } ··· 380 378 * PFIFO engine 381 379 ******************************************************************************/ 382 380 381 + static void 382 + nv84_fifo_uevent_enable(struct nouveau_event *event, int index) 383 + { 384 + struct nv84_fifo_priv *priv = event->priv; 385 + nv_mask(priv, 0x002140, 0x40000000, 0x40000000); 386 + } 387 + 388 + static void 389 + nv84_fifo_uevent_disable(struct nouveau_event *event, int index) 390 + { 391 + struct nv84_fifo_priv *priv = event->priv; 392 + nv_mask(priv, 0x002140, 0x40000000, 0x00000000); 393 + } 394 + 383 395 static int 384 396 nv84_fifo_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 385 397 struct nouveau_oclass *oclass, void *data, u32 size, ··· 416 400 &priv->playlist[1]); 417 401 if (ret) 418 402 return ret; 403 + 404 + priv->base.uevent->enable = nv84_fifo_uevent_enable; 405 + priv->base.uevent->disable = nv84_fifo_uevent_disable; 406 + priv->base.uevent->priv = priv; 419 407 420 408 nv_subdev(priv)->unit = 0x00000100; 421 409 nv_subdev(priv)->intr = nv04_fifo_intr;
+88 -21
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
··· 27 27 #include <core/namedb.h> 28 28 #include <core/gpuobj.h> 29 29 #include <core/engctx.h> 30 + #include <core/event.h> 30 31 #include <core/class.h> 31 32 #include <core/math.h> 32 33 #include <core/enum.h> ··· 150 149 151 150 nv_wr32(priv, 0x002634, chan->base.chid); 152 151 if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { 153 - nv_error(priv, "channel %d kick timeout\n", chan->base.chid); 152 + nv_error(priv, "channel %d [%s] kick timeout\n", 153 + chan->base.chid, nouveau_client_name(chan)); 154 154 if (suspend) 155 155 return -EBUSY; 156 156 } ··· 335 333 ******************************************************************************/ 336 334 337 335 static const struct nouveau_enum nvc0_fifo_fault_unit[] = { 338 - { 0x00, "PGRAPH" }, 336 + { 0x00, "PGRAPH", NULL, NVDEV_ENGINE_GR }, 339 337 { 0x03, "PEEPHOLE" }, 340 338 { 0x04, "BAR1" }, 341 339 { 0x05, "BAR3" }, 342 - { 0x07, "PFIFO" }, 343 - { 0x10, "PBSP" }, 344 - { 0x11, "PPPP" }, 340 + { 0x07, "PFIFO", NULL, NVDEV_ENGINE_FIFO }, 341 + { 0x10, "PBSP", NULL, NVDEV_ENGINE_BSP }, 342 + { 0x11, "PPPP", NULL, NVDEV_ENGINE_PPP }, 345 343 { 0x13, "PCOUNTER" }, 346 - { 0x14, "PVP" }, 347 - { 0x15, "PCOPY0" }, 348 - { 0x16, "PCOPY1" }, 344 + { 0x14, "PVP", NULL, NVDEV_ENGINE_VP }, 345 + { 0x15, "PCOPY0", NULL, NVDEV_ENGINE_COPY0 }, 346 + { 0x16, "PCOPY1", NULL, NVDEV_ENGINE_COPY1 }, 349 347 { 0x17, "PDAEMON" }, 350 348 {} 351 349 }; ··· 404 402 u32 vahi = nv_rd32(priv, 0x002808 + (unit * 0x10)); 405 403 u32 stat = nv_rd32(priv, 0x00280c + (unit * 0x10)); 406 404 u32 client = (stat & 0x00001f00) >> 8; 405 + const struct nouveau_enum *en; 406 + struct nouveau_engine *engine; 407 + struct nouveau_object *engctx = NULL; 407 408 408 409 switch (unit) { 409 410 case 3: /* PEEPHOLE */ ··· 425 420 nv_error(priv, "%s fault at 0x%010llx [", (stat & 0x00000080) ? 426 421 "write" : "read", (u64)vahi << 32 | valo); 427 422 nouveau_enum_print(nvc0_fifo_fault_reason, stat & 0x0000000f); 428 - printk("] from "); 429 - nouveau_enum_print(nvc0_fifo_fault_unit, unit); 423 + pr_cont("] from "); 424 + en = nouveau_enum_print(nvc0_fifo_fault_unit, unit); 430 425 if (stat & 0x00000040) { 431 - printk("/"); 426 + pr_cont("/"); 432 427 nouveau_enum_print(nvc0_fifo_fault_hubclient, client); 433 428 } else { 434 - printk("/GPC%d/", (stat & 0x1f000000) >> 24); 429 + pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); 435 430 nouveau_enum_print(nvc0_fifo_fault_gpcclient, client); 436 431 } 437 - printk(" on channel 0x%010llx\n", (u64)inst << 12); 432 + 433 + if (en && en->data2) { 434 + engine = nouveau_engine(priv, en->data2); 435 + if (engine) 436 + engctx = nouveau_engctx_get(engine, inst); 437 + 438 + } 439 + pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, 440 + nouveau_client_name(engctx)); 441 + 442 + nouveau_engctx_put(engctx); 438 443 } 439 444 440 445 static int ··· 499 484 if (show) { 500 485 nv_error(priv, "SUBFIFO%d:", unit); 501 486 nouveau_bitfield_print(nvc0_fifo_subfifo_intr, show); 502 - printk("\n"); 503 - nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " 504 - "data 0x%08x\n", 505 - unit, chid, subc, mthd, data); 487 + pr_cont("\n"); 488 + nv_error(priv, 489 + "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", 490 + unit, chid, 491 + nouveau_client_name_for_fifo_chid(&priv->base, chid), 492 + subc, mthd, data); 506 493 } 507 494 508 495 nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); ··· 518 501 u32 mask = nv_rd32(priv, 0x002140); 519 502 u32 stat = nv_rd32(priv, 0x002100) & mask; 520 503 504 + if (stat & 0x00000001) { 505 + u32 intr = nv_rd32(priv, 0x00252c); 506 + nv_warn(priv, "INTR 0x00000001: 0x%08x\n", intr); 507 + nv_wr32(priv, 0x002100, 0x00000001); 508 + stat &= ~0x00000001; 509 + } 510 + 521 511 if (stat & 0x00000100) { 522 - nv_warn(priv, "unknown status 0x00000100\n"); 512 + u32 intr = nv_rd32(priv, 0x00254c); 513 + nv_warn(priv, "INTR 0x00000100: 0x%08x\n", intr); 523 514 nv_wr32(priv, 0x002100, 0x00000100); 524 515 stat &= ~0x00000100; 516 + } 517 + 518 + if (stat & 0x00010000) { 519 + u32 intr = nv_rd32(priv, 0x00256c); 520 + nv_warn(priv, "INTR 0x00010000: 0x%08x\n", intr); 521 + nv_wr32(priv, 0x002100, 0x00010000); 522 + stat &= ~0x00010000; 523 + } 524 + 525 + if (stat & 0x01000000) { 526 + u32 intr = nv_rd32(priv, 0x00258c); 527 + nv_warn(priv, "INTR 0x01000000: 0x%08x\n", intr); 528 + nv_wr32(priv, 0x002100, 0x01000000); 529 + stat &= ~0x01000000; 525 530 } 526 531 527 532 if (stat & 0x10000000) { ··· 575 536 } 576 537 577 538 if (stat & 0x40000000) { 578 - nv_warn(priv, "unknown status 0x40000000\n"); 579 - nv_mask(priv, 0x002a00, 0x00000000, 0x00000000); 539 + u32 intr0 = nv_rd32(priv, 0x0025a4); 540 + u32 intr1 = nv_mask(priv, 0x002a00, 0x00000000, 0x00000); 541 + nv_debug(priv, "INTR 0x40000000: 0x%08x 0x%08x\n", 542 + intr0, intr1); 580 543 stat &= ~0x40000000; 544 + } 545 + 546 + if (stat & 0x80000000) { 547 + u32 intr = nv_mask(priv, 0x0025a8, 0x00000000, 0x00000000); 548 + nouveau_event_trigger(priv->base.uevent, 0); 549 + nv_debug(priv, "INTR 0x80000000: 0x%08x\n", intr); 550 + stat &= ~0x80000000; 581 551 } 582 552 583 553 if (stat) { ··· 594 546 nv_wr32(priv, 0x002100, stat); 595 547 nv_wr32(priv, 0x002140, 0); 596 548 } 549 + } 550 + 551 + static void 552 + nvc0_fifo_uevent_enable(struct nouveau_event *event, int index) 553 + { 554 + struct nvc0_fifo_priv *priv = event->priv; 555 + nv_mask(priv, 0x002140, 0x80000000, 0x80000000); 556 + } 557 + 558 + static void 559 + nvc0_fifo_uevent_disable(struct nouveau_event *event, int index) 560 + { 561 + struct nvc0_fifo_priv *priv = event->priv; 562 + nv_mask(priv, 0x002140, 0x80000000, 0x00000000); 597 563 } 598 564 599 565 static int ··· 642 580 &priv->user.bar); 643 581 if (ret) 644 582 return ret; 583 + 584 + priv->base.uevent->enable = nvc0_fifo_uevent_enable; 585 + priv->base.uevent->disable = nvc0_fifo_uevent_disable; 586 + priv->base.uevent->priv = priv; 645 587 646 588 nv_subdev(priv)->unit = 0x00000100; 647 589 nv_subdev(priv)->intr = nvc0_fifo_intr; ··· 705 639 706 640 nv_wr32(priv, 0x002a00, 0xffffffff); /* clears PFIFO.INTR bit 30 */ 707 641 nv_wr32(priv, 0x002100, 0xffffffff); 708 - nv_wr32(priv, 0x002140, 0xbfffffff); 642 + nv_wr32(priv, 0x002140, 0x3fffffff); 643 + nv_wr32(priv, 0x002628, 0x00000001); /* makes mthd 0x20 work */ 709 644 return 0; 710 645 } 711 646
+53 -11
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
··· 27 27 #include <core/namedb.h> 28 28 #include <core/gpuobj.h> 29 29 #include <core/engctx.h> 30 + #include <core/event.h> 30 31 #include <core/class.h> 31 32 #include <core/math.h> 32 33 #include <core/enum.h> ··· 185 184 186 185 nv_wr32(priv, 0x002634, chan->base.chid); 187 186 if (!nv_wait(priv, 0x002634, 0xffffffff, chan->base.chid)) { 188 - nv_error(priv, "channel %d kick timeout\n", chan->base.chid); 187 + nv_error(priv, "channel %d [%s] kick timeout\n", 188 + chan->base.chid, nouveau_client_name(chan)); 189 189 if (suspend) 190 190 return -EBUSY; 191 191 } ··· 414 412 u32 vahi = nv_rd32(priv, 0x2808 + (unit * 0x10)); 415 413 u32 stat = nv_rd32(priv, 0x280c + (unit * 0x10)); 416 414 u32 client = (stat & 0x00001f00) >> 8; 415 + const struct nouveau_enum *en; 416 + struct nouveau_engine *engine; 417 + struct nouveau_object *engctx = NULL; 417 418 418 419 nv_error(priv, "PFIFO: %s fault at 0x%010llx [", (stat & 0x00000080) ? 419 420 "write" : "read", (u64)vahi << 32 | valo); 420 421 nouveau_enum_print(nve0_fifo_fault_reason, stat & 0x0000000f); 421 - printk("] from "); 422 - nouveau_enum_print(nve0_fifo_fault_unit, unit); 422 + pr_cont("] from "); 423 + en = nouveau_enum_print(nve0_fifo_fault_unit, unit); 423 424 if (stat & 0x00000040) { 424 - printk("/"); 425 + pr_cont("/"); 425 426 nouveau_enum_print(nve0_fifo_fault_hubclient, client); 426 427 } else { 427 - printk("/GPC%d/", (stat & 0x1f000000) >> 24); 428 + pr_cont("/GPC%d/", (stat & 0x1f000000) >> 24); 428 429 nouveau_enum_print(nve0_fifo_fault_gpcclient, client); 429 430 } 430 - printk(" on channel 0x%010llx\n", (u64)inst << 12); 431 + 432 + if (en && en->data2) { 433 + engine = nouveau_engine(priv, en->data2); 434 + if (engine) 435 + engctx = nouveau_engctx_get(engine, inst); 436 + 437 + } 438 + 439 + pr_cont(" on channel 0x%010llx [%s]\n", (u64)inst << 12, 440 + nouveau_client_name(engctx)); 441 + 442 + nouveau_engctx_put(engctx); 431 443 } 432 444 433 445 static int ··· 496 480 if (show) { 497 481 nv_error(priv, "SUBFIFO%d:", unit); 498 482 nouveau_bitfield_print(nve0_fifo_subfifo_intr, show); 499 - printk("\n"); 500 - nv_error(priv, "SUBFIFO%d: ch %d subc %d mthd 0x%04x " 501 - "data 0x%08x\n", 502 - unit, chid, subc, mthd, data); 483 + pr_cont("\n"); 484 + nv_error(priv, 485 + "SUBFIFO%d: ch %d [%s] subc %d mthd 0x%04x data 0x%08x\n", 486 + unit, chid, 487 + nouveau_client_name_for_fifo_chid(&priv->base, chid), 488 + subc, mthd, data); 503 489 } 504 490 505 491 nv_wr32(priv, 0x0400c0 + (unit * 0x2000), 0x80600008); ··· 555 537 stat &= ~0x40000000; 556 538 } 557 539 540 + if (stat & 0x80000000) { 541 + nouveau_event_trigger(priv->base.uevent, 0); 542 + nv_wr32(priv, 0x002100, 0x80000000); 543 + stat &= ~0x80000000; 544 + } 545 + 558 546 if (stat) { 559 547 nv_fatal(priv, "unhandled status 0x%08x\n", stat); 560 548 nv_wr32(priv, 0x002100, stat); 561 549 nv_wr32(priv, 0x002140, 0); 562 550 } 551 + } 552 + 553 + static void 554 + nve0_fifo_uevent_enable(struct nouveau_event *event, int index) 555 + { 556 + struct nve0_fifo_priv *priv = event->priv; 557 + nv_mask(priv, 0x002140, 0x80000000, 0x80000000); 558 + } 559 + 560 + static void 561 + nve0_fifo_uevent_disable(struct nouveau_event *event, int index) 562 + { 563 + struct nve0_fifo_priv *priv = event->priv; 564 + nv_mask(priv, 0x002140, 0x80000000, 0x00000000); 563 565 } 564 566 565 567 static int ··· 604 566 &priv->user.bar); 605 567 if (ret) 606 568 return ret; 569 + 570 + priv->base.uevent->enable = nve0_fifo_uevent_enable; 571 + priv->base.uevent->disable = nve0_fifo_uevent_disable; 572 + priv->base.uevent->priv = priv; 607 573 608 574 nv_subdev(priv)->unit = 0x00000100; 609 575 nv_subdev(priv)->intr = nve0_fifo_intr; ··· 659 617 660 618 nv_wr32(priv, 0x002a00, 0xffffffff); 661 619 nv_wr32(priv, 0x002100, 0xffffffff); 662 - nv_wr32(priv, 0x002140, 0xbfffffff); 620 + nv_wr32(priv, 0x002140, 0x3fffffff); 663 621 return 0; 664 622 } 665 623
+9 -7
drivers/gpu/drm/nouveau/core/engine/graph/nv04.c
··· 22 22 * DEALINGS IN THE SOFTWARE. 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/os.h> 26 27 #include <core/class.h> 27 28 #include <core/handle.h> ··· 1298 1297 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 1299 1298 1300 1299 if (show) { 1301 - nv_error(priv, ""); 1300 + nv_error(priv, "%s", ""); 1302 1301 nouveau_bitfield_print(nv04_graph_intr_name, show); 1303 - printk(" nsource:"); 1302 + pr_cont(" nsource:"); 1304 1303 nouveau_bitfield_print(nv04_graph_nsource, nsource); 1305 - printk(" nstatus:"); 1304 + pr_cont(" nstatus:"); 1306 1305 nouveau_bitfield_print(nv04_graph_nstatus, nstatus); 1307 - printk("\n"); 1308 - nv_error(priv, "ch %d/%d class 0x%04x " 1309 - "mthd 0x%04x data 0x%08x\n", 1310 - chid, subc, class, mthd, data); 1306 + pr_cont("\n"); 1307 + nv_error(priv, 1308 + "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 1309 + chid, nouveau_client_name(chan), subc, class, mthd, 1310 + data); 1311 1311 } 1312 1312 1313 1313 nouveau_namedb_put(handle);
+9 -7
drivers/gpu/drm/nouveau/core/engine/graph/nv10.c
··· 22 22 * DEALINGS IN THE SOFTWARE. 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/os.h> 26 27 #include <core/class.h> 27 28 #include <core/handle.h> ··· 1194 1193 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 1195 1194 1196 1195 if (show) { 1197 - nv_error(priv, ""); 1196 + nv_error(priv, "%s", ""); 1198 1197 nouveau_bitfield_print(nv10_graph_intr_name, show); 1199 - printk(" nsource:"); 1198 + pr_cont(" nsource:"); 1200 1199 nouveau_bitfield_print(nv04_graph_nsource, nsource); 1201 - printk(" nstatus:"); 1200 + pr_cont(" nstatus:"); 1202 1201 nouveau_bitfield_print(nv10_graph_nstatus, nstatus); 1203 - printk("\n"); 1204 - nv_error(priv, "ch %d/%d class 0x%04x " 1205 - "mthd 0x%04x data 0x%08x\n", 1206 - chid, subc, class, mthd, data); 1202 + pr_cont("\n"); 1203 + nv_error(priv, 1204 + "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 1205 + chid, nouveau_client_name(chan), subc, class, mthd, 1206 + data); 1207 1207 } 1208 1208 1209 1209 nouveau_namedb_put(handle);
+9 -6
drivers/gpu/drm/nouveau/core/engine/graph/nv20.c
··· 1 + #include <core/client.h> 1 2 #include <core/os.h> 2 3 #include <core/class.h> 3 4 #include <core/engctx.h> ··· 225 224 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 226 225 227 226 if (show) { 228 - nv_error(priv, ""); 227 + nv_error(priv, "%s", ""); 229 228 nouveau_bitfield_print(nv10_graph_intr_name, show); 230 - printk(" nsource:"); 229 + pr_cont(" nsource:"); 231 230 nouveau_bitfield_print(nv04_graph_nsource, nsource); 232 - printk(" nstatus:"); 231 + pr_cont(" nstatus:"); 233 232 nouveau_bitfield_print(nv10_graph_nstatus, nstatus); 234 - printk("\n"); 235 - nv_error(priv, "ch %d/%d class 0x%04x mthd 0x%04x data 0x%08x\n", 236 - chid, subc, class, mthd, data); 233 + pr_cont("\n"); 234 + nv_error(priv, 235 + "ch %d [%s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 236 + chid, nouveau_client_name(engctx), subc, class, mthd, 237 + data); 237 238 } 238 239 239 240 nouveau_engctx_put(engctx);
+9 -7
drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/os.h> 26 27 #include <core/class.h> 27 28 #include <core/handle.h> ··· 322 321 nv_wr32(priv, NV04_PGRAPH_FIFO, 0x00000001); 323 322 324 323 if (show) { 325 - nv_error(priv, ""); 324 + nv_error(priv, "%s", ""); 326 325 nouveau_bitfield_print(nv10_graph_intr_name, show); 327 - printk(" nsource:"); 326 + pr_cont(" nsource:"); 328 327 nouveau_bitfield_print(nv04_graph_nsource, nsource); 329 - printk(" nstatus:"); 328 + pr_cont(" nstatus:"); 330 329 nouveau_bitfield_print(nv10_graph_nstatus, nstatus); 331 - printk("\n"); 332 - nv_error(priv, "ch %d [0x%08x] subc %d class 0x%04x " 333 - "mthd 0x%04x data 0x%08x\n", 334 - chid, inst << 4, subc, class, mthd, data); 330 + pr_cont("\n"); 331 + nv_error(priv, 332 + "ch %d [0x%08x %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 333 + chid, inst << 4, nouveau_client_name(engctx), subc, 334 + class, mthd, data); 335 335 } 336 336 337 337 nouveau_engctx_put(engctx);
+27 -26
drivers/gpu/drm/nouveau/core/engine/graph/nv50.c
··· 24 24 25 25 #include <core/os.h> 26 26 #include <core/class.h> 27 + #include <core/client.h> 27 28 #include <core/handle.h> 28 29 #include <core/engctx.h> 29 30 #include <core/enum.h> ··· 419 418 nv_error(priv, "TRAP_MP_EXEC - " 420 419 "TP %d MP %d: ", tpid, i); 421 420 nouveau_enum_print(nv50_mp_exec_error_names, status); 422 - printk(" at %06x warp %d, opcode %08x %08x\n", 421 + pr_cont(" at %06x warp %d, opcode %08x %08x\n", 423 422 pc&0xffffff, pc >> 24, 424 423 oplow, ophigh); 425 424 } ··· 533 532 534 533 static int 535 534 nv50_graph_trap_handler(struct nv50_graph_priv *priv, u32 display, 536 - int chid, u64 inst) 535 + int chid, u64 inst, struct nouveau_object *engctx) 537 536 { 538 537 u32 status = nv_rd32(priv, 0x400108); 539 538 u32 ustatus; ··· 566 565 567 566 nv_error(priv, "TRAP DISPATCH_FAULT\n"); 568 567 if (display && (addr & 0x80000000)) { 569 - nv_error(priv, "ch %d [0x%010llx] " 570 - "subc %d class 0x%04x mthd 0x%04x " 571 - "data 0x%08x%08x " 572 - "400808 0x%08x 400848 0x%08x\n", 573 - chid, inst, subc, class, mthd, datah, 574 - datal, addr, r848); 568 + nv_error(priv, 569 + "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x%08x 400808 0x%08x 400848 0x%08x\n", 570 + chid, inst, 571 + nouveau_client_name(engctx), subc, 572 + class, mthd, datah, datal, addr, r848); 575 573 } else 576 574 if (display) { 577 575 nv_error(priv, "no stuck command?\n"); ··· 591 591 592 592 nv_error(priv, "TRAP DISPATCH_QUERY\n"); 593 593 if (display && (addr & 0x80000000)) { 594 - nv_error(priv, "ch %d [0x%010llx] " 595 - "subc %d class 0x%04x mthd 0x%04x " 596 - "data 0x%08x 40084c 0x%08x\n", 597 - chid, inst, subc, class, mthd, 598 - data, addr); 594 + nv_error(priv, 595 + "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x 40084c 0x%08x\n", 596 + chid, inst, 597 + nouveau_client_name(engctx), subc, 598 + class, mthd, data, addr); 599 599 } else 600 600 if (display) { 601 601 nv_error(priv, "no stuck command?\n"); ··· 623 623 if (display) { 624 624 nv_error(priv, "TRAP_M2MF"); 625 625 nouveau_bitfield_print(nv50_graph_trap_m2mf, ustatus); 626 - printk("\n"); 626 + pr_cont("\n"); 627 627 nv_error(priv, "TRAP_M2MF %08x %08x %08x %08x\n", 628 628 nv_rd32(priv, 0x406804), nv_rd32(priv, 0x406808), 629 629 nv_rd32(priv, 0x40680c), nv_rd32(priv, 0x406810)); ··· 644 644 if (display) { 645 645 nv_error(priv, "TRAP_VFETCH"); 646 646 nouveau_bitfield_print(nv50_graph_trap_vfetch, ustatus); 647 - printk("\n"); 647 + pr_cont("\n"); 648 648 nv_error(priv, "TRAP_VFETCH %08x %08x %08x %08x\n", 649 649 nv_rd32(priv, 0x400c00), nv_rd32(priv, 0x400c08), 650 650 nv_rd32(priv, 0x400c0c), nv_rd32(priv, 0x400c10)); ··· 661 661 if (display) { 662 662 nv_error(priv, "TRAP_STRMOUT"); 663 663 nouveau_bitfield_print(nv50_graph_trap_strmout, ustatus); 664 - printk("\n"); 664 + pr_cont("\n"); 665 665 nv_error(priv, "TRAP_STRMOUT %08x %08x %08x %08x\n", 666 666 nv_rd32(priv, 0x401804), nv_rd32(priv, 0x401808), 667 667 nv_rd32(priv, 0x40180c), nv_rd32(priv, 0x401810)); ··· 682 682 if (display) { 683 683 nv_error(priv, "TRAP_CCACHE"); 684 684 nouveau_bitfield_print(nv50_graph_trap_ccache, ustatus); 685 - printk("\n"); 685 + pr_cont("\n"); 686 686 nv_error(priv, "TRAP_CCACHE %08x %08x %08x %08x" 687 687 " %08x %08x %08x\n", 688 688 nv_rd32(priv, 0x405000), nv_rd32(priv, 0x405004), ··· 774 774 u32 ecode = nv_rd32(priv, 0x400110); 775 775 nv_error(priv, "DATA_ERROR "); 776 776 nouveau_enum_print(nv50_data_error_names, ecode); 777 - printk("\n"); 777 + pr_cont("\n"); 778 778 } 779 779 780 780 if (stat & 0x00200000) { 781 - if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12)) 781 + if (!nv50_graph_trap_handler(priv, show, chid, (u64)inst << 12, 782 + engctx)) 782 783 show &= ~0x00200000; 783 784 } 784 785 ··· 787 786 nv_wr32(priv, 0x400500, 0x00010001); 788 787 789 788 if (show) { 790 - nv_error(priv, ""); 789 + nv_error(priv, "%s", ""); 791 790 nouveau_bitfield_print(nv50_graph_intr_name, show); 792 - printk("\n"); 793 - nv_error(priv, "ch %d [0x%010llx] subc %d class 0x%04x " 794 - "mthd 0x%04x data 0x%08x\n", 795 - chid, (u64)inst << 12, subc, class, mthd, data); 791 + pr_cont("\n"); 792 + nv_error(priv, 793 + "ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 794 + chid, (u64)inst << 12, nouveau_client_name(engctx), 795 + subc, class, mthd, data); 796 796 } 797 797 798 798 if (nv_rd32(priv, 0x400824) & (1 << 31)) ··· 909 907 nv_wr32(priv, 0x400828, 0x00000000); 910 908 nv_wr32(priv, 0x40082c, 0x00000000); 911 909 nv_wr32(priv, 0x400830, 0x00000000); 912 - nv_wr32(priv, 0x400724, 0x00000000); 913 910 nv_wr32(priv, 0x40032c, 0x00000000); 914 - nv_wr32(priv, 0x400320, 4); /* CTXCTL_CMD = NEWCTXDMA */ 911 + nv_wr32(priv, 0x400330, 0x00000000); 915 912 916 913 /* some unknown zcull magic */ 917 914 switch (nv_device(priv)->chipset & 0xf0) {
+16 -17
drivers/gpu/drm/nouveau/core/engine/graph/nvc0.c
··· 433 433 if (stat & 0x00000010) { 434 434 handle = nouveau_handle_get_class(engctx, class); 435 435 if (!handle || nv_call(handle->object, mthd, data)) { 436 - nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " 437 - "subc %d class 0x%04x mthd 0x%04x " 438 - "data 0x%08x\n", 439 - chid, inst << 12, subc, class, mthd, data); 436 + nv_error(priv, 437 + "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 438 + chid, inst << 12, nouveau_client_name(engctx), 439 + subc, class, mthd, data); 440 440 } 441 441 nouveau_handle_put(handle); 442 442 nv_wr32(priv, 0x400100, 0x00000010); ··· 444 444 } 445 445 446 446 if (stat & 0x00000020) { 447 - nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " 448 - "class 0x%04x mthd 0x%04x data 0x%08x\n", 449 - chid, inst << 12, subc, class, mthd, data); 447 + nv_error(priv, 448 + "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 449 + chid, inst << 12, nouveau_client_name(engctx), subc, 450 + class, mthd, data); 450 451 nv_wr32(priv, 0x400100, 0x00000020); 451 452 stat &= ~0x00000020; 452 453 } ··· 455 454 if (stat & 0x00100000) { 456 455 nv_error(priv, "DATA_ERROR ["); 457 456 nouveau_enum_print(nv50_data_error_names, code); 458 - printk("] ch %d [0x%010llx] subc %d class 0x%04x " 459 - "mthd 0x%04x data 0x%08x\n", 460 - chid, inst << 12, subc, class, mthd, data); 457 + pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 458 + chid, inst << 12, nouveau_client_name(engctx), subc, 459 + class, mthd, data); 461 460 nv_wr32(priv, 0x400100, 0x00100000); 462 461 stat &= ~0x00100000; 463 462 } 464 463 465 464 if (stat & 0x00200000) { 466 - nv_error(priv, "TRAP ch %d [0x%010llx]\n", chid, inst << 12); 465 + nv_error(priv, "TRAP ch %d [0x%010llx %s]\n", chid, inst << 12, 466 + nouveau_client_name(engctx)); 467 467 nvc0_graph_trap_intr(priv); 468 468 nv_wr32(priv, 0x400100, 0x00200000); 469 469 stat &= ~0x00200000; ··· 613 611 static void 614 612 nvc0_graph_dtor_fw(struct nvc0_graph_fuc *fuc) 615 613 { 616 - if (fuc->data) { 617 - kfree(fuc->data); 618 - fuc->data = NULL; 619 - } 614 + kfree(fuc->data); 615 + fuc->data = NULL; 620 616 } 621 617 622 618 void ··· 622 622 { 623 623 struct nvc0_graph_priv *priv = (void *)object; 624 624 625 - if (priv->data) 626 - kfree(priv->data); 625 + kfree(priv->data); 627 626 628 627 nvc0_graph_dtor_fw(&priv->fuc409c); 629 628 nvc0_graph_dtor_fw(&priv->fuc409d);
+24 -20
drivers/gpu/drm/nouveau/core/engine/graph/nve0.c
··· 78 78 } 79 79 80 80 static void 81 - nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst) 81 + nve0_graph_trap_isr(struct nvc0_graph_priv *priv, int chid, u64 inst, 82 + struct nouveau_object *engctx) 82 83 { 83 84 u32 trap = nv_rd32(priv, 0x400108); 84 85 int rop; 85 86 86 87 if (trap & 0x00000001) { 87 88 u32 stat = nv_rd32(priv, 0x404000); 88 - nv_error(priv, "DISPATCH ch %d [0x%010llx] 0x%08x\n", 89 - chid, inst, stat); 89 + nv_error(priv, "DISPATCH ch %d [0x%010llx %s] 0x%08x\n", 90 + chid, inst, nouveau_client_name(engctx), stat); 90 91 nv_wr32(priv, 0x404000, 0xc0000000); 91 92 nv_wr32(priv, 0x400108, 0x00000001); 92 93 trap &= ~0x00000001; ··· 95 94 96 95 if (trap & 0x00000010) { 97 96 u32 stat = nv_rd32(priv, 0x405840); 98 - nv_error(priv, "SHADER ch %d [0x%010llx] 0x%08x\n", 99 - chid, inst, stat); 97 + nv_error(priv, "SHADER ch %d [0x%010llx %s] 0x%08x\n", 98 + chid, inst, nouveau_client_name(engctx), stat); 100 99 nv_wr32(priv, 0x405840, 0xc0000000); 101 100 nv_wr32(priv, 0x400108, 0x00000010); 102 101 trap &= ~0x00000010; ··· 106 105 for (rop = 0; rop < priv->rop_nr; rop++) { 107 106 u32 statz = nv_rd32(priv, ROP_UNIT(rop, 0x070)); 108 107 u32 statc = nv_rd32(priv, ROP_UNIT(rop, 0x144)); 109 - nv_error(priv, "ROP%d ch %d [0x%010llx] 0x%08x 0x%08x\n", 110 - rop, chid, inst, statz, statc); 108 + nv_error(priv, 109 + "ROP%d ch %d [0x%010llx %s] 0x%08x 0x%08x\n", 110 + rop, chid, inst, nouveau_client_name(engctx), 111 + statz, statc); 111 112 nv_wr32(priv, ROP_UNIT(rop, 0x070), 0xc0000000); 112 113 nv_wr32(priv, ROP_UNIT(rop, 0x144), 0xc0000000); 113 114 } ··· 118 115 } 119 116 120 117 if (trap) { 121 - nv_error(priv, "TRAP ch %d [0x%010llx] 0x%08x\n", 122 - chid, inst, trap); 118 + nv_error(priv, "TRAP ch %d [0x%010llx %s] 0x%08x\n", 119 + chid, inst, nouveau_client_name(engctx), trap); 123 120 nv_wr32(priv, 0x400108, trap); 124 121 } 125 122 } ··· 148 145 if (stat & 0x00000010) { 149 146 handle = nouveau_handle_get_class(engctx, class); 150 147 if (!handle || nv_call(handle->object, mthd, data)) { 151 - nv_error(priv, "ILLEGAL_MTHD ch %d [0x%010llx] " 152 - "subc %d class 0x%04x mthd 0x%04x " 153 - "data 0x%08x\n", 154 - chid, inst, subc, class, mthd, data); 148 + nv_error(priv, 149 + "ILLEGAL_MTHD ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 150 + chid, inst, nouveau_client_name(engctx), subc, 151 + class, mthd, data); 155 152 } 156 153 nouveau_handle_put(handle); 157 154 nv_wr32(priv, 0x400100, 0x00000010); ··· 159 156 } 160 157 161 158 if (stat & 0x00000020) { 162 - nv_error(priv, "ILLEGAL_CLASS ch %d [0x%010llx] subc %d " 163 - "class 0x%04x mthd 0x%04x data 0x%08x\n", 164 - chid, inst, subc, class, mthd, data); 159 + nv_error(priv, 160 + "ILLEGAL_CLASS ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 161 + chid, inst, nouveau_client_name(engctx), subc, class, 162 + mthd, data); 165 163 nv_wr32(priv, 0x400100, 0x00000020); 166 164 stat &= ~0x00000020; 167 165 } ··· 170 166 if (stat & 0x00100000) { 171 167 nv_error(priv, "DATA_ERROR ["); 172 168 nouveau_enum_print(nv50_data_error_names, code); 173 - printk("] ch %d [0x%010llx] subc %d class 0x%04x " 174 - "mthd 0x%04x data 0x%08x\n", 175 - chid, inst, subc, class, mthd, data); 169 + pr_cont("] ch %d [0x%010llx %s] subc %d class 0x%04x mthd 0x%04x data 0x%08x\n", 170 + chid, inst, nouveau_client_name(engctx), subc, class, 171 + mthd, data); 176 172 nv_wr32(priv, 0x400100, 0x00100000); 177 173 stat &= ~0x00100000; 178 174 } 179 175 180 176 if (stat & 0x00200000) { 181 - nve0_graph_trap_isr(priv, chid, inst); 177 + nve0_graph_trap_isr(priv, chid, inst, engctx); 182 178 nv_wr32(priv, 0x400100, 0x00200000); 183 179 stat &= ~0x00200000; 184 180 }
+5 -2
drivers/gpu/drm/nouveau/core/engine/mpeg/nv31.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 + #include <core/client.h> 25 26 #include <core/os.h> 26 27 #include <core/class.h> 27 28 #include <core/engctx.h> ··· 232 231 nv_wr32(priv, 0x00b230, 0x00000001); 233 232 234 233 if (show) { 235 - nv_error(priv, "ch %d [0x%08x] 0x%08x 0x%08x 0x%08x 0x%08x\n", 236 - chid, inst << 4, stat, type, mthd, data); 234 + nv_error(priv, 235 + "ch %d [0x%08x %s] 0x%08x 0x%08x 0x%08x 0x%08x\n", 236 + chid, inst << 4, nouveau_client_name(engctx), stat, 237 + type, mthd, data); 237 238 } 238 239 239 240 nouveau_engctx_put(engctx);
+30 -10
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
··· 28 28 #include <core/namedb.h> 29 29 #include <core/handle.h> 30 30 #include <core/gpuobj.h> 31 + #include <core/event.h> 32 + 33 + #include <subdev/bar.h> 31 34 32 35 #include <engine/software.h> 33 36 #include <engine/disp.h> ··· 93 90 { 94 91 struct nv50_software_chan *chan = (void *)nv_engctx(object->parent); 95 92 struct nouveau_disp *disp = nouveau_disp(object); 96 - unsigned long flags; 97 93 u32 crtc = *(u32 *)args; 98 - 99 94 if (crtc > 1) 100 95 return -EINVAL; 101 96 102 - disp->vblank.get(disp->vblank.data, crtc); 103 - 104 - spin_lock_irqsave(&disp->vblank.lock, flags); 105 - list_add(&chan->base.vblank.head, &disp->vblank.list); 106 - chan->base.vblank.crtc = crtc; 107 - spin_unlock_irqrestore(&disp->vblank.lock, flags); 97 + nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); 108 98 return 0; 109 99 } 110 100 ··· 132 136 ******************************************************************************/ 133 137 134 138 static int 139 + nv50_software_vblsem_release(struct nouveau_eventh *event, int head) 140 + { 141 + struct nouveau_software_chan *chan = 142 + container_of(event, struct nouveau_software_chan, vblank.event); 143 + struct nv50_software_priv *priv = (void *)nv_object(chan)->engine; 144 + struct nouveau_bar *bar = nouveau_bar(priv); 145 + 146 + nv_wr32(priv, 0x001704, chan->vblank.channel); 147 + nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma); 148 + bar->flush(bar); 149 + 150 + if (nv_device(priv)->chipset == 0x50) { 151 + nv_wr32(priv, 0x001570, chan->vblank.offset); 152 + nv_wr32(priv, 0x001574, chan->vblank.value); 153 + } else { 154 + nv_wr32(priv, 0x060010, chan->vblank.offset); 155 + nv_wr32(priv, 0x060014, chan->vblank.value); 156 + } 157 + 158 + return NVKM_EVENT_DROP; 159 + } 160 + 161 + static int 135 162 nv50_software_context_ctor(struct nouveau_object *parent, 136 163 struct nouveau_object *engine, 137 164 struct nouveau_oclass *oclass, void *data, u32 size, ··· 169 150 return ret; 170 151 171 152 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; 153 + chan->base.vblank.event.func = nv50_software_vblsem_release; 172 154 return 0; 173 155 } 174 156 ··· 190 170 191 171 static int 192 172 nv50_software_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 193 - struct nouveau_oclass *oclass, void *data, u32 size, 194 - struct nouveau_object **pobject) 173 + struct nouveau_oclass *oclass, void *data, u32 size, 174 + struct nouveau_object **pobject) 195 175 { 196 176 struct nv50_software_priv *priv; 197 177 int ret;
+22 -7
drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
··· 25 25 #include <core/os.h> 26 26 #include <core/class.h> 27 27 #include <core/engctx.h> 28 + #include <core/event.h> 29 + 30 + #include <subdev/bar.h> 28 31 29 32 #include <engine/software.h> 30 33 #include <engine/disp.h> ··· 75 72 { 76 73 struct nvc0_software_chan *chan = (void *)nv_engctx(object->parent); 77 74 struct nouveau_disp *disp = nouveau_disp(object); 78 - unsigned long flags; 79 75 u32 crtc = *(u32 *)args; 80 76 81 77 if ((nv_device(object)->card_type < NV_E0 && crtc > 1) || crtc > 3) 82 78 return -EINVAL; 83 79 84 - disp->vblank.get(disp->vblank.data, crtc); 85 - 86 - spin_lock_irqsave(&disp->vblank.lock, flags); 87 - list_add(&chan->base.vblank.head, &disp->vblank.list); 88 - chan->base.vblank.crtc = crtc; 89 - spin_unlock_irqrestore(&disp->vblank.lock, flags); 80 + nouveau_event_get(disp->vblank, crtc, &chan->base.vblank.event); 90 81 return 0; 91 82 } 92 83 ··· 115 118 ******************************************************************************/ 116 119 117 120 static int 121 + nvc0_software_vblsem_release(struct nouveau_eventh *event, int head) 122 + { 123 + struct nouveau_software_chan *chan = 124 + container_of(event, struct nouveau_software_chan, vblank.event); 125 + struct nvc0_software_priv *priv = (void *)nv_object(chan)->engine; 126 + struct nouveau_bar *bar = nouveau_bar(priv); 127 + 128 + nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel); 129 + bar->flush(bar); 130 + nv_wr32(priv, 0x06000c, upper_32_bits(chan->vblank.offset)); 131 + nv_wr32(priv, 0x060010, lower_32_bits(chan->vblank.offset)); 132 + nv_wr32(priv, 0x060014, chan->vblank.value); 133 + 134 + return NVKM_EVENT_DROP; 135 + } 136 + 137 + static int 118 138 nvc0_software_context_ctor(struct nouveau_object *parent, 119 139 struct nouveau_object *engine, 120 140 struct nouveau_oclass *oclass, void *data, u32 size, ··· 146 132 return ret; 147 133 148 134 chan->base.vblank.channel = nv_gpuobj(parent->parent)->addr >> 12; 135 + chan->base.vblank.event.func = nvc0_software_vblsem_release; 149 136 return 0; 150 137 } 151 138
+25 -19
drivers/gpu/drm/nouveau/core/include/core/class.h
··· 154 154 u32 engine; 155 155 }; 156 156 157 + /* 0046: NV04_DISP 158 + */ 159 + 160 + #define NV04_DISP_CLASS 0x00000046 161 + 162 + struct nv04_display_class { 163 + }; 164 + 157 165 /* 5070: NV50_DISP 158 166 * 8270: NV84_DISP 159 167 * 8370: NVA0_DISP ··· 198 190 #define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f 199 191 #define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 200 192 #define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff 201 - #define NV94_DISP_SOR_DP_TRAIN 0x00016000 202 - #define NV94_DISP_SOR_DP_TRAIN_OP 0xf0000000 203 - #define NV94_DISP_SOR_DP_TRAIN_OP_PATTERN 0x00000000 204 - #define NV94_DISP_SOR_DP_TRAIN_OP_INIT 0x10000000 205 - #define NV94_DISP_SOR_DP_TRAIN_OP_FINI 0x20000000 206 - #define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD 0x00000001 207 - #define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF 0x00000000 208 - #define NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON 0x00000001 209 - #define NV94_DISP_SOR_DP_TRAIN_PATTERN 0x00000003 210 - #define NV94_DISP_SOR_DP_TRAIN_PATTERN_DISABLED 0x00000000 211 - #define NV94_DISP_SOR_DP_LNKCTL 0x00016040 212 - #define NV94_DISP_SOR_DP_LNKCTL_FRAME 0x80000000 213 - #define NV94_DISP_SOR_DP_LNKCTL_FRAME_STD 0x00000000 214 - #define NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH 0x80000000 215 - #define NV94_DISP_SOR_DP_LNKCTL_WIDTH 0x00001f00 216 - #define NV94_DISP_SOR_DP_LNKCTL_COUNT 0x00000007 217 - #define NV94_DISP_SOR_DP_DRVCTL(l) ((l) * 0x40 + 0x00016100) 218 - #define NV94_DISP_SOR_DP_DRVCTL_VS 0x00000300 219 - #define NV94_DISP_SOR_DP_DRVCTL_PE 0x00000003 220 193 221 194 #define NV50_DISP_DAC_MTHD 0x00020000 222 195 #define NV50_DISP_DAC_MTHD_TYPE 0x0000f000 ··· 218 229 #define NV50_DISP_DAC_PWR_STATE_OFF 0x00000040 219 230 #define NV50_DISP_DAC_LOAD 0x0002000c 220 231 #define NV50_DISP_DAC_LOAD_VALUE 0x00000007 232 + 233 + #define NV50_DISP_PIOR_MTHD 0x00030000 234 + #define NV50_DISP_PIOR_MTHD_TYPE 0x0000f000 235 + #define NV50_DISP_PIOR_MTHD_OR 0x00000003 236 + 237 + #define NV50_DISP_PIOR_PWR 0x00030000 238 + #define NV50_DISP_PIOR_PWR_STATE 0x00000001 239 + #define NV50_DISP_PIOR_PWR_STATE_ON 0x00000001 240 + #define NV50_DISP_PIOR_PWR_STATE_OFF 0x00000000 241 + #define NV50_DISP_PIOR_TMDS_PWR 0x00032000 242 + #define NV50_DISP_PIOR_TMDS_PWR_STATE 0x00000001 243 + #define NV50_DISP_PIOR_TMDS_PWR_STATE_ON 0x00000001 244 + #define NV50_DISP_PIOR_TMDS_PWR_STATE_OFF 0x00000000 245 + #define NV50_DISP_PIOR_DP_PWR 0x00036000 246 + #define NV50_DISP_PIOR_DP_PWR_STATE 0x00000001 247 + #define NV50_DISP_PIOR_DP_PWR_STATE_ON 0x00000001 248 + #define NV50_DISP_PIOR_DP_PWR_STATE_OFF 0x00000000 221 249 222 250 struct nv50_display_class { 223 251 };
+2 -1
drivers/gpu/drm/nouveau/core/include/core/client.h
··· 7 7 struct nouveau_namedb base; 8 8 struct nouveau_handle *root; 9 9 struct nouveau_object *device; 10 - char name[16]; 10 + char name[32]; 11 11 u32 debug; 12 12 struct nouveau_vm *vm; 13 13 }; ··· 41 41 42 42 int nouveau_client_init(struct nouveau_client *); 43 43 int nouveau_client_fini(struct nouveau_client *, bool suspend); 44 + const char *nouveau_client_name(void *obj); 44 45 45 46 #endif
+1
drivers/gpu/drm/nouveau/core/include/core/device.h
··· 26 26 */ 27 27 NVDEV_SUBDEV_MXM, 28 28 NVDEV_SUBDEV_MC, 29 + NVDEV_SUBDEV_BUS, 29 30 NVDEV_SUBDEV_TIMER, 30 31 NVDEV_SUBDEV_FB, 31 32 NVDEV_SUBDEV_LTCG,
+2 -1
drivers/gpu/drm/nouveau/core/include/core/enum.h
··· 5 5 u32 value; 6 6 const char *name; 7 7 const void *data; 8 + u32 data2; 8 9 }; 9 10 10 11 const struct nouveau_enum * 11 12 nouveau_enum_find(const struct nouveau_enum *, u32 value); 12 13 13 - void 14 + const struct nouveau_enum * 14 15 nouveau_enum_print(const struct nouveau_enum *en, u32 value); 15 16 16 17 struct nouveau_bitfield {
+36
drivers/gpu/drm/nouveau/core/include/core/event.h
··· 1 + #ifndef __NVKM_EVENT_H__ 2 + #define __NVKM_EVENT_H__ 3 + 4 + /* return codes from event handlers */ 5 + #define NVKM_EVENT_DROP 0 6 + #define NVKM_EVENT_KEEP 1 7 + 8 + struct nouveau_eventh { 9 + struct list_head head; 10 + int (*func)(struct nouveau_eventh *, int index); 11 + }; 12 + 13 + struct nouveau_event { 14 + spinlock_t lock; 15 + 16 + void *priv; 17 + void (*enable)(struct nouveau_event *, int index); 18 + void (*disable)(struct nouveau_event *, int index); 19 + 20 + int index_nr; 21 + struct { 22 + struct list_head list; 23 + int refs; 24 + } index[]; 25 + }; 26 + 27 + int nouveau_event_create(int index_nr, struct nouveau_event **); 28 + void nouveau_event_destroy(struct nouveau_event **); 29 + void nouveau_event_trigger(struct nouveau_event *, int index); 30 + 31 + void nouveau_event_get(struct nouveau_event *, int index, 32 + struct nouveau_eventh *); 33 + void nouveau_event_put(struct nouveau_event *, int index, 34 + struct nouveau_eventh *); 35 + 36 + #endif
+6 -6
drivers/gpu/drm/nouveau/core/include/core/object.h
··· 133 133 nv_ro08(void *obj, u64 addr) 134 134 { 135 135 u8 data = nv_ofuncs(obj)->rd08(obj, addr); 136 - nv_spam(obj, "nv_ro08 0x%08x 0x%02x\n", addr, data); 136 + nv_spam(obj, "nv_ro08 0x%08llx 0x%02x\n", addr, data); 137 137 return data; 138 138 } 139 139 ··· 141 141 nv_ro16(void *obj, u64 addr) 142 142 { 143 143 u16 data = nv_ofuncs(obj)->rd16(obj, addr); 144 - nv_spam(obj, "nv_ro16 0x%08x 0x%04x\n", addr, data); 144 + nv_spam(obj, "nv_ro16 0x%08llx 0x%04x\n", addr, data); 145 145 return data; 146 146 } 147 147 ··· 149 149 nv_ro32(void *obj, u64 addr) 150 150 { 151 151 u32 data = nv_ofuncs(obj)->rd32(obj, addr); 152 - nv_spam(obj, "nv_ro32 0x%08x 0x%08x\n", addr, data); 152 + nv_spam(obj, "nv_ro32 0x%08llx 0x%08x\n", addr, data); 153 153 return data; 154 154 } 155 155 156 156 static inline void 157 157 nv_wo08(void *obj, u64 addr, u8 data) 158 158 { 159 - nv_spam(obj, "nv_wo08 0x%08x 0x%02x\n", addr, data); 159 + nv_spam(obj, "nv_wo08 0x%08llx 0x%02x\n", addr, data); 160 160 nv_ofuncs(obj)->wr08(obj, addr, data); 161 161 } 162 162 163 163 static inline void 164 164 nv_wo16(void *obj, u64 addr, u16 data) 165 165 { 166 - nv_spam(obj, "nv_wo16 0x%08x 0x%04x\n", addr, data); 166 + nv_spam(obj, "nv_wo16 0x%08llx 0x%04x\n", addr, data); 167 167 nv_ofuncs(obj)->wr16(obj, addr, data); 168 168 } 169 169 170 170 static inline void 171 171 nv_wo32(void *obj, u64 addr, u32 data) 172 172 { 173 - nv_spam(obj, "nv_wo32 0x%08x 0x%08x\n", addr, data); 173 + nv_spam(obj, "nv_wo32 0x%08llx 0x%08x\n", addr, data); 174 174 nv_ofuncs(obj)->wr32(obj, addr, data); 175 175 } 176 176
+2 -1
drivers/gpu/drm/nouveau/core/include/core/printk.h
··· 15 15 #define NV_PRINTK_TRACE KERN_DEBUG 16 16 #define NV_PRINTK_SPAM KERN_DEBUG 17 17 18 - void nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); 18 + void __printf(4, 5) 19 + nv_printk_(struct nouveau_object *, const char *, int, const char *, ...); 19 20 20 21 #define nv_printk(o,l,f,a...) do { \ 21 22 if (NV_DBG_##l <= CONFIG_NOUVEAU_DEBUG) \
+13 -14
drivers/gpu/drm/nouveau/core/include/engine/disp.h
··· 4 4 #include <core/object.h> 5 5 #include <core/engine.h> 6 6 #include <core/device.h> 7 + #include <core/event.h> 7 8 8 9 struct nouveau_disp { 9 10 struct nouveau_engine base; 10 - 11 - struct { 12 - struct list_head list; 13 - spinlock_t lock; 14 - void (*notify)(void *, int); 15 - void (*get)(void *, int); 16 - void (*put)(void *, int); 17 - void *data; 18 - } vblank; 11 + struct nouveau_event *vblank; 19 12 }; 20 13 21 14 static inline struct nouveau_disp * ··· 17 24 return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP]; 18 25 } 19 26 20 - #define nouveau_disp_create(p,e,c,i,x,d) \ 21 - nouveau_engine_create((p), (e), (c), true, (i), (x), (d)) 22 - #define nouveau_disp_destroy(d) \ 23 - nouveau_engine_destroy(&(d)->base) 27 + #define nouveau_disp_create(p,e,c,h,i,x,d) \ 28 + nouveau_disp_create_((p), (e), (c), (h), (i), (x), \ 29 + sizeof(**d), (void **)d) 30 + #define nouveau_disp_destroy(d) ({ \ 31 + struct nouveau_disp *disp = (d); \ 32 + _nouveau_disp_dtor(nv_object(disp)); \ 33 + }) 24 34 #define nouveau_disp_init(d) \ 25 35 nouveau_engine_init(&(d)->base) 26 36 #define nouveau_disp_fini(d,s) \ 27 37 nouveau_engine_fini(&(d)->base, (s)) 28 38 29 - #define _nouveau_disp_dtor _nouveau_engine_dtor 39 + int nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *, 40 + struct nouveau_oclass *, int heads, 41 + const char *, const char *, int, void **); 42 + void _nouveau_disp_dtor(struct nouveau_object *); 30 43 #define _nouveau_disp_init _nouveau_engine_init 31 44 #define _nouveau_disp_fini _nouveau_engine_fini 32 45
+4
drivers/gpu/drm/nouveau/core/include/engine/fifo.h
··· 65 65 struct nouveau_fifo { 66 66 struct nouveau_engine base; 67 67 68 + struct nouveau_event *uevent; 69 + 68 70 struct nouveau_object **channel; 69 71 spinlock_t lock; 70 72 u16 min; ··· 94 92 struct nouveau_oclass *, int min, int max, 95 93 int size, void **); 96 94 void nouveau_fifo_destroy(struct nouveau_fifo *); 95 + const char * 96 + nouveau_client_name_for_fifo_chid(struct nouveau_fifo *fifo, u32 chid); 97 97 98 98 #define _nouveau_fifo_init _nouveau_engine_init 99 99 #define _nouveau_fifo_fini _nouveau_engine_fini
+2 -2
drivers/gpu/drm/nouveau/core/include/engine/software.h
··· 3 3 4 4 #include <core/engine.h> 5 5 #include <core/engctx.h> 6 + #include <core/event.h> 6 7 7 8 struct nouveau_software_chan { 8 9 struct nouveau_engctx base; 9 10 10 11 struct { 11 - struct list_head head; 12 + struct nouveau_eventh event; 12 13 u32 channel; 13 14 u32 ctxdma; 14 15 u64 offset; 15 16 u32 value; 16 - u32 crtc; 17 17 } vblank; 18 18 19 19 int (*flip)(void *);
+3
drivers/gpu/drm/nouveau/core/include/subdev/bios/dcb.h
··· 16 16 17 17 struct dcb_output { 18 18 int index; /* may not be raw dcb index if merging has happened */ 19 + u16 hasht; 20 + u16 hashm; 19 21 enum dcb_output_type type; 20 22 uint8_t i2c_index; 21 23 uint8_t heads; ··· 27 25 uint8_t or; 28 26 uint8_t link; 29 27 bool duallink_possible; 28 + uint8_t extdev; 30 29 union { 31 30 struct sor_conf { 32 31 int link;
+8 -3
drivers/gpu/drm/nouveau/core/include/subdev/bios/gpio.h
··· 1 1 #ifndef __NVBIOS_GPIO_H__ 2 2 #define __NVBIOS_GPIO_H__ 3 3 4 - struct nouveau_bios; 5 - 6 4 enum dcb_gpio_func_name { 7 5 DCB_GPIO_PANEL_POWER = 0x01, 8 6 DCB_GPIO_TVDAC0 = 0x0c, 9 7 DCB_GPIO_TVDAC1 = 0x2d, 10 - DCB_GPIO_PWM_FAN = 0x09, 8 + DCB_GPIO_FAN = 0x09, 11 9 DCB_GPIO_FAN_SENSE = 0x3d, 12 10 DCB_GPIO_UNUSED = 0xff 13 11 }; 12 + 13 + #define DCB_GPIO_LOG_DIR 0x02 14 + #define DCB_GPIO_LOG_DIR_OUT 0x00 15 + #define DCB_GPIO_LOG_DIR_IN 0x02 16 + #define DCB_GPIO_LOG_VAL 0x01 17 + #define DCB_GPIO_LOG_VAL_LO 0x00 18 + #define DCB_GPIO_LOG_VAL_HI 0x01 14 19 15 20 struct dcb_gpio_func { 16 21 u8 func;
+1 -1
drivers/gpu/drm/nouveau/core/include/subdev/bios/i2c.h
··· 15 15 enum dcb_i2c_type type; 16 16 u8 drive; 17 17 u8 sense; 18 - u32 data; 18 + u8 share; 19 19 }; 20 20 21 21 u16 dcb_i2c_table(struct nouveau_bios *, u8 *ver, u8 *hdr, u8 *cnt, u8 *len);
+16
drivers/gpu/drm/nouveau/core/include/subdev/bios/therm.h
··· 23 23 struct nvbios_therm_threshold thrs_shutdown; 24 24 }; 25 25 26 + /* no vbios have more than 6 */ 27 + #define NOUVEAU_TEMP_FAN_TRIP_MAX 10 28 + struct nouveau_therm_trip_point { 29 + int fan_duty; 30 + int temp; 31 + int hysteresis; 32 + }; 33 + 26 34 struct nvbios_therm_fan { 27 35 u16 pwm_freq; 28 36 29 37 u8 min_duty; 30 38 u8 max_duty; 39 + 40 + u16 bump_period; 41 + u16 slow_down_period; 42 + 43 + struct nouveau_therm_trip_point trip[NOUVEAU_TEMP_FAN_TRIP_MAX]; 44 + u8 nr_fan_trip; 45 + u8 linear_min_temp; 46 + u8 linear_max_temp; 31 47 }; 32 48 33 49 enum nvbios_therm_domain {
+19
drivers/gpu/drm/nouveau/core/include/subdev/bios/xpio.h
··· 1 + #ifndef __NVBIOS_XPIO_H__ 2 + #define __NVBIOS_XPIO_H__ 3 + 4 + #define NVBIOS_XPIO_FLAG_AUX 0x10 5 + #define NVBIOS_XPIO_FLAG_AUX0 0x00 6 + #define NVBIOS_XPIO_FLAG_AUX1 0x10 7 + 8 + struct nvbios_xpio { 9 + u8 type; 10 + u8 addr; 11 + u8 flags; 12 + }; 13 + 14 + u16 dcb_xpio_table(struct nouveau_bios *, u8 idx, 15 + u8 *ver, u8 *hdr, u8 *cnt, u8 *len); 16 + u16 dcb_xpio_parse(struct nouveau_bios *, u8 idx, 17 + u8 *ver, u8 *hdr, u8 *cnt, u8 *len, struct nvbios_xpio *); 18 + 19 + #endif
+41
drivers/gpu/drm/nouveau/core/include/subdev/bus.h
··· 1 + #ifndef __NOUVEAU_BUS_H__ 2 + #define __NOUVEAU_BUS_H__ 3 + 4 + #include <core/subdev.h> 5 + #include <core/device.h> 6 + 7 + struct nouveau_bus_intr { 8 + u32 stat; 9 + u32 unit; 10 + }; 11 + 12 + struct nouveau_bus { 13 + struct nouveau_subdev base; 14 + }; 15 + 16 + static inline struct nouveau_bus * 17 + nouveau_bus(void *obj) 18 + { 19 + return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_BUS]; 20 + } 21 + 22 + #define nouveau_bus_create(p, e, o, d) \ 23 + nouveau_subdev_create_((p), (e), (o), 0, "PBUS", "master", \ 24 + sizeof(**d), (void **)d) 25 + #define nouveau_bus_destroy(p) \ 26 + nouveau_subdev_destroy(&(p)->base) 27 + #define nouveau_bus_init(p) \ 28 + nouveau_subdev_init(&(p)->base) 29 + #define nouveau_bus_fini(p, s) \ 30 + nouveau_subdev_fini(&(p)->base, (s)) 31 + 32 + #define _nouveau_bus_dtor _nouveau_subdev_dtor 33 + #define _nouveau_bus_init _nouveau_subdev_init 34 + #define _nouveau_bus_fini _nouveau_subdev_fini 35 + 36 + extern struct nouveau_oclass nv04_bus_oclass; 37 + extern struct nouveau_oclass nv31_bus_oclass; 38 + extern struct nouveau_oclass nv50_bus_oclass; 39 + extern struct nouveau_oclass nvc0_bus_oclass; 40 + 41 + #endif
+14 -25
drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
··· 3 3 4 4 #include <core/subdev.h> 5 5 #include <core/device.h> 6 + #include <core/event.h> 6 7 7 8 #include <subdev/bios.h> 8 9 #include <subdev/bios/gpio.h> ··· 11 10 struct nouveau_gpio { 12 11 struct nouveau_subdev base; 13 12 13 + struct nouveau_event *events; 14 + 14 15 /* hardware interfaces */ 15 16 void (*reset)(struct nouveau_gpio *, u8 func); 16 17 int (*drive)(struct nouveau_gpio *, int line, int dir, int out); 17 18 int (*sense)(struct nouveau_gpio *, int line); 18 - void (*irq_enable)(struct nouveau_gpio *, int line, bool); 19 19 20 20 /* software interfaces */ 21 21 int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line, 22 22 struct dcb_gpio_func *); 23 23 int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); 24 24 int (*get)(struct nouveau_gpio *, int idx, u8 tag, u8 line); 25 - int (*irq)(struct nouveau_gpio *, int idx, u8 tag, u8 line, bool on); 26 - 27 - /* interrupt handling */ 28 - struct list_head isr; 29 - spinlock_t lock; 30 - 31 - void (*isr_run)(struct nouveau_gpio *, int idx, u32 mask); 32 - int (*isr_add)(struct nouveau_gpio *, int idx, u8 tag, u8 line, 33 - void (*)(void *, int state), void *data); 34 - void (*isr_del)(struct nouveau_gpio *, int idx, u8 tag, u8 line, 35 - void (*)(void *, int state), void *data); 36 25 }; 37 26 38 27 static inline struct nouveau_gpio * ··· 31 40 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO]; 32 41 } 33 42 34 - #define nouveau_gpio_create(p,e,o,d) \ 35 - nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) 36 - #define nouveau_gpio_destroy(p) \ 37 - nouveau_subdev_destroy(&(p)->base) 43 + #define nouveau_gpio_create(p,e,o,l,d) \ 44 + nouveau_gpio_create_((p), (e), (o), (l), sizeof(**d), (void **)d) 45 + #define nouveau_gpio_destroy(p) ({ \ 46 + struct nouveau_gpio *gpio = (p); \ 47 + _nouveau_gpio_dtor(nv_object(gpio)); \ 48 + }) 38 49 #define nouveau_gpio_fini(p,s) \ 39 50 nouveau_subdev_fini(&(p)->base, (s)) 40 51 41 - int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, 42 - struct nouveau_oclass *, int, void **); 43 - int nouveau_gpio_init(struct nouveau_gpio *); 52 + int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, 53 + struct nouveau_oclass *, int, int, void **); 54 + void _nouveau_gpio_dtor(struct nouveau_object *); 55 + int nouveau_gpio_init(struct nouveau_gpio *); 44 56 45 57 extern struct nouveau_oclass nv10_gpio_oclass; 46 58 extern struct nouveau_oclass nv50_gpio_oclass; 47 59 extern struct nouveau_oclass nvd0_gpio_oclass; 48 - 49 - void nv50_gpio_dtor(struct nouveau_object *); 50 - int nv50_gpio_init(struct nouveau_object *); 51 - int nv50_gpio_fini(struct nouveau_object *, bool); 52 - void nv50_gpio_intr(struct nouveau_subdev *); 53 - void nv50_gpio_irq_enable(struct nouveau_gpio *, int line, bool); 60 + extern struct nouveau_oclass nve0_gpio_oclass; 54 61 55 62 #endif
+109 -18
drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
··· 10 10 #define NV_I2C_PORT(n) (0x00 + (n)) 11 11 #define NV_I2C_DEFAULT(n) (0x80 + (n)) 12 12 13 + #define NV_I2C_TYPE_DCBI2C(n) (0x0000 | (n)) 14 + #define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8) 15 + #define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8) 16 + 13 17 struct nouveau_i2c_port { 18 + struct nouveau_object base; 14 19 struct i2c_adapter adapter; 15 - struct nouveau_i2c *i2c; 16 - struct i2c_algo_bit_data bit; 20 + 17 21 struct list_head head; 18 22 u8 index; 19 - u8 type; 20 - u32 dcb; 21 - u32 drive; 22 - u32 sense; 23 - u32 state; 23 + 24 + const struct nouveau_i2c_func *func; 24 25 }; 26 + 27 + struct nouveau_i2c_func { 28 + void (*acquire)(struct nouveau_i2c_port *); 29 + void (*release)(struct nouveau_i2c_port *); 30 + 31 + void (*drive_scl)(struct nouveau_i2c_port *, int); 32 + void (*drive_sda)(struct nouveau_i2c_port *, int); 33 + int (*sense_scl)(struct nouveau_i2c_port *); 34 + int (*sense_sda)(struct nouveau_i2c_port *); 35 + 36 + int (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8); 37 + int (*pattern)(struct nouveau_i2c_port *, int pattern); 38 + int (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh); 39 + int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); 40 + }; 41 + 42 + #define nouveau_i2c_port_create(p,e,o,i,a,d) \ 43 + nouveau_i2c_port_create_((p), (e), (o), (i), (a), \ 44 + sizeof(**d), (void **)d) 45 + #define nouveau_i2c_port_destroy(p) ({ \ 46 + struct nouveau_i2c_port *port = (p); \ 47 + _nouveau_i2c_port_dtor(nv_object(i2c)); \ 48 + }) 49 + #define nouveau_i2c_port_init(p) \ 50 + nouveau_object_init(&(p)->base) 51 + #define nouveau_i2c_port_fini(p,s) \ 52 + nouveau_object_fini(&(p)->base, (s)) 53 + 54 + int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, 55 + struct nouveau_oclass *, u8, 56 + const struct i2c_algorithm *, int, void **); 57 + void _nouveau_i2c_port_dtor(struct nouveau_object *); 58 + #define _nouveau_i2c_port_init nouveau_object_init 59 + #define _nouveau_i2c_port_fini nouveau_object_fini 25 60 26 61 struct nouveau_i2c { 27 62 struct nouveau_subdev base; 28 63 29 64 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); 65 + struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type); 30 66 int (*identify)(struct nouveau_i2c *, int index, 31 67 const char *what, struct i2c_board_info *, 32 68 bool (*match)(struct nouveau_i2c_port *, ··· 76 40 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; 77 41 } 78 42 79 - extern struct nouveau_oclass nouveau_i2c_oclass; 43 + #define nouveau_i2c_create(p,e,o,s,d) \ 44 + nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d) 45 + #define nouveau_i2c_destroy(p) ({ \ 46 + struct nouveau_i2c *i2c = (p); \ 47 + _nouveau_i2c_dtor(nv_object(i2c)); \ 48 + }) 49 + #define nouveau_i2c_init(p) ({ \ 50 + struct nouveau_i2c *i2c = (p); \ 51 + _nouveau_i2c_init(nv_object(i2c)); \ 52 + }) 53 + #define nouveau_i2c_fini(p,s) ({ \ 54 + struct nouveau_i2c *i2c = (p); \ 55 + _nouveau_i2c_fini(nv_object(i2c), (s)); \ 56 + }) 80 57 81 - void nouveau_i2c_drive_scl(void *, int); 82 - void nouveau_i2c_drive_sda(void *, int); 83 - int nouveau_i2c_sense_scl(void *); 84 - int nouveau_i2c_sense_sda(void *); 58 + int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, 59 + struct nouveau_oclass *, struct nouveau_oclass *, 60 + int, void **); 61 + void _nouveau_i2c_dtor(struct nouveau_object *); 62 + int _nouveau_i2c_init(struct nouveau_object *); 63 + int _nouveau_i2c_fini(struct nouveau_object *, bool); 85 64 86 - int nv_rdi2cr(struct nouveau_i2c_port *, u8 addr, u8 reg); 87 - int nv_wri2cr(struct nouveau_i2c_port *, u8 addr, u8 reg, u8 val); 88 - bool nv_probe_i2c(struct nouveau_i2c_port *, u8 addr); 89 - 90 - int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 91 - int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 65 + extern struct nouveau_oclass nv04_i2c_oclass; 66 + extern struct nouveau_oclass nv4e_i2c_oclass; 67 + extern struct nouveau_oclass nv50_i2c_oclass; 68 + extern struct nouveau_oclass nv94_i2c_oclass; 69 + extern struct nouveau_oclass nvd0_i2c_oclass; 70 + extern struct nouveau_oclass nouveau_anx9805_sclass[]; 92 71 93 72 extern const struct i2c_algorithm nouveau_i2c_bit_algo; 94 73 extern const struct i2c_algorithm nouveau_i2c_aux_algo; 74 + 75 + static inline int 76 + nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) 77 + { 78 + u8 val; 79 + struct i2c_msg msgs[] = { 80 + { .addr = addr, .flags = 0, .len = 1, .buf = &reg }, 81 + { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, 82 + }; 83 + 84 + int ret = i2c_transfer(&port->adapter, msgs, 2); 85 + if (ret != 2) 86 + return -EIO; 87 + 88 + return val; 89 + } 90 + 91 + static inline int 92 + nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) 93 + { 94 + u8 buf[2] = { reg, val }; 95 + struct i2c_msg msgs[] = { 96 + { .addr = addr, .flags = 0, .len = 2, .buf = buf }, 97 + }; 98 + 99 + int ret = i2c_transfer(&port->adapter, msgs, 1); 100 + if (ret != 1) 101 + return -EIO; 102 + 103 + return 0; 104 + } 105 + 106 + static inline bool 107 + nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) 108 + { 109 + return nv_rdi2cr(port, addr, 0) >= 0; 110 + } 111 + 112 + int nv_rdaux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 113 + int nv_wraux(struct nouveau_i2c_port *, u32 addr, u8 *data, u8 size); 95 114 96 115 #endif
+29 -8
drivers/gpu/drm/nouveau/core/include/subdev/therm.h
··· 4 4 #include <core/device.h> 5 5 #include <core/subdev.h> 6 6 7 - enum nouveau_therm_fan_mode { 8 - FAN_CONTROL_NONE = 0, 9 - FAN_CONTROL_MANUAL = 1, 10 - FAN_CONTROL_NR, 7 + enum nouveau_therm_mode { 8 + NOUVEAU_THERM_CTRL_NONE = 0, 9 + NOUVEAU_THERM_CTRL_MANUAL = 1, 10 + NOUVEAU_THERM_CTRL_AUTO = 2, 11 11 }; 12 12 13 13 enum nouveau_therm_attr_type { ··· 28 28 struct nouveau_therm { 29 29 struct nouveau_subdev base; 30 30 31 + int (*pwm_ctrl)(struct nouveau_therm *, int line, bool); 32 + int (*pwm_get)(struct nouveau_therm *, int line, u32 *, u32 *); 33 + int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); 34 + int (*pwm_clock)(struct nouveau_therm *); 35 + 31 36 int (*fan_get)(struct nouveau_therm *); 32 37 int (*fan_set)(struct nouveau_therm *, int); 33 38 int (*fan_sense)(struct nouveau_therm *); ··· 51 46 } 52 47 53 48 #define nouveau_therm_create(p,e,o,d) \ 54 - nouveau_subdev_create((p), (e), (o), 0, "THERM", "therm", d) 55 - #define nouveau_therm_destroy(p) \ 56 - nouveau_subdev_destroy(&(p)->base) 49 + nouveau_therm_create_((p), (e), (o), sizeof(**d), (void **)d) 50 + #define nouveau_therm_destroy(p) ({ \ 51 + struct nouveau_therm *therm = (p); \ 52 + _nouveau_therm_dtor(nv_object(therm)); \ 53 + }) 54 + #define nouveau_therm_init(p) ({ \ 55 + struct nouveau_therm *therm = (p); \ 56 + _nouveau_therm_init(nv_object(therm)); \ 57 + }) 58 + #define nouveau_therm_fini(p,s) ({ \ 59 + struct nouveau_therm *therm = (p); \ 60 + _nouveau_therm_init(nv_object(therm), (s)); \ 61 + }) 57 62 58 - #define _nouveau_therm_dtor _nouveau_subdev_dtor 63 + int nouveau_therm_create_(struct nouveau_object *, struct nouveau_object *, 64 + struct nouveau_oclass *, int, void **); 65 + void _nouveau_therm_dtor(struct nouveau_object *); 66 + int _nouveau_therm_init(struct nouveau_object *); 67 + int _nouveau_therm_fini(struct nouveau_object *, bool); 59 68 60 69 extern struct nouveau_oclass nv40_therm_oclass; 61 70 extern struct nouveau_oclass nv50_therm_oclass; 71 + extern struct nouveau_oclass nva3_therm_oclass; 72 + extern struct nouveau_oclass nvd0_therm_oclass; 62 73 63 74 #endif
+8
drivers/gpu/drm/nouveau/core/include/subdev/timer.h
··· 10 10 void (*func)(struct nouveau_alarm *); 11 11 }; 12 12 13 + static inline void 14 + nouveau_alarm_init(struct nouveau_alarm *alarm, 15 + void (*func)(struct nouveau_alarm *)) 16 + { 17 + INIT_LIST_HEAD(&alarm->head); 18 + alarm->func = func; 19 + } 20 + 13 21 bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); 14 22 bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); 15 23 bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
+1
drivers/gpu/drm/nouveau/core/os.h
··· 16 16 #include <linux/vmalloc.h> 17 17 #include <linux/acpi.h> 18 18 #include <linux/dmi.h> 19 + #include <linux/reboot.h> 19 20 20 21 #include <asm/unaligned.h> 21 22
+1 -1
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
··· 172 172 nv_wr32(bios, pcireg, access); 173 173 } 174 174 175 - #if defined(CONFIG_ACPI) 175 + #if defined(CONFIG_ACPI) && defined(CONFIG_X86) 176 176 int nouveau_acpi_get_bios_chunk(uint8_t *bios, int offset, int len); 177 177 bool nouveau_acpi_rom_supported(struct pci_dev *pdev); 178 178 #else
+19 -13
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
··· 107 107 return 0x0000; 108 108 } 109 109 110 + static inline u16 111 + dcb_outp_hasht(struct dcb_output *outp) 112 + { 113 + return (outp->extdev << 8) | (outp->location << 4) | outp->type; 114 + } 115 + 116 + static inline u16 117 + dcb_outp_hashm(struct dcb_output *outp) 118 + { 119 + return (outp->heads << 8) | (outp->link << 6) | outp->or; 120 + } 121 + 110 122 u16 111 123 dcb_outp_parse(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, 112 124 struct dcb_output *outp) ··· 147 135 case DCB_OUTPUT_DP: 148 136 outp->link = (conf & 0x00000030) >> 4; 149 137 outp->sorconf.link = outp->link; /*XXX*/ 138 + outp->extdev = 0x00; 139 + if (outp->location != 0) 140 + outp->extdev = (conf & 0x0000ff00) >> 8; 150 141 break; 151 142 default: 152 143 break; 153 144 } 154 145 } 146 + 147 + outp->hasht = dcb_outp_hasht(outp); 148 + outp->hashm = dcb_outp_hashm(outp); 155 149 } 156 150 return dcb; 157 - } 158 - 159 - static inline u16 160 - dcb_outp_hasht(struct dcb_output *outp) 161 - { 162 - return outp->type; 163 - } 164 - 165 - static inline u16 166 - dcb_outp_hashm(struct dcb_output *outp) 167 - { 168 - return (outp->heads << 8) | (outp->link << 6) | outp->or; 169 151 } 170 152 171 153 u16 ··· 168 162 { 169 163 u16 dcb, idx = 0; 170 164 while ((dcb = dcb_outp_parse(bios, idx++, ver, len, outp))) { 171 - if (dcb_outp_hasht(outp) == type) { 165 + if ((dcb_outp_hasht(outp) & 0x00ff) == (type & 0x00ff)) { 172 166 if ((dcb_outp_hashm(outp) & mask) == mask) 173 167 break; 174 168 }
+1 -1
drivers/gpu/drm/nouveau/core/subdev/bios/extdev.c
··· 48 48 return extdev + *hdr; 49 49 } 50 50 51 - u16 51 + static u16 52 52 nvbios_extdev_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) 53 53 { 54 54 u8 hdr, cnt;
+9 -2
drivers/gpu/drm/nouveau/core/subdev/bios/gpio.c
··· 25 25 #include <subdev/bios.h> 26 26 #include <subdev/bios/dcb.h> 27 27 #include <subdev/bios/gpio.h> 28 + #include <subdev/bios/xpio.h> 28 29 29 30 u16 30 31 dcb_gpio_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) ··· 61 60 u16 62 61 dcb_gpio_entry(struct nouveau_bios *bios, int idx, int ent, u8 *ver, u8 *len) 63 62 { 64 - u8 hdr, cnt; 65 - u16 gpio = !idx ? dcb_gpio_table(bios, ver, &hdr, &cnt, len) : 0x0000; 63 + u8 hdr, cnt, xver; /* use gpio version for xpio entry parsing */ 64 + u16 gpio; 65 + 66 + if (!idx--) 67 + gpio = dcb_gpio_table(bios, ver, &hdr, &cnt, len); 68 + else 69 + gpio = dcb_xpio_table(bios, idx, &xver, &hdr, &cnt, len); 70 + 66 71 if (gpio && ent < cnt) 67 72 return gpio + hdr + (ent * *len); 68 73 return 0x0000;
+10 -5
drivers/gpu/drm/nouveau/core/subdev/bios/i2c.c
··· 70 70 u8 ver, len; 71 71 u16 ent = dcb_i2c_entry(bios, idx, &ver, &len); 72 72 if (ent) { 73 - info->data = nv_ro32(bios, ent + 0); 74 - info->type = nv_ro08(bios, ent + 3); 73 + info->type = nv_ro08(bios, ent + 3); 74 + info->share = DCB_I2C_UNUSED; 75 75 if (ver < 0x30) { 76 76 info->type &= 0x07; 77 77 if (info->type == 0x07) 78 - info->type = 0xff; 78 + info->type = DCB_I2C_UNUSED; 79 79 } 80 80 81 81 switch (info->type) { ··· 88 88 return 0; 89 89 case DCB_I2C_NVIO_BIT: 90 90 case DCB_I2C_NVIO_AUX: 91 - info->drive = nv_ro08(bios, ent + 0); 91 + info->drive = nv_ro08(bios, ent + 0) & 0x0f; 92 + if (nv_ro08(bios, ent + 1) & 0x01) { 93 + info->share = nv_ro08(bios, ent + 1) >> 1; 94 + info->share &= 0x0f; 95 + } 92 96 return 0; 93 97 case DCB_I2C_UNUSED: 94 98 return 0; ··· 125 121 if (!info->sense) info->sense = 0x36; 126 122 } 127 123 128 - info->type = DCB_I2C_NV04_BIT; 124 + info->type = DCB_I2C_NV04_BIT; 125 + info->share = DCB_I2C_UNUSED; 129 126 return 0; 130 127 } 131 128
+10 -5
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
··· 231 231 return NULL; 232 232 } 233 233 234 + if (index == -2 && init->outp->location) { 235 + index = NV_I2C_TYPE_EXTAUX(init->outp->extdev); 236 + return i2c->find_type(i2c, index); 237 + } 238 + 234 239 index = init->outp->i2c_index; 235 240 } 236 241 ··· 263 258 static int 264 259 init_rdauxr(struct nvbios_init *init, u32 addr) 265 260 { 266 - struct nouveau_i2c_port *port = init_i2c(init, -1); 261 + struct nouveau_i2c_port *port = init_i2c(init, -2); 267 262 u8 data; 268 263 269 264 if (port && init_exec(init)) { ··· 279 274 static int 280 275 init_wrauxr(struct nvbios_init *init, u32 addr, u8 data) 281 276 { 282 - struct nouveau_i2c_port *port = init_i2c(init, -1); 277 + struct nouveau_i2c_port *port = init_i2c(init, -2); 283 278 if (port && init_exec(init)) 284 279 return nv_wraux(port, addr, &data, 1); 285 280 return -ENODEV; ··· 1821 1816 u8 i, j; 1822 1817 1823 1818 trace("RAM_RESTRICT_ZM_REG_GROUP\t" 1824 - "R[%08x] 0x%02x 0x%02x\n", addr, incr, num); 1819 + "R[0x%08x] 0x%02x 0x%02x\n", addr, incr, num); 1825 1820 init->offset += 7; 1826 1821 1827 1822 for (i = 0; i < num; i++) { ··· 1854 1849 u32 sreg = nv_ro32(bios, init->offset + 1); 1855 1850 u32 dreg = nv_ro32(bios, init->offset + 5); 1856 1851 1857 - trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", sreg, dreg); 1852 + trace("COPY_ZM_REG\tR[0x%06x] = R[0x%06x]\n", dreg, sreg); 1858 1853 init->offset += 9; 1859 1854 1860 1855 init_wr32(init, dreg, init_rd32(init, sreg)); ··· 1871 1866 u32 addr = nv_ro32(bios, init->offset + 1); 1872 1867 u8 count = nv_ro08(bios, init->offset + 5); 1873 1868 1874 - trace("ZM_REG_GROUP\tR[0x%06x] =\n"); 1869 + trace("ZM_REG_GROUP\tR[0x%06x] =\n", addr); 1875 1870 init->offset += 6; 1876 1871 1877 1872 while (count--) {
+27 -1
drivers/gpu/drm/nouveau/core/subdev/bios/therm.c
··· 55 55 return therm + nv_ro08(bios, therm + 1); 56 56 } 57 57 58 - u16 58 + static u16 59 59 nvbios_therm_entry(struct nouveau_bios *bios, int idx, u8 *ver, u8 *len) 60 60 { 61 61 u8 hdr, cnt; ··· 155 155 nvbios_therm_fan_parse(struct nouveau_bios *bios, 156 156 struct nvbios_therm_fan *fan) 157 157 { 158 + struct nouveau_therm_trip_point *cur_trip = NULL; 158 159 u8 ver, len, i; 159 160 u16 entry; 160 161 162 + uint8_t duty_lut[] = { 0, 0, 25, 0, 40, 0, 50, 0, 163 + 75, 0, 85, 0, 100, 0, 100, 0 }; 164 + 161 165 i = 0; 166 + fan->nr_fan_trip = 0; 162 167 while ((entry = nvbios_therm_entry(bios, i++, &ver, &len))) { 163 168 s16 value = nv_ro16(bios, entry + 1); 164 169 ··· 172 167 fan->min_duty = value & 0xff; 173 168 fan->max_duty = (value & 0xff00) >> 8; 174 169 break; 170 + case 0x24: 171 + fan->nr_fan_trip++; 172 + cur_trip = &fan->trip[fan->nr_fan_trip - 1]; 173 + cur_trip->hysteresis = value & 0xf; 174 + cur_trip->temp = (value & 0xff0) >> 4; 175 + cur_trip->fan_duty = duty_lut[(value & 0xf000) >> 12]; 176 + break; 177 + case 0x25: 178 + cur_trip = &fan->trip[fan->nr_fan_trip - 1]; 179 + cur_trip->fan_duty = value; 180 + break; 175 181 case 0x26: 176 182 fan->pwm_freq = value; 183 + break; 184 + case 0x3b: 185 + fan->bump_period = value; 186 + break; 187 + case 0x3c: 188 + fan->slow_down_period = value; 189 + break; 190 + case 0x46: 191 + fan->linear_min_temp = nv_ro08(bios, entry + 1); 192 + fan->linear_max_temp = nv_ro08(bios, entry + 2); 177 193 break; 178 194 } 179 195 }
+76
drivers/gpu/drm/nouveau/core/subdev/bios/xpio.c
··· 1 + /* 2 + * Copyright 2012 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 <subdev/bios.h> 26 + #include <subdev/bios/gpio.h> 27 + #include <subdev/bios/xpio.h> 28 + 29 + static u16 30 + dcb_xpiod_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 31 + { 32 + u16 data = dcb_gpio_table(bios, ver, hdr, cnt, len); 33 + if (data && *ver >= 0x40 && *hdr >= 0x06) { 34 + u16 xpio = nv_ro16(bios, data + 0x04); 35 + if (xpio) { 36 + *ver = nv_ro08(bios, data + 0x00); 37 + *hdr = nv_ro08(bios, data + 0x01); 38 + *cnt = nv_ro08(bios, data + 0x02); 39 + *len = nv_ro08(bios, data + 0x03); 40 + return xpio; 41 + } 42 + } 43 + return 0x0000; 44 + } 45 + 46 + u16 47 + dcb_xpio_table(struct nouveau_bios *bios, u8 idx, 48 + u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 49 + { 50 + u16 data = dcb_xpiod_table(bios, ver, hdr, cnt, len); 51 + if (data && idx < *cnt) { 52 + u16 xpio = nv_ro16(bios, data + *hdr + (idx * *len)); 53 + if (xpio) { 54 + *ver = nv_ro08(bios, data + 0x00); 55 + *hdr = nv_ro08(bios, data + 0x01); 56 + *cnt = nv_ro08(bios, data + 0x02); 57 + *len = nv_ro08(bios, data + 0x03); 58 + return xpio; 59 + } 60 + } 61 + return 0x0000; 62 + } 63 + 64 + u16 65 + dcb_xpio_parse(struct nouveau_bios *bios, u8 idx, 66 + u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 67 + struct nvbios_xpio *info) 68 + { 69 + u16 data = dcb_xpio_table(bios, idx, ver, hdr, cnt, len); 70 + if (data && *len >= 6) { 71 + info->type = nv_ro08(bios, data + 0x04); 72 + info->addr = nv_ro08(bios, data + 0x05); 73 + info->flags = nv_ro08(bios, data + 0x06); 74 + } 75 + return 0x0000; 76 + }
+95
drivers/gpu/drm/nouveau/core/subdev/bus/nv04.c
··· 1 + /* 2 + * Copyright 2012 Nouveau Community 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 <martin.peres@labri.fr> 23 + * Ben Skeggs 24 + */ 25 + 26 + #include <subdev/bus.h> 27 + 28 + struct nv04_bus_priv { 29 + struct nouveau_bus base; 30 + }; 31 + 32 + static void 33 + nv04_bus_intr(struct nouveau_subdev *subdev) 34 + { 35 + struct nouveau_bus *pbus = nouveau_bus(subdev); 36 + u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); 37 + 38 + if (stat & 0x00000001) { 39 + nv_error(pbus, "BUS ERROR\n"); 40 + stat &= ~0x00000001; 41 + nv_wr32(pbus, 0x001100, 0x00000001); 42 + } 43 + 44 + if (stat & 0x00000110) { 45 + subdev = nouveau_subdev(subdev, NVDEV_SUBDEV_GPIO); 46 + if (subdev && subdev->intr) 47 + subdev->intr(subdev); 48 + stat &= ~0x00000110; 49 + nv_wr32(pbus, 0x001100, 0x00000110); 50 + } 51 + 52 + if (stat) { 53 + nv_error(pbus, "unknown intr 0x%08x\n", stat); 54 + nv_mask(pbus, 0x001140, stat, 0x00000000); 55 + } 56 + } 57 + 58 + static int 59 + nv04_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 60 + struct nouveau_oclass *oclass, void *data, u32 size, 61 + struct nouveau_object **pobject) 62 + { 63 + struct nv04_bus_priv *priv; 64 + int ret; 65 + 66 + ret = nouveau_bus_create(parent, engine, oclass, &priv); 67 + *pobject = nv_object(priv); 68 + if (ret) 69 + return ret; 70 + 71 + nv_subdev(priv)->intr = nv04_bus_intr; 72 + return 0; 73 + } 74 + 75 + static int 76 + nv04_bus_init(struct nouveau_object *object) 77 + { 78 + struct nv04_bus_priv *priv = (void *)object; 79 + 80 + nv_wr32(priv, 0x001100, 0xffffffff); 81 + nv_wr32(priv, 0x001140, 0x00000111); 82 + 83 + return nouveau_bus_init(&priv->base); 84 + } 85 + 86 + struct nouveau_oclass 87 + nv04_bus_oclass = { 88 + .handle = NV_SUBDEV(BUS, 0x04), 89 + .ofuncs = &(struct nouveau_ofuncs) { 90 + .ctor = nv04_bus_ctor, 91 + .dtor = _nouveau_bus_dtor, 92 + .init = nv04_bus_init, 93 + .fini = _nouveau_bus_fini, 94 + }, 95 + };
+112
drivers/gpu/drm/nouveau/core/subdev/bus/nv31.c
··· 1 + /* 2 + * Copyright 2012 Nouveau Community 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 <martin.peres@labri.fr> 23 + * Ben Skeggs 24 + */ 25 + 26 + #include <subdev/bus.h> 27 + 28 + struct nv31_bus_priv { 29 + struct nouveau_bus base; 30 + }; 31 + 32 + static void 33 + nv31_bus_intr(struct nouveau_subdev *subdev) 34 + { 35 + struct nouveau_bus *pbus = nouveau_bus(subdev); 36 + u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); 37 + u32 gpio = nv_rd32(pbus, 0x001104) & nv_rd32(pbus, 0x001144); 38 + 39 + if (gpio) { 40 + subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_GPIO); 41 + if (subdev && subdev->intr) 42 + subdev->intr(subdev); 43 + } 44 + 45 + if (stat & 0x00000008) { /* NV41- */ 46 + u32 addr = nv_rd32(pbus, 0x009084); 47 + u32 data = nv_rd32(pbus, 0x009088); 48 + 49 + nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", 50 + (addr & 0x00000002) ? "write" : "read", data, 51 + (addr & 0x00fffffc)); 52 + 53 + stat &= ~0x00000008; 54 + nv_wr32(pbus, 0x001100, 0x00000008); 55 + } 56 + 57 + if (stat & 0x00070000) { 58 + subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_THERM); 59 + if (subdev && subdev->intr) 60 + subdev->intr(subdev); 61 + stat &= ~0x00070000; 62 + nv_wr32(pbus, 0x001100, 0x00070000); 63 + } 64 + 65 + if (stat) { 66 + nv_error(pbus, "unknown intr 0x%08x\n", stat); 67 + nv_mask(pbus, 0x001140, stat, 0x00000000); 68 + } 69 + } 70 + 71 + static int 72 + nv31_bus_init(struct nouveau_object *object) 73 + { 74 + struct nv31_bus_priv *priv = (void *)object; 75 + int ret; 76 + 77 + ret = nouveau_bus_init(&priv->base); 78 + if (ret) 79 + return ret; 80 + 81 + nv_wr32(priv, 0x001100, 0xffffffff); 82 + nv_wr32(priv, 0x001140, 0x00070008); 83 + return 0; 84 + } 85 + 86 + static int 87 + nv31_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 88 + struct nouveau_oclass *oclass, void *data, u32 size, 89 + struct nouveau_object **pobject) 90 + { 91 + struct nv31_bus_priv *priv; 92 + int ret; 93 + 94 + ret = nouveau_bus_create(parent, engine, oclass, &priv); 95 + *pobject = nv_object(priv); 96 + if (ret) 97 + return ret; 98 + 99 + nv_subdev(priv)->intr = nv31_bus_intr; 100 + return 0; 101 + } 102 + 103 + struct nouveau_oclass 104 + nv31_bus_oclass = { 105 + .handle = NV_SUBDEV(BUS, 0x31), 106 + .ofuncs = &(struct nouveau_ofuncs) { 107 + .ctor = nv31_bus_ctor, 108 + .dtor = _nouveau_bus_dtor, 109 + .init = nv31_bus_init, 110 + .fini = _nouveau_bus_fini, 111 + }, 112 + };
+105
drivers/gpu/drm/nouveau/core/subdev/bus/nv50.c
··· 1 + /* 2 + * Copyright 2012 Nouveau Community 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 <martin.peres@labri.fr> 23 + * Ben Skeggs 24 + */ 25 + 26 + #include <subdev/bus.h> 27 + 28 + struct nv50_bus_priv { 29 + struct nouveau_bus base; 30 + }; 31 + 32 + static void 33 + nv50_bus_intr(struct nouveau_subdev *subdev) 34 + { 35 + struct nouveau_bus *pbus = nouveau_bus(subdev); 36 + u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); 37 + 38 + if (stat & 0x00000008) { 39 + u32 addr = nv_rd32(pbus, 0x009084); 40 + u32 data = nv_rd32(pbus, 0x009088); 41 + 42 + nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", 43 + (addr & 0x00000002) ? "write" : "read", data, 44 + (addr & 0x00fffffc)); 45 + 46 + stat &= ~0x00000008; 47 + nv_wr32(pbus, 0x001100, 0x00000008); 48 + } 49 + 50 + if (stat & 0x00010000) { 51 + subdev = nouveau_subdev(pbus, NVDEV_SUBDEV_THERM); 52 + if (subdev && subdev->intr) 53 + subdev->intr(subdev); 54 + stat &= ~0x00010000; 55 + nv_wr32(pbus, 0x001100, 0x00010000); 56 + } 57 + 58 + if (stat) { 59 + nv_error(pbus, "unknown intr 0x%08x\n", stat); 60 + nv_mask(pbus, 0x001140, stat, 0); 61 + } 62 + } 63 + 64 + static int 65 + nv50_bus_init(struct nouveau_object *object) 66 + { 67 + struct nv50_bus_priv *priv = (void *)object; 68 + int ret; 69 + 70 + ret = nouveau_bus_init(&priv->base); 71 + if (ret) 72 + return ret; 73 + 74 + nv_wr32(priv, 0x001100, 0xffffffff); 75 + nv_wr32(priv, 0x001140, 0x00010008); 76 + return 0; 77 + } 78 + 79 + static int 80 + nv50_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 81 + struct nouveau_oclass *oclass, void *data, u32 size, 82 + struct nouveau_object **pobject) 83 + { 84 + struct nv50_bus_priv *priv; 85 + int ret; 86 + 87 + ret = nouveau_bus_create(parent, engine, oclass, &priv); 88 + *pobject = nv_object(priv); 89 + if (ret) 90 + return ret; 91 + 92 + nv_subdev(priv)->intr = nv50_bus_intr; 93 + return 0; 94 + } 95 + 96 + struct nouveau_oclass 97 + nv50_bus_oclass = { 98 + .handle = NV_SUBDEV(BUS, 0x50), 99 + .ofuncs = &(struct nouveau_ofuncs) { 100 + .ctor = nv50_bus_ctor, 101 + .dtor = _nouveau_bus_dtor, 102 + .init = nv50_bus_init, 103 + .fini = _nouveau_bus_fini, 104 + }, 105 + };
+101
drivers/gpu/drm/nouveau/core/subdev/bus/nvc0.c
··· 1 + /* 2 + * Copyright 2012 Nouveau Community 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 <martin.peres@labri.fr> 23 + * Ben Skeggs 24 + */ 25 + 26 + #include <subdev/bus.h> 27 + 28 + struct nvc0_bus_priv { 29 + struct nouveau_bus base; 30 + }; 31 + 32 + static void 33 + nvc0_bus_intr(struct nouveau_subdev *subdev) 34 + { 35 + struct nouveau_bus *pbus = nouveau_bus(subdev); 36 + u32 stat = nv_rd32(pbus, 0x001100) & nv_rd32(pbus, 0x001140); 37 + 38 + if (stat & 0x0000000e) { 39 + u32 addr = nv_rd32(pbus, 0x009084); 40 + u32 data = nv_rd32(pbus, 0x009088); 41 + 42 + nv_error(pbus, "MMIO %s of 0x%08x FAULT at 0x%06x [ %s%s%s]\n", 43 + (addr & 0x00000002) ? "write" : "read", data, 44 + (addr & 0x00fffffc), 45 + (stat & 0x00000002) ? "!ENGINE " : "", 46 + (stat & 0x00000004) ? "IBUS " : "", 47 + (stat & 0x00000008) ? "TIMEOUT " : ""); 48 + 49 + nv_wr32(pbus, 0x009084, 0x00000000); 50 + nv_wr32(pbus, 0x001100, (stat & 0x0000000e)); 51 + stat &= ~0x0000000e; 52 + } 53 + 54 + if (stat) { 55 + nv_error(pbus, "unknown intr 0x%08x\n", stat); 56 + nv_mask(pbus, 0x001140, stat, 0x00000000); 57 + } 58 + } 59 + 60 + static int 61 + nvc0_bus_init(struct nouveau_object *object) 62 + { 63 + struct nvc0_bus_priv *priv = (void *)object; 64 + int ret; 65 + 66 + ret = nouveau_bus_init(&priv->base); 67 + if (ret) 68 + return ret; 69 + 70 + nv_wr32(priv, 0x001100, 0xffffffff); 71 + nv_wr32(priv, 0x001140, 0x0000000e); 72 + return 0; 73 + } 74 + 75 + static int 76 + nvc0_bus_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 77 + struct nouveau_oclass *oclass, void *data, u32 size, 78 + struct nouveau_object **pobject) 79 + { 80 + struct nvc0_bus_priv *priv; 81 + int ret; 82 + 83 + ret = nouveau_bus_create(parent, engine, oclass, &priv); 84 + *pobject = nv_object(priv); 85 + if (ret) 86 + return ret; 87 + 88 + nv_subdev(priv)->intr = nvc0_bus_intr; 89 + return 0; 90 + } 91 + 92 + struct nouveau_oclass 93 + nvc0_bus_oclass = { 94 + .handle = NV_SUBDEV(BUS, 0xc0), 95 + .ofuncs = &(struct nouveau_ofuncs) { 96 + .ctor = nvc0_bus_ctor, 97 + .dtor = _nouveau_bus_dtor, 98 + .init = nvc0_bus_init, 99 + .fini = _nouveau_bus_fini, 100 + }, 101 + };
+3 -2
drivers/gpu/drm/nouveau/core/subdev/device/base.c
··· 66 66 [NVDEV_SUBDEV_CLOCK] = NV_DEVICE_DISABLE_CORE, 67 67 [NVDEV_SUBDEV_MXM] = NV_DEVICE_DISABLE_CORE, 68 68 [NVDEV_SUBDEV_MC] = NV_DEVICE_DISABLE_CORE, 69 + [NVDEV_SUBDEV_BUS] = NV_DEVICE_DISABLE_CORE, 69 70 [NVDEV_SUBDEV_TIMER] = NV_DEVICE_DISABLE_CORE, 70 71 [NVDEV_SUBDEV_FB] = NV_DEVICE_DISABLE_CORE, 71 72 [NVDEV_SUBDEV_LTCG] = NV_DEVICE_DISABLE_CORE, ··· 104 103 struct nouveau_device *device; 105 104 struct nouveau_devobj *devobj; 106 105 struct nv_device_class *args = data; 107 - u64 disable, boot0, strap; 108 - u64 mmio_base, mmio_size; 106 + u32 boot0, strap; 107 + u64 disable, mmio_base, mmio_size; 109 108 void __iomem *map; 110 109 int ret, i, c; 111 110
+5 -2
drivers/gpu/drm/nouveau/core/subdev/device/nv04.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/i2c.h> 28 29 #include <subdev/clock.h> 29 30 #include <subdev/devinit.h> ··· 47 46 case 0x04: 48 47 device->cname = "NV04"; 49 48 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 50 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 49 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 51 50 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 52 51 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv04_devinit_oclass; 53 52 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 53 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 54 54 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 55 55 device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; 56 56 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 65 63 case 0x05: 66 64 device->cname = "NV05"; 67 65 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 68 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 66 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 69 67 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 70 68 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv05_devinit_oclass; 71 69 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 70 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 72 71 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 73 72 device->oclass[NVDEV_SUBDEV_FB ] = &nv04_fb_oclass; 74 73 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+17 -8
drivers/gpu/drm/nouveau/core/subdev/device/nv10.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/gpio.h> 28 29 #include <subdev/i2c.h> 29 30 #include <subdev/clock.h> ··· 49 48 device->cname = "NV10"; 50 49 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 51 50 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 52 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 51 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 53 52 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 54 53 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 55 54 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 55 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 56 56 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 57 57 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 58 58 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 66 64 device->cname = "NV15"; 67 65 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 68 66 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 69 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 67 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 70 68 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 71 69 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 72 70 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 71 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 73 72 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 74 73 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 75 74 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 85 82 device->cname = "NV16"; 86 83 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 87 84 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 88 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 85 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 89 86 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 90 87 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 91 88 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 89 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 92 90 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 93 91 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 94 92 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 104 100 device->cname = "nForce"; 105 101 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 106 102 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 107 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 103 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 108 104 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 109 105 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 110 106 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 107 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 111 108 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 112 109 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass; 113 110 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 123 118 device->cname = "NV11"; 124 119 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 125 120 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 126 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 121 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 127 122 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 128 123 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 129 124 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 125 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 130 126 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 131 127 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 132 128 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 142 136 device->cname = "NV17"; 143 137 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 144 138 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 145 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 139 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 146 140 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 147 141 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 148 142 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 143 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 149 144 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 150 145 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 151 146 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 161 154 device->cname = "nForce2"; 162 155 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 163 156 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 164 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 157 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 165 158 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 166 159 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 167 160 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 161 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 168 162 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 169 163 device->oclass[NVDEV_SUBDEV_FB ] = &nv1a_fb_oclass; 170 164 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 180 172 device->cname = "NV18"; 181 173 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 182 174 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 183 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 175 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 184 176 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 185 177 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 186 178 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 179 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 187 180 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 188 181 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 189 182 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+9 -4
drivers/gpu/drm/nouveau/core/subdev/device/nv20.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/gpio.h> 28 29 #include <subdev/i2c.h> 29 30 #include <subdev/clock.h> ··· 50 49 device->cname = "NV20"; 51 50 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 52 51 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 53 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 52 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 54 53 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 55 54 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 56 55 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 56 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 57 57 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 58 58 device->oclass[NVDEV_SUBDEV_FB ] = &nv20_fb_oclass; 59 59 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 69 67 device->cname = "NV25"; 70 68 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 71 69 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 72 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 70 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 73 71 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 74 72 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 75 73 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 74 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 76 75 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 77 76 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; 78 77 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 88 85 device->cname = "NV28"; 89 86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 90 87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 91 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 88 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 92 89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 93 90 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 94 91 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 92 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 95 93 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 96 94 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; 97 95 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 107 103 device->cname = "NV2A"; 108 104 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 109 105 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 110 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 106 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 111 107 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 112 108 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 113 109 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 110 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 114 111 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 115 112 device->oclass[NVDEV_SUBDEV_FB ] = &nv25_fb_oclass; 116 113 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+11 -5
drivers/gpu/drm/nouveau/core/subdev/device/nv30.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/gpio.h> 28 29 #include <subdev/i2c.h> 29 30 #include <subdev/clock.h> ··· 50 49 device->cname = "NV30"; 51 50 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 52 51 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 53 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 52 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 54 53 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 55 54 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 56 55 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 56 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 57 57 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 58 58 device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; 59 59 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 69 67 device->cname = "NV35"; 70 68 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 71 69 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 72 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 70 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 73 71 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 74 72 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 75 73 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 74 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv04_bus_oclass; 76 75 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 77 76 device->oclass[NVDEV_SUBDEV_FB ] = &nv35_fb_oclass; 78 77 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 88 85 device->cname = "NV31"; 89 86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 90 87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 91 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 88 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 92 89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 93 90 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 94 91 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 92 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 95 93 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 96 94 device->oclass[NVDEV_SUBDEV_FB ] = &nv30_fb_oclass; 97 95 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 108 104 device->cname = "NV36"; 109 105 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 110 106 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 111 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 107 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 112 108 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 113 109 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv20_devinit_oclass; 114 110 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 111 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 115 112 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 116 113 device->oclass[NVDEV_SUBDEV_FB ] = &nv36_fb_oclass; 117 114 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass; ··· 128 123 device->cname = "NV34"; 129 124 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 130 125 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 131 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 126 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 132 127 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 133 128 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv10_devinit_oclass; 134 129 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 130 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 135 131 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 136 132 device->oclass[NVDEV_SUBDEV_FB ] = &nv10_fb_oclass; 137 133 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv04_instmem_oclass;
+34 -16
drivers/gpu/drm/nouveau/core/subdev/device/nv40.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 28 + #include <subdev/vm.h> 27 29 #include <subdev/gpio.h> 28 30 #include <subdev/i2c.h> 29 31 #include <subdev/clock.h> ··· 52 50 device->cname = "NV40"; 53 51 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 54 52 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 55 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 53 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 56 54 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 57 55 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 58 56 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 59 57 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 58 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 60 59 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 61 60 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 62 61 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 73 70 device->cname = "NV41"; 74 71 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 75 72 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 76 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 73 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 77 74 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 78 75 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 79 76 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 80 77 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 78 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 81 79 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 82 80 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; 83 81 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 94 90 device->cname = "NV42"; 95 91 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 96 92 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 97 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 93 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 98 94 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 99 95 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 100 96 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 101 97 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 98 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 102 99 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 103 100 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; 104 101 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 115 110 device->cname = "NV43"; 116 111 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 117 112 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 118 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 113 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 119 114 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 120 115 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 121 116 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 122 117 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 118 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 123 119 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 124 120 device->oclass[NVDEV_SUBDEV_FB ] = &nv41_fb_oclass; 125 121 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 136 130 device->cname = "NV45"; 137 131 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 138 132 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 139 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 133 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 140 134 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 141 135 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 142 136 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 143 137 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 138 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 144 139 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 145 140 device->oclass[NVDEV_SUBDEV_FB ] = &nv40_fb_oclass; 146 141 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 157 150 device->cname = "G70"; 158 151 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 159 152 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 160 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 153 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 161 154 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 162 155 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 163 156 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 164 157 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 158 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 165 159 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 166 160 device->oclass[NVDEV_SUBDEV_FB ] = &nv47_fb_oclass; 167 161 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 178 170 device->cname = "G71"; 179 171 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 180 172 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 181 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 173 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 182 174 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 183 175 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 184 176 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 185 177 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 178 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 186 179 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 187 180 device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass; 188 181 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 199 190 device->cname = "G73"; 200 191 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 201 192 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 202 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 193 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 203 194 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 204 195 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 205 196 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 206 197 device->oclass[NVDEV_SUBDEV_MC ] = &nv04_mc_oclass; 198 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 207 199 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 208 200 device->oclass[NVDEV_SUBDEV_FB ] = &nv49_fb_oclass; 209 201 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 220 210 device->cname = "NV44"; 221 211 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 222 212 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 223 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 213 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 224 214 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 225 215 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 226 216 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 227 217 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 218 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 228 219 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 229 220 device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass; 230 221 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 241 230 device->cname = "G72"; 242 231 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 243 232 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 244 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 233 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 245 234 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 246 235 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 247 236 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 248 237 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 238 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 249 239 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 250 240 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 251 241 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 262 250 device->cname = "NV44A"; 263 251 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 264 252 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 265 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 253 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 266 254 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 267 255 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 268 256 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 269 257 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 258 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 270 259 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 271 260 device->oclass[NVDEV_SUBDEV_FB ] = &nv44_fb_oclass; 272 261 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 283 270 device->cname = "C61"; 284 271 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 285 272 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 286 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 273 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 287 274 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 288 275 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 289 276 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 290 277 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 278 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 291 279 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 292 280 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 293 281 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 304 290 device->cname = "C51"; 305 291 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 306 292 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 307 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 293 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv4e_i2c_oclass; 308 294 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 309 295 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 310 296 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 311 297 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 298 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 312 299 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 313 300 device->oclass[NVDEV_SUBDEV_FB ] = &nv4e_fb_oclass; 314 301 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 325 310 device->cname = "C73"; 326 311 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 327 312 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 328 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 313 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 329 314 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 330 315 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 331 316 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 332 317 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 318 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 333 319 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 334 320 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 335 321 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 346 330 device->cname = "C67"; 347 331 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 348 332 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 349 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 333 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 350 334 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 351 335 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 352 336 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 353 337 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 338 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 354 339 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 355 340 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 356 341 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass; ··· 367 350 device->cname = "C68"; 368 351 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 369 352 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 370 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 353 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 371 354 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 372 355 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 373 356 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv1a_devinit_oclass; 374 357 device->oclass[NVDEV_SUBDEV_MC ] = &nv44_mc_oclass; 358 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv31_bus_oclass; 375 359 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 376 360 device->oclass[NVDEV_SUBDEV_FB ] = &nv46_fb_oclass; 377 361 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv40_instmem_oclass;
+33 -18
drivers/gpu/drm/nouveau/core/subdev/device/nv50.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/gpio.h> 28 29 #include <subdev/i2c.h> 29 30 #include <subdev/clock.h> ··· 58 57 device->cname = "G80"; 59 58 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 60 59 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 61 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 60 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 62 61 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 63 62 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 64 63 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 65 64 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 66 65 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 66 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 67 67 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 68 68 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 69 69 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 81 79 device->cname = "G84"; 82 80 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 83 81 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 84 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 82 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 85 83 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 86 84 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 87 85 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 88 86 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 89 87 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 88 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 90 89 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 91 90 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 92 91 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 107 104 device->cname = "G86"; 108 105 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 109 106 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 110 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 107 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 111 108 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 112 109 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 113 110 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 114 111 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 115 112 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 113 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 116 114 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 117 115 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 118 116 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 133 129 device->cname = "G92"; 134 130 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 135 131 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 136 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 132 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 137 133 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 138 134 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 139 135 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 140 136 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 141 137 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 138 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 142 139 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 143 140 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 144 141 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 159 154 device->cname = "G94"; 160 155 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 161 156 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 162 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 157 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 163 158 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 164 159 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 165 160 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 166 161 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 167 162 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 163 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 168 164 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 169 165 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 170 166 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 185 179 device->cname = "G96"; 186 180 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 187 181 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 188 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 182 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 189 183 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 190 184 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 191 185 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 192 186 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 193 187 device->oclass[NVDEV_SUBDEV_MC ] = &nv50_mc_oclass; 188 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 194 189 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 195 190 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 196 191 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 211 204 device->cname = "G98"; 212 205 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 213 206 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 214 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 207 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 215 208 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 216 209 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 217 210 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 218 211 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 219 212 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 213 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 220 214 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 221 215 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 222 216 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 237 229 device->cname = "G200"; 238 230 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 239 231 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 240 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 232 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 241 233 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 242 234 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 243 235 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 244 236 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 245 237 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 238 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 246 239 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 247 240 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 248 241 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 263 254 device->cname = "MCP77/MCP78"; 264 255 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 265 256 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 266 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 257 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 267 258 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 268 259 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 269 260 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 270 261 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 271 262 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 263 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 272 264 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 273 265 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 274 266 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 289 279 device->cname = "MCP79/MCP7A"; 290 280 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 291 281 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 292 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 282 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 293 283 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv50_clock_oclass; 294 284 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 295 285 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 296 286 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 297 287 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 288 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 298 289 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 299 290 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 300 291 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 315 304 device->cname = "GT215"; 316 305 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 317 306 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 318 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 307 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 319 308 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 320 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 309 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 321 310 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 322 311 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 323 312 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 313 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 324 314 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 325 315 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 326 316 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 342 330 device->cname = "GT216"; 343 331 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 344 332 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 345 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 333 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 346 334 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 347 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 335 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 348 336 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 349 337 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 350 338 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 339 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 351 340 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 352 341 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 353 342 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 368 355 device->cname = "GT218"; 369 356 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 370 357 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 371 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 358 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 372 359 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 373 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 360 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 374 361 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 375 362 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 376 363 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 364 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 377 365 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 378 366 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 379 367 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass; ··· 394 380 device->cname = "MCP89"; 395 381 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 396 382 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 397 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 383 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 398 384 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 399 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 385 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 400 386 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 401 387 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 402 388 device->oclass[NVDEV_SUBDEV_MC ] = &nv98_mc_oclass; 389 + device->oclass[NVDEV_SUBDEV_BUS ] = &nv50_bus_oclass; 403 390 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 404 391 device->oclass[NVDEV_SUBDEV_FB ] = &nv50_fb_oclass; 405 392 device->oclass[NVDEV_SUBDEV_INSTMEM] = &nv50_instmem_oclass;
+26 -17
drivers/gpu/drm/nouveau/core/subdev/device/nvc0.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/gpio.h> 28 29 #include <subdev/i2c.h> 29 30 #include <subdev/clock.h> ··· 58 57 device->cname = "GF100"; 59 58 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 60 59 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 61 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 60 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 62 61 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 63 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 62 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 64 63 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 65 64 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 66 65 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 66 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 67 67 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 68 68 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 69 69 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 87 85 device->cname = "GF104"; 88 86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 89 87 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 90 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 88 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 91 89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 92 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 90 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 93 91 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 94 92 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 95 93 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 94 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 96 95 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 97 96 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 98 97 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 116 113 device->cname = "GF106"; 117 114 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 118 115 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 119 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 116 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 120 117 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 121 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 118 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 122 119 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 123 120 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 124 121 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 122 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 125 123 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 126 124 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 127 125 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 145 141 device->cname = "GF114"; 146 142 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 147 143 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 148 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 144 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 149 145 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 150 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 146 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 151 147 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 152 148 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 153 149 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 150 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 154 151 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 155 152 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 156 153 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 174 169 device->cname = "GF116"; 175 170 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 176 171 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 177 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 172 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 178 173 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 179 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 174 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 180 175 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 181 176 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 182 177 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 178 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 183 179 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 184 180 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 185 181 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 203 197 device->cname = "GF108"; 204 198 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 205 199 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 206 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 200 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 207 201 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 208 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 202 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 209 203 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 210 204 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 211 205 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 206 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 212 207 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 213 208 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 214 209 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 232 225 device->cname = "GF110"; 233 226 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 234 227 device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 235 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 228 + device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 236 229 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 237 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 230 + device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 238 231 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 239 232 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 240 233 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 234 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 241 235 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 242 236 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 243 237 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 261 253 device->cname = "GF119"; 262 254 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 263 255 device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 264 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 256 + device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 265 257 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 266 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 258 + device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 267 259 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 268 260 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 269 261 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 262 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 270 263 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 271 264 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 272 265 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 291 282 } 292 283 293 284 return 0; 294 - } 285 + }
+13 -9
drivers/gpu/drm/nouveau/core/subdev/device/nve0.c
··· 24 24 25 25 #include <subdev/device.h> 26 26 #include <subdev/bios.h> 27 + #include <subdev/bus.h> 27 28 #include <subdev/gpio.h> 28 29 #include <subdev/i2c.h> 29 30 #include <subdev/clock.h> ··· 57 56 case 0xe4: 58 57 device->cname = "GK104"; 59 58 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 60 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 61 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 59 + device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 60 + device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 62 61 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 63 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 62 + device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 64 63 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 65 64 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 66 65 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 66 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 67 67 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 68 68 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 69 69 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 86 84 case 0xe7: 87 85 device->cname = "GK107"; 88 86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 89 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 90 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 87 + device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 88 + device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 91 89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 92 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 90 + device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 93 91 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 94 92 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 95 93 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 94 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 96 95 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 97 96 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 98 97 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass; ··· 115 112 case 0xe6: 116 113 device->cname = "GK106"; 117 114 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 118 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 119 - device->oclass[NVDEV_SUBDEV_I2C ] = &nouveau_i2c_oclass; 115 + device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 116 + device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 120 117 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 121 - device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 118 + device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 122 119 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; 123 120 device->oclass[NVDEV_SUBDEV_DEVINIT] = &nv50_devinit_oclass; 124 121 device->oclass[NVDEV_SUBDEV_MC ] = &nvc0_mc_oclass; 122 + device->oclass[NVDEV_SUBDEV_BUS ] = &nvc0_bus_oclass; 125 123 device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass; 126 124 device->oclass[NVDEV_SUBDEV_FB ] = &nvc0_fb_oclass; 127 125 device->oclass[NVDEV_SUBDEV_LTCG ] = &nvc0_ltcg_oclass;
+8 -6
drivers/gpu/drm/nouveau/core/subdev/devinit/nv50.c
··· 78 78 if (ret) 79 79 return ret; 80 80 81 - /* if we ran the init tables, execute first script pointer for each 82 - * display table output entry that has a matching dcb entry. 81 + /* if we ran the init tables, we have to execute the first script 82 + * pointer of each dcb entry's display encoder table in order 83 + * to properly initialise each encoder. 83 84 */ 84 - while (priv->base.post && ver) { 85 - u16 data = nvbios_outp_parse(bios, i++, &ver, &hdr, &cnt, &len, &info); 86 - if (data && dcb_outp_match(bios, info.type, info.mask, &ver, &len, &outp)) { 85 + while (priv->base.post && dcb_outp_parse(bios, i, &ver, &hdr, &outp)) { 86 + if (nvbios_outp_match(bios, outp.hasht, outp.hashm, 87 + &ver, &hdr, &cnt, &len, &info)) { 87 88 struct nvbios_init init = { 88 89 .subdev = nv_subdev(priv), 89 90 .bios = bios, ··· 96 95 97 96 nvbios_exec(&init); 98 97 } 99 - }; 98 + i++; 99 + } 100 100 101 101 return 0; 102 102 }
+45 -21
drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <core/object.h> 25 + #include <core/client.h> 26 26 #include <core/enum.h> 27 + #include <core/engctx.h> 28 + #include <core/object.h> 27 29 28 30 #include <subdev/fb.h> 29 31 #include <subdev/bios.h> ··· 304 302 }; 305 303 306 304 static const struct nouveau_enum vm_engine[] = { 307 - { 0x00000000, "PGRAPH", NULL }, 308 - { 0x00000001, "PVP", NULL }, 305 + { 0x00000000, "PGRAPH", NULL, NVDEV_ENGINE_GR }, 306 + { 0x00000001, "PVP", NULL, NVDEV_ENGINE_VP }, 309 307 { 0x00000004, "PEEPHOLE", NULL }, 310 - { 0x00000005, "PFIFO", vm_pfifo_subclients }, 308 + { 0x00000005, "PFIFO", vm_pfifo_subclients, NVDEV_ENGINE_FIFO }, 311 309 { 0x00000006, "BAR", vm_bar_subclients }, 312 - { 0x00000008, "PPPP", NULL }, 313 - { 0x00000009, "PBSP", NULL }, 314 - { 0x0000000a, "PCRYPT", NULL }, 310 + { 0x00000008, "PPPP", NULL, NVDEV_ENGINE_PPP }, 311 + { 0x00000008, "PMPEG", NULL, NVDEV_ENGINE_MPEG }, 312 + { 0x00000009, "PBSP", NULL, NVDEV_ENGINE_BSP }, 313 + { 0x0000000a, "PCRYPT", NULL, NVDEV_ENGINE_CRYPT }, 315 314 { 0x0000000b, "PCOUNTER", NULL }, 316 315 { 0x0000000c, "SEMAPHORE_BG", NULL }, 317 - { 0x0000000d, "PCOPY", NULL }, 316 + { 0x0000000d, "PCOPY", NULL, NVDEV_ENGINE_COPY0 }, 318 317 { 0x0000000e, "PDAEMON", NULL }, 319 318 {} 320 319 }; ··· 337 334 nv50_fb_intr(struct nouveau_subdev *subdev) 338 335 { 339 336 struct nouveau_device *device = nv_device(subdev); 337 + struct nouveau_engine *engine; 340 338 struct nv50_fb_priv *priv = (void *)subdev; 341 339 const struct nouveau_enum *en, *cl; 340 + struct nouveau_object *engctx = NULL; 342 341 u32 trap[6], idx, chan; 343 342 u8 st0, st1, st2, st3; 344 343 int i; ··· 371 366 } 372 367 chan = (trap[2] << 16) | trap[1]; 373 368 374 - nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x ", 375 - (trap[5] & 0x00000100) ? "read" : "write", 376 - trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan); 377 - 378 369 en = nouveau_enum_find(vm_engine, st0); 370 + 371 + if (en && en->data2) { 372 + const struct nouveau_enum *orig_en = en; 373 + while (en->name && en->value == st0 && en->data2) { 374 + engine = nouveau_engine(subdev, en->data2); 375 + if (engine) { 376 + engctx = nouveau_engctx_get(engine, chan); 377 + if (engctx) 378 + break; 379 + } 380 + en++; 381 + } 382 + if (!engctx) 383 + en = orig_en; 384 + } 385 + 386 + nv_error(priv, "trapped %s at 0x%02x%04x%04x on channel 0x%08x [%s] ", 387 + (trap[5] & 0x00000100) ? "read" : "write", 388 + trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, chan, 389 + nouveau_client_name(engctx)); 390 + 391 + nouveau_engctx_put(engctx); 392 + 379 393 if (en) 380 - printk("%s/", en->name); 394 + pr_cont("%s/", en->name); 381 395 else 382 - printk("%02x/", st0); 396 + pr_cont("%02x/", st0); 383 397 384 398 cl = nouveau_enum_find(vm_client, st2); 385 399 if (cl) 386 - printk("%s/", cl->name); 400 + pr_cont("%s/", cl->name); 387 401 else 388 - printk("%02x/", st2); 402 + pr_cont("%02x/", st2); 389 403 390 404 if (cl && cl->data) cl = nouveau_enum_find(cl->data, st3); 391 405 else if (en && en->data) cl = nouveau_enum_find(en->data, st3); 392 406 else cl = NULL; 393 407 if (cl) 394 - printk("%s", cl->name); 408 + pr_cont("%s", cl->name); 395 409 else 396 - printk("%02x", st3); 410 + pr_cont("%02x", st3); 397 411 398 - printk(" reason: "); 412 + pr_cont(" reason: "); 399 413 en = nouveau_enum_find(vm_fault, st1); 400 414 if (en) 401 - printk("%s\n", en->name); 415 + pr_cont("%s\n", en->name); 402 416 else 403 - printk("0x%08x\n", st1); 417 + pr_cont("0x%08x\n", st1); 404 418 } 405 419 406 420 static int
+11 -129
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
··· 102 102 return ret; 103 103 } 104 104 105 - static int 106 - nouveau_gpio_irq(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, bool on) 105 + void 106 + _nouveau_gpio_dtor(struct nouveau_object *object) 107 107 { 108 - struct dcb_gpio_func func; 109 - int ret; 110 - 111 - ret = nouveau_gpio_find(gpio, idx, tag, line, &func); 112 - if (ret == 0) { 113 - if (idx == 0 && gpio->irq_enable) 114 - gpio->irq_enable(gpio, func.line, on); 115 - else 116 - ret = -ENODEV; 117 - } 118 - 119 - return ret; 120 - } 121 - 122 - struct gpio_isr { 123 - struct nouveau_gpio *gpio; 124 - struct list_head head; 125 - struct work_struct work; 126 - int idx; 127 - struct dcb_gpio_func func; 128 - void (*handler)(void *, int); 129 - void *data; 130 - bool inhibit; 131 - }; 132 - 133 - static void 134 - nouveau_gpio_isr_bh(struct work_struct *work) 135 - { 136 - struct gpio_isr *isr = container_of(work, struct gpio_isr, work); 137 - struct nouveau_gpio *gpio = isr->gpio; 138 - unsigned long flags; 139 - int state; 140 - 141 - state = nouveau_gpio_get(gpio, isr->idx, isr->func.func, 142 - isr->func.line); 143 - if (state >= 0) 144 - isr->handler(isr->data, state); 145 - 146 - spin_lock_irqsave(&gpio->lock, flags); 147 - isr->inhibit = false; 148 - spin_unlock_irqrestore(&gpio->lock, flags); 149 - } 150 - 151 - static void 152 - nouveau_gpio_isr_run(struct nouveau_gpio *gpio, int idx, u32 line_mask) 153 - { 154 - struct gpio_isr *isr; 155 - 156 - if (idx != 0) 157 - return; 158 - 159 - spin_lock(&gpio->lock); 160 - list_for_each_entry(isr, &gpio->isr, head) { 161 - if (line_mask & (1 << isr->func.line)) { 162 - if (isr->inhibit) 163 - continue; 164 - isr->inhibit = true; 165 - schedule_work(&isr->work); 166 - } 167 - } 168 - spin_unlock(&gpio->lock); 169 - } 170 - 171 - static int 172 - nouveau_gpio_isr_add(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, 173 - void (*handler)(void *, int), void *data) 174 - { 175 - struct gpio_isr *isr; 176 - unsigned long flags; 177 - int ret; 178 - 179 - isr = kzalloc(sizeof(*isr), GFP_KERNEL); 180 - if (!isr) 181 - return -ENOMEM; 182 - 183 - ret = nouveau_gpio_find(gpio, idx, tag, line, &isr->func); 184 - if (ret) { 185 - kfree(isr); 186 - return ret; 187 - } 188 - 189 - INIT_WORK(&isr->work, nouveau_gpio_isr_bh); 190 - isr->gpio = gpio; 191 - isr->handler = handler; 192 - isr->data = data; 193 - isr->idx = idx; 194 - 195 - spin_lock_irqsave(&gpio->lock, flags); 196 - list_add(&isr->head, &gpio->isr); 197 - spin_unlock_irqrestore(&gpio->lock, flags); 198 - return 0; 199 - } 200 - 201 - static void 202 - nouveau_gpio_isr_del(struct nouveau_gpio *gpio, int idx, u8 tag, u8 line, 203 - void (*handler)(void *, int), void *data) 204 - { 205 - struct gpio_isr *isr, *tmp; 206 - struct dcb_gpio_func func; 207 - unsigned long flags; 208 - LIST_HEAD(tofree); 209 - int ret; 210 - 211 - ret = nouveau_gpio_find(gpio, idx, tag, line, &func); 212 - if (ret == 0) { 213 - spin_lock_irqsave(&gpio->lock, flags); 214 - list_for_each_entry_safe(isr, tmp, &gpio->isr, head) { 215 - if (memcmp(&isr->func, &func, sizeof(func)) || 216 - isr->idx != idx || 217 - isr->handler != handler || isr->data != data) 218 - continue; 219 - list_move_tail(&isr->head, &tofree); 220 - } 221 - spin_unlock_irqrestore(&gpio->lock, flags); 222 - 223 - list_for_each_entry_safe(isr, tmp, &tofree, head) { 224 - flush_work(&isr->work); 225 - kfree(isr); 226 - } 227 - } 108 + struct nouveau_gpio *gpio = (void *)object; 109 + nouveau_event_destroy(&gpio->events); 110 + nouveau_subdev_destroy(&gpio->base); 228 111 } 229 112 230 113 int 231 114 nouveau_gpio_create_(struct nouveau_object *parent, 232 115 struct nouveau_object *engine, 233 - struct nouveau_oclass *oclass, int length, void **pobject) 116 + struct nouveau_oclass *oclass, int lines, 117 + int length, void **pobject) 234 118 { 235 119 struct nouveau_gpio *gpio; 236 120 int ret; ··· 125 241 if (ret) 126 242 return ret; 127 243 244 + ret = nouveau_event_create(lines, &gpio->events); 245 + if (ret) 246 + return ret; 247 + 128 248 gpio->find = nouveau_gpio_find; 129 249 gpio->set = nouveau_gpio_set; 130 250 gpio->get = nouveau_gpio_get; 131 - gpio->irq = nouveau_gpio_irq; 132 - gpio->isr_run = nouveau_gpio_isr_run; 133 - gpio->isr_add = nouveau_gpio_isr_add; 134 - gpio->isr_del = nouveau_gpio_isr_del; 135 - INIT_LIST_HEAD(&gpio->isr); 136 - spin_lock_init(&gpio->lock); 137 251 return 0; 138 252 } 139 253
+24 -16
drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
··· 24 24 * 25 25 */ 26 26 27 - #include <subdev/gpio.h> 27 + #include "priv.h" 28 28 29 29 struct nv10_gpio_priv { 30 30 struct nouveau_gpio base; ··· 83 83 } 84 84 85 85 static void 86 - nv10_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) 87 - { 88 - u32 mask = 0x00010001 << line; 89 - 90 - nv_wr32(gpio, 0x001104, mask); 91 - nv_mask(gpio, 0x001144, mask, on ? mask : 0); 92 - } 93 - 94 - static void 95 86 nv10_gpio_intr(struct nouveau_subdev *subdev) 96 87 { 97 88 struct nv10_gpio_priv *priv = (void *)subdev; 98 89 u32 intr = nv_rd32(priv, 0x001104); 99 90 u32 hi = (intr & 0x0000ffff) >> 0; 100 91 u32 lo = (intr & 0xffff0000) >> 16; 92 + int i; 101 93 102 - priv->base.isr_run(&priv->base, 0, hi | lo); 94 + for (i = 0; (hi | lo) && i < 32; i++) { 95 + if ((hi | lo) & (1 << i)) 96 + nouveau_event_trigger(priv->base.events, i); 97 + } 103 98 104 99 nv_wr32(priv, 0x001104, intr); 100 + } 101 + 102 + static void 103 + nv10_gpio_intr_enable(struct nouveau_event *event, int line) 104 + { 105 + nv_wr32(event->priv, 0x001104, 0x00010001 << line); 106 + nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00010001 << line); 107 + } 108 + 109 + static void 110 + nv10_gpio_intr_disable(struct nouveau_event *event, int line) 111 + { 112 + nv_wr32(event->priv, 0x001104, 0x00010001 << line); 113 + nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00000000); 105 114 } 106 115 107 116 static int ··· 121 112 struct nv10_gpio_priv *priv; 122 113 int ret; 123 114 124 - ret = nouveau_gpio_create(parent, engine, oclass, &priv); 115 + ret = nouveau_gpio_create(parent, engine, oclass, 16, &priv); 125 116 *pobject = nv_object(priv); 126 117 if (ret) 127 118 return ret; 128 119 129 120 priv->base.drive = nv10_gpio_drive; 130 121 priv->base.sense = nv10_gpio_sense; 131 - priv->base.irq_enable = nv10_gpio_irq_enable; 122 + priv->base.events->priv = priv; 123 + priv->base.events->enable = nv10_gpio_intr_enable; 124 + priv->base.events->disable = nv10_gpio_intr_disable; 132 125 nv_subdev(priv)->intr = nv10_gpio_intr; 133 126 return 0; 134 127 } ··· 152 141 if (ret) 153 142 return ret; 154 143 155 - nv_wr32(priv, 0x001140, 0x00000000); 156 - nv_wr32(priv, 0x001100, 0xffffffff); 157 144 nv_wr32(priv, 0x001144, 0x00000000); 158 145 nv_wr32(priv, 0x001104, 0xffffffff); 159 146 return 0; ··· 161 152 nv10_gpio_fini(struct nouveau_object *object, bool suspend) 162 153 { 163 154 struct nv10_gpio_priv *priv = (void *)object; 164 - nv_wr32(priv, 0x001140, 0x00000000); 165 155 nv_wr32(priv, 0x001144, 0x00000000); 166 156 return nouveau_gpio_fini(&priv->base, suspend); 167 157 }
+31 -14
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <subdev/gpio.h> 25 + #include "priv.h" 26 26 27 27 struct nv50_gpio_priv { 28 28 struct nouveau_gpio base; ··· 95 95 } 96 96 97 97 void 98 - nv50_gpio_irq_enable(struct nouveau_gpio *gpio, int line, bool on) 99 - { 100 - u32 reg = line < 16 ? 0xe050 : 0xe070; 101 - u32 mask = 0x00010001 << (line & 0xf); 102 - 103 - nv_wr32(gpio, reg + 4, mask); 104 - nv_mask(gpio, reg + 0, mask, on ? mask : 0); 105 - } 106 - 107 - void 108 98 nv50_gpio_intr(struct nouveau_subdev *subdev) 109 99 { 110 100 struct nv50_gpio_priv *priv = (void *)subdev; 111 101 u32 intr0, intr1 = 0; 112 102 u32 hi, lo; 103 + int i; 113 104 114 105 intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); 115 106 if (nv_device(priv)->chipset >= 0x90) ··· 108 117 109 118 hi = (intr0 & 0x0000ffff) | (intr1 << 16); 110 119 lo = (intr0 >> 16) | (intr1 & 0xffff0000); 111 - priv->base.isr_run(&priv->base, 0, hi | lo); 120 + 121 + for (i = 0; (hi | lo) && i < 32; i++) { 122 + if ((hi | lo) & (1 << i)) 123 + nouveau_event_trigger(priv->base.events, i); 124 + } 112 125 113 126 nv_wr32(priv, 0xe054, intr0); 114 127 if (nv_device(priv)->chipset >= 0x90) 115 128 nv_wr32(priv, 0xe074, intr1); 129 + } 130 + 131 + void 132 + nv50_gpio_intr_enable(struct nouveau_event *event, int line) 133 + { 134 + const u32 addr = line < 16 ? 0xe050 : 0xe070; 135 + const u32 mask = 0x00010001 << (line & 0xf); 136 + nv_wr32(event->priv, addr + 0x04, mask); 137 + nv_mask(event->priv, addr + 0x00, mask, mask); 138 + } 139 + 140 + void 141 + nv50_gpio_intr_disable(struct nouveau_event *event, int line) 142 + { 143 + const u32 addr = line < 16 ? 0xe050 : 0xe070; 144 + const u32 mask = 0x00010001 << (line & 0xf); 145 + nv_wr32(event->priv, addr + 0x04, mask); 146 + nv_mask(event->priv, addr + 0x00, mask, 0x00000000); 116 147 } 117 148 118 149 static int ··· 145 132 struct nv50_gpio_priv *priv; 146 133 int ret; 147 134 148 - ret = nouveau_gpio_create(parent, engine, oclass, &priv); 135 + ret = nouveau_gpio_create(parent, engine, oclass, 136 + nv_device(parent)->chipset >= 0x90 ? 32 : 16, 137 + &priv); 149 138 *pobject = nv_object(priv); 150 139 if (ret) 151 140 return ret; ··· 155 140 priv->base.reset = nv50_gpio_reset; 156 141 priv->base.drive = nv50_gpio_drive; 157 142 priv->base.sense = nv50_gpio_sense; 158 - priv->base.irq_enable = nv50_gpio_irq_enable; 143 + priv->base.events->priv = priv; 144 + priv->base.events->enable = nv50_gpio_intr_enable; 145 + priv->base.events->disable = nv50_gpio_intr_disable; 159 146 nv_subdev(priv)->intr = nv50_gpio_intr; 160 147 return 0; 161 148 }
+8 -6
drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <subdev/gpio.h> 25 + #include "priv.h" 26 26 27 27 struct nvd0_gpio_priv { 28 28 struct nouveau_gpio base; 29 29 }; 30 30 31 - static void 31 + void 32 32 nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) 33 33 { 34 34 struct nouveau_bios *bios = nouveau_bios(gpio); ··· 57 57 } 58 58 } 59 59 60 - static int 60 + int 61 61 nvd0_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) 62 62 { 63 63 u32 data = ((dir ^ 1) << 13) | (out << 12); ··· 66 66 return 0; 67 67 } 68 68 69 - static int 69 + int 70 70 nvd0_gpio_sense(struct nouveau_gpio *gpio, int line) 71 71 { 72 72 return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); ··· 80 80 struct nvd0_gpio_priv *priv; 81 81 int ret; 82 82 83 - ret = nouveau_gpio_create(parent, engine, oclass, &priv); 83 + ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); 84 84 *pobject = nv_object(priv); 85 85 if (ret) 86 86 return ret; ··· 88 88 priv->base.reset = nvd0_gpio_reset; 89 89 priv->base.drive = nvd0_gpio_drive; 90 90 priv->base.sense = nvd0_gpio_sense; 91 - priv->base.irq_enable = nv50_gpio_irq_enable; 91 + priv->base.events->priv = priv; 92 + priv->base.events->enable = nv50_gpio_intr_enable; 93 + priv->base.events->disable = nv50_gpio_intr_disable; 92 94 nv_subdev(priv)->intr = nv50_gpio_intr; 93 95 return 0; 94 96 }
+131
drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c
··· 1 + /* 2 + * Copyright 2012 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 "priv.h" 26 + 27 + struct nve0_gpio_priv { 28 + struct nouveau_gpio base; 29 + }; 30 + 31 + void 32 + nve0_gpio_intr(struct nouveau_subdev *subdev) 33 + { 34 + struct nve0_gpio_priv *priv = (void *)subdev; 35 + u32 intr0 = nv_rd32(priv, 0xdc00) & nv_rd32(priv, 0xdc08); 36 + u32 intr1 = nv_rd32(priv, 0xdc80) & nv_rd32(priv, 0xdc88); 37 + u32 hi = (intr0 & 0x0000ffff) | (intr1 << 16); 38 + u32 lo = (intr0 >> 16) | (intr1 & 0xffff0000); 39 + int i; 40 + 41 + for (i = 0; (hi | lo) && i < 32; i++) { 42 + if ((hi | lo) & (1 << i)) 43 + nouveau_event_trigger(priv->base.events, i); 44 + } 45 + 46 + nv_wr32(priv, 0xdc00, intr0); 47 + nv_wr32(priv, 0xdc88, intr1); 48 + } 49 + 50 + void 51 + nve0_gpio_intr_enable(struct nouveau_event *event, int line) 52 + { 53 + const u32 addr = line < 16 ? 0xdc00 : 0xdc80; 54 + const u32 mask = 0x00010001 << (line & 0xf); 55 + nv_wr32(event->priv, addr + 0x08, mask); 56 + nv_mask(event->priv, addr + 0x00, mask, mask); 57 + } 58 + 59 + void 60 + nve0_gpio_intr_disable(struct nouveau_event *event, int line) 61 + { 62 + const u32 addr = line < 16 ? 0xdc00 : 0xdc80; 63 + const u32 mask = 0x00010001 << (line & 0xf); 64 + nv_wr32(event->priv, addr + 0x08, mask); 65 + nv_mask(event->priv, addr + 0x00, mask, 0x00000000); 66 + } 67 + 68 + int 69 + nve0_gpio_fini(struct nouveau_object *object, bool suspend) 70 + { 71 + struct nve0_gpio_priv *priv = (void *)object; 72 + nv_wr32(priv, 0xdc08, 0x00000000); 73 + nv_wr32(priv, 0xdc88, 0x00000000); 74 + return nouveau_gpio_fini(&priv->base, suspend); 75 + } 76 + 77 + int 78 + nve0_gpio_init(struct nouveau_object *object) 79 + { 80 + struct nve0_gpio_priv *priv = (void *)object; 81 + int ret; 82 + 83 + ret = nouveau_gpio_init(&priv->base); 84 + if (ret) 85 + return ret; 86 + 87 + nv_wr32(priv, 0xdc00, 0xffffffff); 88 + nv_wr32(priv, 0xdc80, 0xffffffff); 89 + return 0; 90 + } 91 + 92 + void 93 + nve0_gpio_dtor(struct nouveau_object *object) 94 + { 95 + struct nve0_gpio_priv *priv = (void *)object; 96 + nouveau_gpio_destroy(&priv->base); 97 + } 98 + 99 + static int 100 + nve0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 101 + struct nouveau_oclass *oclass, void *data, u32 size, 102 + struct nouveau_object **pobject) 103 + { 104 + struct nve0_gpio_priv *priv; 105 + int ret; 106 + 107 + ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); 108 + *pobject = nv_object(priv); 109 + if (ret) 110 + return ret; 111 + 112 + priv->base.reset = nvd0_gpio_reset; 113 + priv->base.drive = nvd0_gpio_drive; 114 + priv->base.sense = nvd0_gpio_sense; 115 + priv->base.events->priv = priv; 116 + priv->base.events->enable = nve0_gpio_intr_enable; 117 + priv->base.events->disable = nve0_gpio_intr_disable; 118 + nv_subdev(priv)->intr = nve0_gpio_intr; 119 + return 0; 120 + } 121 + 122 + struct nouveau_oclass 123 + nve0_gpio_oclass = { 124 + .handle = NV_SUBDEV(GPIO, 0xe0), 125 + .ofuncs = &(struct nouveau_ofuncs) { 126 + .ctor = nve0_gpio_ctor, 127 + .dtor = nv50_gpio_dtor, 128 + .init = nve0_gpio_init, 129 + .fini = nve0_gpio_fini, 130 + }, 131 + };
+17
drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h
··· 1 + #ifndef __NVKM_GPIO_H__ 2 + #define __NVKM_GPIO_H__ 3 + 4 + #include <subdev/gpio.h> 5 + 6 + void nv50_gpio_dtor(struct nouveau_object *); 7 + int nv50_gpio_init(struct nouveau_object *); 8 + int nv50_gpio_fini(struct nouveau_object *, bool); 9 + void nv50_gpio_intr(struct nouveau_subdev *); 10 + void nv50_gpio_intr_enable(struct nouveau_event *, int line); 11 + void nv50_gpio_intr_disable(struct nouveau_event *, int line); 12 + 13 + void nvd0_gpio_reset(struct nouveau_gpio *, u8); 14 + int nvd0_gpio_drive(struct nouveau_gpio *, int, int, int); 15 + int nvd0_gpio_sense(struct nouveau_gpio *, int); 16 + 17 + #endif
+279
drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
··· 1 + /* 2 + * Copyright 2013 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 + 25 + #include <subdev/i2c.h> 26 + 27 + struct anx9805_i2c_port { 28 + struct nouveau_i2c_port base; 29 + u32 addr; 30 + u32 ctrl; 31 + }; 32 + 33 + static int 34 + anx9805_train(struct nouveau_i2c_port *port, int link_nr, int link_bw, bool enh) 35 + { 36 + struct anx9805_i2c_port *chan = (void *)port; 37 + struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent; 38 + u8 tmp, i; 39 + 40 + nv_wri2cr(mast, chan->addr, 0xa0, link_bw); 41 + nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00)); 42 + nv_wri2cr(mast, chan->addr, 0xa2, 0x01); 43 + nv_wri2cr(mast, chan->addr, 0xa8, 0x01); 44 + 45 + i = 0; 46 + while ((tmp = nv_rdi2cr(mast, chan->addr, 0xa8)) & 0x01) { 47 + mdelay(5); 48 + if (i++ == 100) { 49 + nv_error(port, "link training timed out\n"); 50 + return -ETIMEDOUT; 51 + } 52 + } 53 + 54 + if (tmp & 0x70) { 55 + nv_error(port, "link training failed: 0x%02x\n", tmp); 56 + return -EIO; 57 + } 58 + 59 + return 1; 60 + } 61 + 62 + static int 63 + anx9805_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size) 64 + { 65 + struct anx9805_i2c_port *chan = (void *)port; 66 + struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent; 67 + int i, ret = -ETIMEDOUT; 68 + u8 tmp; 69 + 70 + tmp = nv_rdi2cr(mast, chan->ctrl, 0x07) & ~0x04; 71 + nv_wri2cr(mast, chan->ctrl, 0x07, tmp | 0x04); 72 + nv_wri2cr(mast, chan->ctrl, 0x07, tmp); 73 + nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); 74 + 75 + nv_wri2cr(mast, chan->addr, 0xe4, 0x80); 76 + for (i = 0; !(type & 1) && i < size; i++) 77 + nv_wri2cr(mast, chan->addr, 0xf0 + i, data[i]); 78 + nv_wri2cr(mast, chan->addr, 0xe5, ((size - 1) << 4) | type); 79 + nv_wri2cr(mast, chan->addr, 0xe6, (addr & 0x000ff) >> 0); 80 + nv_wri2cr(mast, chan->addr, 0xe7, (addr & 0x0ff00) >> 8); 81 + nv_wri2cr(mast, chan->addr, 0xe8, (addr & 0xf0000) >> 16); 82 + nv_wri2cr(mast, chan->addr, 0xe9, 0x01); 83 + 84 + i = 0; 85 + while ((tmp = nv_rdi2cr(mast, chan->addr, 0xe9)) & 0x01) { 86 + mdelay(5); 87 + if (i++ == 32) 88 + goto done; 89 + } 90 + 91 + if ((tmp = nv_rdi2cr(mast, chan->ctrl, 0xf7)) & 0x01) { 92 + ret = -EIO; 93 + goto done; 94 + } 95 + 96 + for (i = 0; (type & 1) && i < size; i++) 97 + data[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); 98 + ret = 0; 99 + done: 100 + nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); 101 + return ret; 102 + } 103 + 104 + static const struct nouveau_i2c_func 105 + anx9805_aux_func = { 106 + .aux = anx9805_aux, 107 + .lnk_ctl = anx9805_train, 108 + }; 109 + 110 + static int 111 + anx9805_aux_chan_ctor(struct nouveau_object *parent, 112 + struct nouveau_object *engine, 113 + struct nouveau_oclass *oclass, void *data, u32 index, 114 + struct nouveau_object **pobject) 115 + { 116 + struct nouveau_i2c_port *mast = (void *)parent; 117 + struct anx9805_i2c_port *chan; 118 + int ret; 119 + 120 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 121 + &nouveau_i2c_aux_algo, &chan); 122 + *pobject = nv_object(chan); 123 + if (ret) 124 + return ret; 125 + 126 + switch ((oclass->handle & 0xff00) >> 8) { 127 + case 0x0d: 128 + chan->addr = 0x38; 129 + chan->ctrl = 0x39; 130 + break; 131 + case 0x0e: 132 + chan->addr = 0x3c; 133 + chan->ctrl = 0x3b; 134 + break; 135 + default: 136 + BUG_ON(1); 137 + } 138 + 139 + if (mast->adapter.algo == &i2c_bit_algo) { 140 + struct i2c_algo_bit_data *algo = mast->adapter.algo_data; 141 + algo->udelay = max(algo->udelay, 40); 142 + } 143 + 144 + chan->base.func = &anx9805_aux_func; 145 + return 0; 146 + } 147 + 148 + static struct nouveau_ofuncs 149 + anx9805_aux_ofuncs = { 150 + .ctor = anx9805_aux_chan_ctor, 151 + .dtor = _nouveau_i2c_port_dtor, 152 + .init = _nouveau_i2c_port_init, 153 + .fini = _nouveau_i2c_port_fini, 154 + }; 155 + 156 + static int 157 + anx9805_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 158 + { 159 + struct anx9805_i2c_port *port = adap->algo_data; 160 + struct nouveau_i2c_port *mast = (void *)nv_object(port)->parent; 161 + struct i2c_msg *msg = msgs; 162 + int ret = -ETIMEDOUT; 163 + int i, j, cnt = num; 164 + u8 seg = 0x00, off = 0x00, tmp; 165 + 166 + tmp = nv_rdi2cr(mast, port->ctrl, 0x07) & ~0x10; 167 + nv_wri2cr(mast, port->ctrl, 0x07, tmp | 0x10); 168 + nv_wri2cr(mast, port->ctrl, 0x07, tmp); 169 + nv_wri2cr(mast, port->addr, 0x43, 0x05); 170 + mdelay(5); 171 + 172 + while (cnt--) { 173 + if ( (msg->flags & I2C_M_RD) && msg->addr == 0x50) { 174 + nv_wri2cr(mast, port->addr, 0x40, msg->addr << 1); 175 + nv_wri2cr(mast, port->addr, 0x41, seg); 176 + nv_wri2cr(mast, port->addr, 0x42, off); 177 + nv_wri2cr(mast, port->addr, 0x44, msg->len); 178 + nv_wri2cr(mast, port->addr, 0x45, 0x00); 179 + nv_wri2cr(mast, port->addr, 0x43, 0x01); 180 + for (i = 0; i < msg->len; i++) { 181 + j = 0; 182 + while (nv_rdi2cr(mast, port->addr, 0x46) & 0x10) { 183 + mdelay(5); 184 + if (j++ == 32) 185 + goto done; 186 + } 187 + msg->buf[i] = nv_rdi2cr(mast, port->addr, 0x47); 188 + } 189 + } else 190 + if (!(msg->flags & I2C_M_RD)) { 191 + if (msg->addr == 0x50 && msg->len == 0x01) { 192 + off = msg->buf[0]; 193 + } else 194 + if (msg->addr == 0x30 && msg->len == 0x01) { 195 + seg = msg->buf[0]; 196 + } else 197 + goto done; 198 + } else { 199 + goto done; 200 + } 201 + msg++; 202 + } 203 + 204 + ret = num; 205 + done: 206 + nv_wri2cr(mast, port->addr, 0x43, 0x00); 207 + return ret; 208 + } 209 + 210 + static u32 211 + anx9805_func(struct i2c_adapter *adap) 212 + { 213 + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 214 + } 215 + 216 + static const struct i2c_algorithm 217 + anx9805_i2c_algo = { 218 + .master_xfer = anx9805_xfer, 219 + .functionality = anx9805_func 220 + }; 221 + 222 + static const struct nouveau_i2c_func 223 + anx9805_i2c_func = { 224 + }; 225 + 226 + static int 227 + anx9805_ddc_port_ctor(struct nouveau_object *parent, 228 + struct nouveau_object *engine, 229 + struct nouveau_oclass *oclass, void *data, u32 index, 230 + struct nouveau_object **pobject) 231 + { 232 + struct nouveau_i2c_port *mast = (void *)parent; 233 + struct anx9805_i2c_port *port; 234 + int ret; 235 + 236 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 237 + &anx9805_i2c_algo, &port); 238 + *pobject = nv_object(port); 239 + if (ret) 240 + return ret; 241 + 242 + switch ((oclass->handle & 0xff00) >> 8) { 243 + case 0x0d: 244 + port->addr = 0x3d; 245 + port->ctrl = 0x39; 246 + break; 247 + case 0x0e: 248 + port->addr = 0x3f; 249 + port->ctrl = 0x3b; 250 + break; 251 + default: 252 + BUG_ON(1); 253 + } 254 + 255 + if (mast->adapter.algo == &i2c_bit_algo) { 256 + struct i2c_algo_bit_data *algo = mast->adapter.algo_data; 257 + algo->udelay = max(algo->udelay, 40); 258 + } 259 + 260 + port->base.func = &anx9805_i2c_func; 261 + return 0; 262 + } 263 + 264 + static struct nouveau_ofuncs 265 + anx9805_ddc_ofuncs = { 266 + .ctor = anx9805_ddc_port_ctor, 267 + .dtor = _nouveau_i2c_port_dtor, 268 + .init = _nouveau_i2c_port_init, 269 + .fini = _nouveau_i2c_port_fini, 270 + }; 271 + 272 + struct nouveau_oclass 273 + nouveau_anx9805_sclass[] = { 274 + { .handle = NV_I2C_TYPE_EXTDDC(0x0d), .ofuncs = &anx9805_ddc_ofuncs }, 275 + { .handle = NV_I2C_TYPE_EXTAUX(0x0d), .ofuncs = &anx9805_aux_ofuncs }, 276 + { .handle = NV_I2C_TYPE_EXTDDC(0x0e), .ofuncs = &anx9805_ddc_ofuncs }, 277 + { .handle = NV_I2C_TYPE_EXTAUX(0x0e), .ofuncs = &anx9805_aux_ofuncs }, 278 + {} 279 + };
+21 -133
drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c
··· 24 24 25 25 #include <subdev/i2c.h> 26 26 27 - /****************************************************************************** 28 - * aux channel util functions 29 - *****************************************************************************/ 30 - #define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) 31 - #define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) 32 - 33 - static void 34 - auxch_fini(struct nouveau_i2c *aux, int ch) 27 + int 28 + nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size) 35 29 { 36 - nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); 37 - } 38 - 39 - static int 40 - auxch_init(struct nouveau_i2c *aux, int ch) 41 - { 42 - const u32 unksel = 1; /* nfi which to use, or if it matters.. */ 43 - const u32 ureq = unksel ? 0x00100000 : 0x00200000; 44 - const u32 urep = unksel ? 0x01000000 : 0x02000000; 45 - u32 ctrl, timeout; 46 - 47 - /* wait up to 1ms for any previous transaction to be done... */ 48 - timeout = 1000; 49 - do { 50 - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 51 - udelay(1); 52 - if (!timeout--) { 53 - AUX_ERR("begin idle timeout 0x%08x\n", ctrl); 54 - return -EBUSY; 55 - } 56 - } while (ctrl & 0x03010000); 57 - 58 - /* set some magic, and wait up to 1ms for it to appear */ 59 - nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); 60 - timeout = 1000; 61 - do { 62 - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 63 - udelay(1); 64 - if (!timeout--) { 65 - AUX_ERR("magic wait 0x%08x\n", ctrl); 66 - auxch_fini(aux, ch); 67 - return -EBUSY; 68 - } 69 - } while ((ctrl & 0x03000000) != urep); 70 - 71 - return 0; 72 - } 73 - 74 - static int 75 - auxch_tx(struct nouveau_i2c *aux, int ch, u8 type, u32 addr, u8 *data, u8 size) 76 - { 77 - u32 ctrl, stat, timeout, retries; 78 - u32 xbuf[4] = {}; 79 - int ret, i; 80 - 81 - AUX_DBG("%d: 0x%08x %d\n", type, addr, size); 82 - 83 - ret = auxch_init(aux, ch); 84 - if (ret) 85 - goto out; 86 - 87 - stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); 88 - if (!(stat & 0x10000000)) { 89 - AUX_DBG("sink not detected\n"); 90 - ret = -ENXIO; 91 - goto out; 30 + if (port->func->aux) { 31 + if (port->func->acquire) 32 + port->func->acquire(port); 33 + return port->func->aux(port, 9, addr, data, size); 92 34 } 93 - 94 - if (!(type & 1)) { 95 - memcpy(xbuf, data, size); 96 - for (i = 0; i < 16; i += 4) { 97 - AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); 98 - nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); 99 - } 100 - } 101 - 102 - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 103 - ctrl &= ~0x0001f0ff; 104 - ctrl |= type << 12; 105 - ctrl |= size - 1; 106 - nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); 107 - 108 - /* retry transaction a number of times on failure... */ 109 - ret = -EREMOTEIO; 110 - for (retries = 0; retries < 32; retries++) { 111 - /* reset, and delay a while if this is a retry */ 112 - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); 113 - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); 114 - if (retries) 115 - udelay(400); 116 - 117 - /* transaction request, wait up to 1ms for it to complete */ 118 - nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); 119 - 120 - timeout = 1000; 121 - do { 122 - ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 123 - udelay(1); 124 - if (!timeout--) { 125 - AUX_ERR("tx req timeout 0x%08x\n", ctrl); 126 - goto out; 127 - } 128 - } while (ctrl & 0x00010000); 129 - 130 - /* read status, and check if transaction completed ok */ 131 - stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); 132 - if (!(stat & 0x000f0f00)) { 133 - ret = 0; 134 - break; 135 - } 136 - 137 - AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); 138 - } 139 - 140 - if (type & 1) { 141 - for (i = 0; i < 16; i += 4) { 142 - xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); 143 - AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); 144 - } 145 - memcpy(data, xbuf, size); 146 - } 147 - 148 - out: 149 - auxch_fini(aux, ch); 150 - return ret; 35 + return -ENODEV; 151 36 } 152 37 153 38 int 154 - nv_rdaux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) 39 + nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size) 155 40 { 156 - return auxch_tx(auxch->i2c, auxch->drive, 9, addr, data, size); 157 - } 158 - 159 - int 160 - nv_wraux(struct nouveau_i2c_port *auxch, u32 addr, u8 *data, u8 size) 161 - { 162 - return auxch_tx(auxch->i2c, auxch->drive, 8, addr, data, size); 41 + if (port->func->aux) { 42 + if (port->func->acquire) 43 + port->func->acquire(port); 44 + return port->func->aux(port, 8, addr, data, size); 45 + } 46 + return -ENODEV; 163 47 } 164 48 165 49 static int 166 50 aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 167 51 { 168 - struct nouveau_i2c_port *auxch = (struct nouveau_i2c_port *)adap; 52 + struct nouveau_i2c_port *port = adap->algo_data; 169 53 struct i2c_msg *msg = msgs; 170 54 int ret, mcnt = num; 55 + 56 + if (!port->func->aux) 57 + return -ENODEV; 58 + if ( port->func->acquire) 59 + port->func->acquire(port); 171 60 172 61 while (mcnt--) { 173 62 u8 remaining = msg->len; ··· 74 185 if (mcnt || remaining > 16) 75 186 cmd |= 4; /* MOT */ 76 187 77 - ret = auxch_tx(auxch->i2c, auxch->drive, cmd, 78 - msg->addr, ptr, cnt); 188 + ret = port->func->aux(port, cmd, msg->addr, ptr, cnt); 79 189 if (ret < 0) 80 190 return ret; 81 191
+230 -269
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
··· 1 1 /* 2 - * Copyright 2012 Red Hat Inc. 2 + * Copyright 2013 Red Hat Inc. 3 3 * 4 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 5 * copy of this software and associated documentation files (the "Software"), ··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include "core/option.h" 25 + #include <core/option.h> 26 26 27 - #include "subdev/i2c.h" 28 - #include "subdev/vga.h" 27 + #include <subdev/bios.h> 28 + #include <subdev/bios/dcb.h> 29 + #include <subdev/bios/i2c.h> 30 + #include <subdev/i2c.h> 31 + #include <subdev/vga.h> 29 32 30 - int 31 - nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg) 33 + /****************************************************************************** 34 + * interface to linux i2c bit-banging algorithm 35 + *****************************************************************************/ 36 + 37 + #ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT 38 + #define CSTMSEL true 39 + #else 40 + #define CSTMSEL false 41 + #endif 42 + 43 + static int 44 + nouveau_i2c_pre_xfer(struct i2c_adapter *adap) 32 45 { 33 - u8 val; 34 - struct i2c_msg msgs[] = { 35 - { .addr = addr, .flags = 0, .len = 1, .buf = &reg }, 36 - { .addr = addr, .flags = I2C_M_RD, .len = 1, .buf = &val }, 37 - }; 38 - 39 - int ret = i2c_transfer(&port->adapter, msgs, 2); 40 - if (ret != 2) 41 - return -EIO; 42 - 43 - return val; 44 - } 45 - 46 - int 47 - nv_wri2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg, u8 val) 48 - { 49 - struct i2c_msg msgs[] = { 50 - { .addr = addr, .flags = 0, .len = 1, .buf = &reg }, 51 - { .addr = addr, .flags = 0, .len = 1, .buf = &val }, 52 - }; 53 - 54 - int ret = i2c_transfer(&port->adapter, msgs, 2); 55 - if (ret != 2) 56 - return -EIO; 57 - 46 + struct i2c_algo_bit_data *bit = adap->algo_data; 47 + struct nouveau_i2c_port *port = bit->data; 48 + if (port->func->acquire) 49 + port->func->acquire(port); 58 50 return 0; 59 51 } 60 52 61 - bool 62 - nv_probe_i2c(struct nouveau_i2c_port *port, u8 addr) 53 + static void 54 + nouveau_i2c_setscl(void *data, int state) 63 55 { 64 - u8 buf[] = { 0 }; 65 - struct i2c_msg msgs[] = { 66 - { 67 - .addr = addr, 68 - .flags = 0, 69 - .len = 1, 70 - .buf = buf, 71 - }, 72 - { 73 - .addr = addr, 74 - .flags = I2C_M_RD, 75 - .len = 1, 76 - .buf = buf, 77 - } 78 - }; 79 - 80 - return i2c_transfer(&port->adapter, msgs, 2) == 2; 56 + struct nouveau_i2c_port *port = data; 57 + port->func->drive_scl(port, state); 81 58 } 59 + 60 + static void 61 + nouveau_i2c_setsda(void *data, int state) 62 + { 63 + struct nouveau_i2c_port *port = data; 64 + port->func->drive_sda(port, state); 65 + } 66 + 67 + static int 68 + nouveau_i2c_getscl(void *data) 69 + { 70 + struct nouveau_i2c_port *port = data; 71 + return port->func->sense_scl(port); 72 + } 73 + 74 + static int 75 + nouveau_i2c_getsda(void *data) 76 + { 77 + struct nouveau_i2c_port *port = data; 78 + return port->func->sense_sda(port); 79 + } 80 + 81 + /****************************************************************************** 82 + * base i2c "port" class implementation 83 + *****************************************************************************/ 84 + 85 + void 86 + _nouveau_i2c_port_dtor(struct nouveau_object *object) 87 + { 88 + struct nouveau_i2c_port *port = (void *)object; 89 + i2c_del_adapter(&port->adapter); 90 + nouveau_object_destroy(&port->base); 91 + } 92 + 93 + int 94 + nouveau_i2c_port_create_(struct nouveau_object *parent, 95 + struct nouveau_object *engine, 96 + struct nouveau_oclass *oclass, u8 index, 97 + const struct i2c_algorithm *algo, 98 + int size, void **pobject) 99 + { 100 + struct nouveau_device *device = nv_device(parent); 101 + struct nouveau_i2c *i2c = (void *)engine; 102 + struct nouveau_i2c_port *port; 103 + int ret; 104 + 105 + ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject); 106 + port = *pobject; 107 + if (ret) 108 + return ret; 109 + 110 + snprintf(port->adapter.name, sizeof(port->adapter.name), 111 + "nouveau-%s-%d", device->name, index); 112 + port->adapter.owner = THIS_MODULE; 113 + port->adapter.dev.parent = &device->pdev->dev; 114 + port->index = index; 115 + i2c_set_adapdata(&port->adapter, i2c); 116 + 117 + if ( algo == &nouveau_i2c_bit_algo && 118 + !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) { 119 + struct i2c_algo_bit_data *bit; 120 + 121 + bit = kzalloc(sizeof(*bit), GFP_KERNEL); 122 + if (!bit) 123 + return -ENOMEM; 124 + 125 + bit->udelay = 10; 126 + bit->timeout = usecs_to_jiffies(2200); 127 + bit->data = port; 128 + bit->pre_xfer = nouveau_i2c_pre_xfer; 129 + bit->setsda = nouveau_i2c_setsda; 130 + bit->setscl = nouveau_i2c_setscl; 131 + bit->getsda = nouveau_i2c_getsda; 132 + bit->getscl = nouveau_i2c_getscl; 133 + 134 + port->adapter.algo_data = bit; 135 + ret = i2c_bit_add_bus(&port->adapter); 136 + } else { 137 + port->adapter.algo_data = port; 138 + port->adapter.algo = algo; 139 + ret = i2c_add_adapter(&port->adapter); 140 + } 141 + 142 + /* drop port's i2c subdev refcount, i2c handles this itself */ 143 + if (ret == 0) { 144 + list_add_tail(&port->head, &i2c->ports); 145 + atomic_dec(&engine->refcount); 146 + } 147 + 148 + return ret; 149 + } 150 + 151 + /****************************************************************************** 152 + * base i2c subdev class implementation 153 + *****************************************************************************/ 82 154 83 155 static struct nouveau_i2c_port * 84 156 nouveau_i2c_find(struct nouveau_i2c *i2c, u8 index) ··· 175 103 176 104 list_for_each_entry(port, &i2c->ports, head) { 177 105 if (port->index == index) 178 - break; 106 + return port; 179 107 } 180 108 181 - if (&port->head == &i2c->ports) 182 - return NULL; 109 + return NULL; 110 + } 183 111 184 - if (nv_device(i2c)->card_type >= NV_50 && (port->dcb & 0x00000100)) { 185 - u32 reg = 0x00e500, val; 186 - if (port->type == 6) { 187 - reg += port->drive * 0x50; 188 - val = 0x2002; 189 - } else { 190 - reg += ((port->dcb & 0x1e00) >> 9) * 0x50; 191 - val = 0xe001; 192 - } 112 + static struct nouveau_i2c_port * 113 + nouveau_i2c_find_type(struct nouveau_i2c *i2c, u16 type) 114 + { 115 + struct nouveau_i2c_port *port; 193 116 194 - /* nfi, but neither auxch or i2c work if it's 1 */ 195 - nv_mask(i2c, reg + 0x0c, 0x00000001, 0x00000000); 196 - /* nfi, but switches auxch vs normal i2c */ 197 - nv_mask(i2c, reg + 0x00, 0x0000f003, val); 117 + list_for_each_entry(port, &i2c->ports, head) { 118 + if (nv_hclass(port) == type) 119 + return port; 198 120 } 199 121 200 - return port; 122 + return NULL; 201 123 } 202 124 203 125 static int ··· 221 155 return -ENODEV; 222 156 } 223 157 224 - void 225 - nouveau_i2c_drive_scl(void *data, int state) 158 + int 159 + _nouveau_i2c_fini(struct nouveau_object *object, bool suspend) 226 160 { 227 - struct nouveau_i2c_port *port = data; 161 + struct nouveau_i2c *i2c = (void *)object; 162 + struct nouveau_i2c_port *port; 163 + int ret; 228 164 229 - if (port->type == DCB_I2C_NV04_BIT) { 230 - u8 val = nv_rdvgac(port->i2c, 0, port->drive); 231 - if (state) val |= 0x20; 232 - else val &= 0xdf; 233 - nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); 234 - } else 235 - if (port->type == DCB_I2C_NV4E_BIT) { 236 - nv_mask(port->i2c, port->drive, 0x2f, state ? 0x21 : 0x01); 237 - } else 238 - if (port->type == DCB_I2C_NVIO_BIT) { 239 - if (state) port->state |= 0x01; 240 - else port->state &= 0xfe; 241 - nv_wr32(port->i2c, port->drive, 4 | port->state); 165 + list_for_each_entry(port, &i2c->ports, head) { 166 + ret = nv_ofuncs(port)->fini(nv_object(port), suspend); 167 + if (ret && suspend) 168 + goto fail; 242 169 } 243 - } 244 170 245 - void 246 - nouveau_i2c_drive_sda(void *data, int state) 247 - { 248 - struct nouveau_i2c_port *port = data; 249 - 250 - if (port->type == DCB_I2C_NV04_BIT) { 251 - u8 val = nv_rdvgac(port->i2c, 0, port->drive); 252 - if (state) val |= 0x10; 253 - else val &= 0xef; 254 - nv_wrvgac(port->i2c, 0, port->drive, val | 0x01); 255 - } else 256 - if (port->type == DCB_I2C_NV4E_BIT) { 257 - nv_mask(port->i2c, port->drive, 0x1f, state ? 0x11 : 0x01); 258 - } else 259 - if (port->type == DCB_I2C_NVIO_BIT) { 260 - if (state) port->state |= 0x02; 261 - else port->state &= 0xfd; 262 - nv_wr32(port->i2c, port->drive, 4 | port->state); 171 + return nouveau_subdev_fini(&i2c->base, suspend); 172 + fail: 173 + list_for_each_entry_continue_reverse(port, &i2c->ports, head) { 174 + nv_ofuncs(port)->init(nv_object(port)); 263 175 } 176 + 177 + return ret; 264 178 } 265 179 266 180 int 267 - nouveau_i2c_sense_scl(void *data) 181 + _nouveau_i2c_init(struct nouveau_object *object) 268 182 { 269 - struct nouveau_i2c_port *port = data; 270 - struct nouveau_device *device = nv_device(port->i2c); 183 + struct nouveau_i2c *i2c = (void *)object; 184 + struct nouveau_i2c_port *port; 185 + int ret; 271 186 272 - if (port->type == DCB_I2C_NV04_BIT) { 273 - return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x04); 274 - } else 275 - if (port->type == DCB_I2C_NV4E_BIT) { 276 - return !!(nv_rd32(port->i2c, port->sense) & 0x00040000); 277 - } else 278 - if (port->type == DCB_I2C_NVIO_BIT) { 279 - if (device->card_type < NV_D0) 280 - return !!(nv_rd32(port->i2c, port->sense) & 0x01); 281 - else 282 - return !!(nv_rd32(port->i2c, port->sense) & 0x10); 187 + ret = nouveau_subdev_init(&i2c->base); 188 + if (ret == 0) { 189 + list_for_each_entry(port, &i2c->ports, head) { 190 + ret = nv_ofuncs(port)->init(nv_object(port)); 191 + if (ret) 192 + goto fail; 193 + } 283 194 } 284 195 285 - return 0; 286 - } 287 - 288 - int 289 - nouveau_i2c_sense_sda(void *data) 290 - { 291 - struct nouveau_i2c_port *port = data; 292 - struct nouveau_device *device = nv_device(port->i2c); 293 - 294 - if (port->type == DCB_I2C_NV04_BIT) { 295 - return !!(nv_rdvgac(port->i2c, 0, port->sense) & 0x08); 296 - } else 297 - if (port->type == DCB_I2C_NV4E_BIT) { 298 - return !!(nv_rd32(port->i2c, port->sense) & 0x00080000); 299 - } else 300 - if (port->type == DCB_I2C_NVIO_BIT) { 301 - if (device->card_type < NV_D0) 302 - return !!(nv_rd32(port->i2c, port->sense) & 0x02); 303 - else 304 - return !!(nv_rd32(port->i2c, port->sense) & 0x20); 196 + return ret; 197 + fail: 198 + list_for_each_entry_continue_reverse(port, &i2c->ports, head) { 199 + nv_ofuncs(port)->fini(nv_object(port), false); 305 200 } 306 201 307 - return 0; 202 + return ret; 308 203 } 309 204 310 - static const u32 nv50_i2c_port[] = { 311 - 0x00e138, 0x00e150, 0x00e168, 0x00e180, 312 - 0x00e254, 0x00e274, 0x00e764, 0x00e780, 313 - 0x00e79c, 0x00e7b8 205 + void 206 + _nouveau_i2c_dtor(struct nouveau_object *object) 207 + { 208 + struct nouveau_i2c *i2c = (void *)object; 209 + struct nouveau_i2c_port *port, *temp; 210 + 211 + list_for_each_entry_safe(port, temp, &i2c->ports, head) { 212 + nouveau_object_ref(NULL, (struct nouveau_object **)&port); 213 + } 214 + 215 + nouveau_subdev_destroy(&i2c->base); 216 + } 217 + 218 + static struct nouveau_oclass * 219 + nouveau_i2c_extdev_sclass[] = { 220 + nouveau_anx9805_sclass, 314 221 }; 315 222 316 - static int 317 - nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 318 - struct nouveau_oclass *oclass, void *data, u32 size, 319 - struct nouveau_object **pobject) 223 + int 224 + nouveau_i2c_create_(struct nouveau_object *parent, 225 + struct nouveau_object *engine, 226 + struct nouveau_oclass *oclass, 227 + struct nouveau_oclass *sclass, 228 + int length, void **pobject) 320 229 { 321 - struct nouveau_device *device = nv_device(parent); 322 230 struct nouveau_bios *bios = nouveau_bios(parent); 323 - struct nouveau_i2c_port *port; 324 231 struct nouveau_i2c *i2c; 232 + struct nouveau_object *object; 325 233 struct dcb_i2c_entry info; 326 - int ret, i = -1; 234 + int ret, i, j, index = -1; 235 + struct dcb_output outp; 236 + u8 ver, hdr; 237 + u32 data; 327 238 328 239 ret = nouveau_subdev_create(parent, engine, oclass, 0, 329 240 "I2C", "i2c", &i2c); ··· 309 266 return ret; 310 267 311 268 i2c->find = nouveau_i2c_find; 269 + i2c->find_type = nouveau_i2c_find_type; 312 270 i2c->identify = nouveau_i2c_identify; 313 271 INIT_LIST_HEAD(&i2c->ports); 314 272 315 - while (!dcb_i2c_parse(bios, ++i, &info)) { 273 + while (!dcb_i2c_parse(bios, ++index, &info)) { 316 274 if (info.type == DCB_I2C_UNUSED) 317 275 continue; 318 276 319 - port = kzalloc(sizeof(*port), GFP_KERNEL); 320 - if (!port) { 321 - nv_error(i2c, "failed port memory alloc at %d\n", i); 322 - break; 323 - } 324 - 325 - port->type = info.type; 326 - switch (port->type) { 327 - case DCB_I2C_NV04_BIT: 328 - port->drive = info.drive; 329 - port->sense = info.sense; 330 - break; 331 - case DCB_I2C_NV4E_BIT: 332 - port->drive = 0x600800 + info.drive; 333 - port->sense = port->drive; 334 - break; 335 - case DCB_I2C_NVIO_BIT: 336 - port->drive = info.drive & 0x0f; 337 - if (device->card_type < NV_D0) { 338 - if (port->drive >= ARRAY_SIZE(nv50_i2c_port)) 339 - break; 340 - port->drive = nv50_i2c_port[port->drive]; 341 - port->sense = port->drive; 342 - } else { 343 - port->drive = 0x00d014 + (port->drive * 0x20); 344 - port->sense = port->drive; 277 + oclass = sclass; 278 + do { 279 + ret = -EINVAL; 280 + if (oclass->handle == info.type) { 281 + ret = nouveau_object_ctor(*pobject, *pobject, 282 + oclass, &info, 283 + index, &object); 345 284 } 285 + } while (ret && (++oclass)->handle); 286 + } 287 + 288 + /* in addition to the busses specified in the i2c table, there 289 + * may be ddc/aux channels hiding behind external tmds/dp/etc 290 + * transmitters. 291 + */ 292 + index = ((index + 0x0f) / 0x10) * 0x10; 293 + i = -1; 294 + while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &outp))) { 295 + if (!outp.location || !outp.extdev) 296 + continue; 297 + 298 + switch (outp.type) { 299 + case DCB_OUTPUT_TMDS: 300 + info.type = NV_I2C_TYPE_EXTDDC(outp.extdev); 346 301 break; 347 - case DCB_I2C_NVIO_AUX: 348 - port->drive = info.drive & 0x0f; 349 - port->sense = port->drive; 350 - port->adapter.algo = &nouveau_i2c_aux_algo; 302 + case DCB_OUTPUT_DP: 303 + info.type = NV_I2C_TYPE_EXTAUX(outp.extdev); 351 304 break; 352 305 default: 353 - break; 354 - } 355 - 356 - if (!port->adapter.algo && !port->drive) { 357 - nv_error(i2c, "I2C%d: type %d index %x/%x unknown\n", 358 - i, port->type, port->drive, port->sense); 359 - kfree(port); 360 306 continue; 361 307 } 362 308 363 - snprintf(port->adapter.name, sizeof(port->adapter.name), 364 - "nouveau-%s-%d", device->name, i); 365 - port->adapter.owner = THIS_MODULE; 366 - port->adapter.dev.parent = &device->pdev->dev; 367 - port->i2c = i2c; 368 - port->index = i; 369 - port->dcb = info.data; 370 - i2c_set_adapdata(&port->adapter, i2c); 371 - 372 - if (port->adapter.algo != &nouveau_i2c_aux_algo) { 373 - nouveau_i2c_drive_scl(port, 0); 374 - nouveau_i2c_drive_sda(port, 1); 375 - nouveau_i2c_drive_scl(port, 1); 376 - 377 - #ifdef CONFIG_NOUVEAU_I2C_INTERNAL_DEFAULT 378 - if (nouveau_boolopt(device->cfgopt, "NvI2C", true)) { 379 - #else 380 - if (nouveau_boolopt(device->cfgopt, "NvI2C", false)) { 381 - #endif 382 - port->adapter.algo = &nouveau_i2c_bit_algo; 383 - ret = i2c_add_adapter(&port->adapter); 384 - } else { 385 - port->adapter.algo_data = &port->bit; 386 - port->bit.udelay = 10; 387 - port->bit.timeout = usecs_to_jiffies(2200); 388 - port->bit.data = port; 389 - port->bit.setsda = nouveau_i2c_drive_sda; 390 - port->bit.setscl = nouveau_i2c_drive_scl; 391 - port->bit.getsda = nouveau_i2c_sense_sda; 392 - port->bit.getscl = nouveau_i2c_sense_scl; 393 - ret = i2c_bit_add_bus(&port->adapter); 394 - } 395 - } else { 396 - port->adapter.algo = &nouveau_i2c_aux_algo; 397 - ret = i2c_add_adapter(&port->adapter); 309 + ret = -ENODEV; 310 + j = -1; 311 + while (ret && ++j < ARRAY_SIZE(nouveau_i2c_extdev_sclass)) { 312 + parent = nv_object(i2c->find(i2c, outp.i2c_index)); 313 + oclass = nouveau_i2c_extdev_sclass[j]; 314 + do { 315 + if (oclass->handle != info.type) 316 + continue; 317 + ret = nouveau_object_ctor(parent, *pobject, 318 + oclass, NULL, 319 + index++, &object); 320 + } while (ret && (++oclass)->handle); 398 321 } 399 - 400 - if (ret) { 401 - nv_error(i2c, "I2C%d: failed register: %d\n", i, ret); 402 - kfree(port); 403 - continue; 404 - } 405 - 406 - list_add_tail(&port->head, &i2c->ports); 407 322 } 408 323 409 324 return 0; 410 325 } 411 - 412 - static void 413 - nouveau_i2c_dtor(struct nouveau_object *object) 414 - { 415 - struct nouveau_i2c *i2c = (void *)object; 416 - struct nouveau_i2c_port *port, *temp; 417 - 418 - list_for_each_entry_safe(port, temp, &i2c->ports, head) { 419 - i2c_del_adapter(&port->adapter); 420 - list_del(&port->head); 421 - kfree(port); 422 - } 423 - 424 - nouveau_subdev_destroy(&i2c->base); 425 - } 426 - 427 - static int 428 - nouveau_i2c_init(struct nouveau_object *object) 429 - { 430 - struct nouveau_i2c *i2c = (void *)object; 431 - return nouveau_subdev_init(&i2c->base); 432 - } 433 - 434 - static int 435 - nouveau_i2c_fini(struct nouveau_object *object, bool suspend) 436 - { 437 - struct nouveau_i2c *i2c = (void *)object; 438 - return nouveau_subdev_fini(&i2c->base, suspend); 439 - } 440 - 441 - struct nouveau_oclass 442 - nouveau_i2c_oclass = { 443 - .handle = NV_SUBDEV(I2C, 0x00), 444 - .ofuncs = &(struct nouveau_ofuncs) { 445 - .ctor = nouveau_i2c_ctor, 446 - .dtor = nouveau_i2c_dtor, 447 - .init = nouveau_i2c_init, 448 - .fini = nouveau_i2c_fini, 449 - }, 450 - };
+10 -8
drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c
··· 32 32 static inline void 33 33 i2c_drive_scl(struct nouveau_i2c_port *port, int state) 34 34 { 35 - nouveau_i2c_drive_scl(port, state); 35 + port->func->drive_scl(port, state); 36 36 } 37 37 38 38 static inline void 39 39 i2c_drive_sda(struct nouveau_i2c_port *port, int state) 40 40 { 41 - nouveau_i2c_drive_sda(port, state); 41 + port->func->drive_sda(port, state); 42 42 } 43 43 44 44 static inline int 45 45 i2c_sense_scl(struct nouveau_i2c_port *port) 46 46 { 47 - return nouveau_i2c_sense_scl(port); 47 + return port->func->sense_scl(port); 48 48 } 49 49 50 50 static inline int 51 51 i2c_sense_sda(struct nouveau_i2c_port *port) 52 52 { 53 - return nouveau_i2c_sense_sda(port); 53 + return port->func->sense_sda(port); 54 54 } 55 55 56 56 static void ··· 77 77 { 78 78 int ret = 0; 79 79 80 - port->state = i2c_sense_scl(port); 81 - port->state |= i2c_sense_sda(port) << 1; 82 - if (port->state != 3) { 80 + if (!i2c_sense_scl(port) || 81 + !i2c_sense_sda(port)) { 83 82 i2c_drive_scl(port, 0); 84 83 i2c_drive_sda(port, 1); 85 84 if (!i2c_raise_scl(port)) ··· 183 184 static int 184 185 i2c_bit_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 185 186 { 186 - struct nouveau_i2c_port *port = (struct nouveau_i2c_port *)adap; 187 + struct nouveau_i2c_port *port = adap->algo_data; 187 188 struct i2c_msg *msg = msgs; 188 189 int ret = 0, mcnt = num; 190 + 191 + if (port->func->acquire) 192 + port->func->acquire(port); 189 193 190 194 while (!ret && mcnt--) { 191 195 u8 remaining = msg->len;
+143
drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
··· 1 + /* 2 + * Copyright 2012 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 <subdev/i2c.h> 26 + #include <subdev/vga.h> 27 + 28 + struct nv04_i2c_priv { 29 + struct nouveau_i2c base; 30 + }; 31 + 32 + struct nv04_i2c_port { 33 + struct nouveau_i2c_port base; 34 + u8 drive; 35 + u8 sense; 36 + }; 37 + 38 + static void 39 + nv04_i2c_drive_scl(struct nouveau_i2c_port *base, int state) 40 + { 41 + struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; 42 + struct nv04_i2c_port *port = (void *)base; 43 + u8 val = nv_rdvgac(priv, 0, port->drive); 44 + if (state) val |= 0x20; 45 + else val &= 0xdf; 46 + nv_wrvgac(priv, 0, port->drive, val | 0x01); 47 + } 48 + 49 + static void 50 + nv04_i2c_drive_sda(struct nouveau_i2c_port *base, int state) 51 + { 52 + struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; 53 + struct nv04_i2c_port *port = (void *)base; 54 + u8 val = nv_rdvgac(priv, 0, port->drive); 55 + if (state) val |= 0x10; 56 + else val &= 0xef; 57 + nv_wrvgac(priv, 0, port->drive, val | 0x01); 58 + } 59 + 60 + static int 61 + nv04_i2c_sense_scl(struct nouveau_i2c_port *base) 62 + { 63 + struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; 64 + struct nv04_i2c_port *port = (void *)base; 65 + return !!(nv_rdvgac(priv, 0, port->sense) & 0x04); 66 + } 67 + 68 + static int 69 + nv04_i2c_sense_sda(struct nouveau_i2c_port *base) 70 + { 71 + struct nv04_i2c_priv *priv = (void *)nv_object(base)->engine; 72 + struct nv04_i2c_port *port = (void *)base; 73 + return !!(nv_rdvgac(priv, 0, port->sense) & 0x08); 74 + } 75 + 76 + static const struct nouveau_i2c_func 77 + nv04_i2c_func = { 78 + .drive_scl = nv04_i2c_drive_scl, 79 + .drive_sda = nv04_i2c_drive_sda, 80 + .sense_scl = nv04_i2c_sense_scl, 81 + .sense_sda = nv04_i2c_sense_sda, 82 + }; 83 + 84 + static int 85 + nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 86 + struct nouveau_oclass *oclass, void *data, u32 index, 87 + struct nouveau_object **pobject) 88 + { 89 + struct dcb_i2c_entry *info = data; 90 + struct nv04_i2c_port *port; 91 + int ret; 92 + 93 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 94 + &nouveau_i2c_bit_algo, &port); 95 + *pobject = nv_object(port); 96 + if (ret) 97 + return ret; 98 + 99 + port->base.func = &nv04_i2c_func; 100 + port->drive = info->drive; 101 + port->sense = info->sense; 102 + return 0; 103 + } 104 + 105 + static struct nouveau_oclass 106 + nv04_i2c_sclass[] = { 107 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV04_BIT), 108 + .ofuncs = &(struct nouveau_ofuncs) { 109 + .ctor = nv04_i2c_port_ctor, 110 + .dtor = _nouveau_i2c_port_dtor, 111 + .init = _nouveau_i2c_port_init, 112 + .fini = _nouveau_i2c_port_fini, 113 + }, 114 + }, 115 + {} 116 + }; 117 + 118 + static int 119 + nv04_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 120 + struct nouveau_oclass *oclass, void *data, u32 size, 121 + struct nouveau_object **pobject) 122 + { 123 + struct nv04_i2c_priv *priv; 124 + int ret; 125 + 126 + ret = nouveau_i2c_create(parent, engine, oclass, nv04_i2c_sclass, &priv); 127 + *pobject = nv_object(priv); 128 + if (ret) 129 + return ret; 130 + 131 + return 0; 132 + } 133 + 134 + struct nouveau_oclass 135 + nv04_i2c_oclass = { 136 + .handle = NV_SUBDEV(I2C, 0x04), 137 + .ofuncs = &(struct nouveau_ofuncs) { 138 + .ctor = nv04_i2c_ctor, 139 + .dtor = _nouveau_i2c_dtor, 140 + .init = _nouveau_i2c_init, 141 + .fini = _nouveau_i2c_fini, 142 + }, 143 + };
+135
drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
··· 1 + /* 2 + * Copyright 2012 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 <subdev/i2c.h> 26 + #include <subdev/vga.h> 27 + 28 + struct nv4e_i2c_priv { 29 + struct nouveau_i2c base; 30 + }; 31 + 32 + struct nv4e_i2c_port { 33 + struct nouveau_i2c_port base; 34 + u32 addr; 35 + }; 36 + 37 + static void 38 + nv4e_i2c_drive_scl(struct nouveau_i2c_port *base, int state) 39 + { 40 + struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; 41 + struct nv4e_i2c_port *port = (void *)base; 42 + nv_mask(priv, port->addr, 0x2f, state ? 0x21 : 0x01); 43 + } 44 + 45 + static void 46 + nv4e_i2c_drive_sda(struct nouveau_i2c_port *base, int state) 47 + { 48 + struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; 49 + struct nv4e_i2c_port *port = (void *)base; 50 + nv_mask(priv, port->addr, 0x1f, state ? 0x11 : 0x01); 51 + } 52 + 53 + static int 54 + nv4e_i2c_sense_scl(struct nouveau_i2c_port *base) 55 + { 56 + struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; 57 + struct nv4e_i2c_port *port = (void *)base; 58 + return !!(nv_rd32(priv, port->addr) & 0x00040000); 59 + } 60 + 61 + static int 62 + nv4e_i2c_sense_sda(struct nouveau_i2c_port *base) 63 + { 64 + struct nv4e_i2c_priv *priv = (void *)nv_object(base)->engine; 65 + struct nv4e_i2c_port *port = (void *)base; 66 + return !!(nv_rd32(priv, port->addr) & 0x00080000); 67 + } 68 + 69 + static const struct nouveau_i2c_func 70 + nv4e_i2c_func = { 71 + .drive_scl = nv4e_i2c_drive_scl, 72 + .drive_sda = nv4e_i2c_drive_sda, 73 + .sense_scl = nv4e_i2c_sense_scl, 74 + .sense_sda = nv4e_i2c_sense_sda, 75 + }; 76 + 77 + static int 78 + nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 79 + struct nouveau_oclass *oclass, void *data, u32 index, 80 + struct nouveau_object **pobject) 81 + { 82 + struct dcb_i2c_entry *info = data; 83 + struct nv4e_i2c_port *port; 84 + int ret; 85 + 86 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 87 + &nouveau_i2c_bit_algo, &port); 88 + *pobject = nv_object(port); 89 + if (ret) 90 + return ret; 91 + 92 + port->base.func = &nv4e_i2c_func; 93 + port->addr = 0x600800 + info->drive; 94 + return 0; 95 + } 96 + 97 + static struct nouveau_oclass 98 + nv4e_i2c_sclass[] = { 99 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NV4E_BIT), 100 + .ofuncs = &(struct nouveau_ofuncs) { 101 + .ctor = nv4e_i2c_port_ctor, 102 + .dtor = _nouveau_i2c_port_dtor, 103 + .init = _nouveau_i2c_port_init, 104 + .fini = _nouveau_i2c_port_fini, 105 + }, 106 + }, 107 + {} 108 + }; 109 + 110 + static int 111 + nv4e_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 112 + struct nouveau_oclass *oclass, void *data, u32 size, 113 + struct nouveau_object **pobject) 114 + { 115 + struct nv4e_i2c_priv *priv; 116 + int ret; 117 + 118 + ret = nouveau_i2c_create(parent, engine, oclass, nv4e_i2c_sclass, &priv); 119 + *pobject = nv_object(priv); 120 + if (ret) 121 + return ret; 122 + 123 + return 0; 124 + } 125 + 126 + struct nouveau_oclass 127 + nv4e_i2c_oclass = { 128 + .handle = NV_SUBDEV(I2C, 0x4e), 129 + .ofuncs = &(struct nouveau_ofuncs) { 130 + .ctor = nv4e_i2c_ctor, 131 + .dtor = _nouveau_i2c_dtor, 132 + .init = _nouveau_i2c_init, 133 + .fini = _nouveau_i2c_fini, 134 + }, 135 + };
+149
drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
··· 1 + /* 2 + * Copyright 2012 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 "nv50.h" 26 + 27 + void 28 + nv50_i2c_drive_scl(struct nouveau_i2c_port *base, int state) 29 + { 30 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 31 + struct nv50_i2c_port *port = (void *)base; 32 + if (state) port->state |= 0x01; 33 + else port->state &= 0xfe; 34 + nv_wr32(priv, port->addr, port->state); 35 + } 36 + 37 + void 38 + nv50_i2c_drive_sda(struct nouveau_i2c_port *base, int state) 39 + { 40 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 41 + struct nv50_i2c_port *port = (void *)base; 42 + if (state) port->state |= 0x02; 43 + else port->state &= 0xfd; 44 + nv_wr32(priv, port->addr, port->state); 45 + } 46 + 47 + int 48 + nv50_i2c_sense_scl(struct nouveau_i2c_port *base) 49 + { 50 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 51 + struct nv50_i2c_port *port = (void *)base; 52 + return !!(nv_rd32(priv, port->addr) & 0x00000001); 53 + } 54 + 55 + int 56 + nv50_i2c_sense_sda(struct nouveau_i2c_port *base) 57 + { 58 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 59 + struct nv50_i2c_port *port = (void *)base; 60 + return !!(nv_rd32(priv, port->addr) & 0x00000002); 61 + } 62 + 63 + static const struct nouveau_i2c_func 64 + nv50_i2c_func = { 65 + .drive_scl = nv50_i2c_drive_scl, 66 + .drive_sda = nv50_i2c_drive_sda, 67 + .sense_scl = nv50_i2c_sense_scl, 68 + .sense_sda = nv50_i2c_sense_sda, 69 + }; 70 + 71 + const u32 nv50_i2c_addr[] = { 72 + 0x00e138, 0x00e150, 0x00e168, 0x00e180, 73 + 0x00e254, 0x00e274, 0x00e764, 0x00e780, 74 + 0x00e79c, 0x00e7b8 75 + }; 76 + const int nv50_i2c_addr_nr = ARRAY_SIZE(nv50_i2c_addr); 77 + 78 + static int 79 + nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 80 + struct nouveau_oclass *oclass, void *data, u32 index, 81 + struct nouveau_object **pobject) 82 + { 83 + struct dcb_i2c_entry *info = data; 84 + struct nv50_i2c_port *port; 85 + int ret; 86 + 87 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 88 + &nouveau_i2c_bit_algo, &port); 89 + *pobject = nv_object(port); 90 + if (ret) 91 + return ret; 92 + 93 + if (info->drive >= nv50_i2c_addr_nr) 94 + return -EINVAL; 95 + 96 + port->base.func = &nv50_i2c_func; 97 + port->state = 0x00000007; 98 + port->addr = nv50_i2c_addr[info->drive]; 99 + return 0; 100 + } 101 + 102 + int 103 + nv50_i2c_port_init(struct nouveau_object *object) 104 + { 105 + struct nv50_i2c_priv *priv = (void *)object->engine; 106 + struct nv50_i2c_port *port = (void *)object; 107 + nv_wr32(priv, port->addr, port->state); 108 + return nouveau_i2c_port_init(&port->base); 109 + } 110 + 111 + static struct nouveau_oclass 112 + nv50_i2c_sclass[] = { 113 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), 114 + .ofuncs = &(struct nouveau_ofuncs) { 115 + .ctor = nv50_i2c_port_ctor, 116 + .dtor = _nouveau_i2c_port_dtor, 117 + .init = nv50_i2c_port_init, 118 + .fini = _nouveau_i2c_port_fini, 119 + }, 120 + }, 121 + {} 122 + }; 123 + 124 + static int 125 + nv50_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 126 + struct nouveau_oclass *oclass, void *data, u32 size, 127 + struct nouveau_object **pobject) 128 + { 129 + struct nv50_i2c_priv *priv; 130 + int ret; 131 + 132 + ret = nouveau_i2c_create(parent, engine, oclass, nv50_i2c_sclass, &priv); 133 + *pobject = nv_object(priv); 134 + if (ret) 135 + return ret; 136 + 137 + return 0; 138 + } 139 + 140 + struct nouveau_oclass 141 + nv50_i2c_oclass = { 142 + .handle = NV_SUBDEV(I2C, 0x50), 143 + .ofuncs = &(struct nouveau_ofuncs) { 144 + .ctor = nv50_i2c_ctor, 145 + .dtor = _nouveau_i2c_dtor, 146 + .init = _nouveau_i2c_init, 147 + .fini = _nouveau_i2c_fini, 148 + }, 149 + };
+32
drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h
··· 1 + #ifndef __NV50_I2C_H__ 2 + #define __NV50_I2C_H__ 3 + 4 + #include <subdev/i2c.h> 5 + 6 + struct nv50_i2c_priv { 7 + struct nouveau_i2c base; 8 + }; 9 + 10 + struct nv50_i2c_port { 11 + struct nouveau_i2c_port base; 12 + u32 addr; 13 + u32 ctrl; 14 + u32 data; 15 + u32 state; 16 + }; 17 + 18 + extern const u32 nv50_i2c_addr[]; 19 + extern const int nv50_i2c_addr_nr; 20 + int nv50_i2c_port_init(struct nouveau_object *); 21 + int nv50_i2c_sense_scl(struct nouveau_i2c_port *); 22 + int nv50_i2c_sense_sda(struct nouveau_i2c_port *); 23 + void nv50_i2c_drive_scl(struct nouveau_i2c_port *, int state); 24 + void nv50_i2c_drive_sda(struct nouveau_i2c_port *, int state); 25 + 26 + int nv94_aux_port_ctor(struct nouveau_object *, struct nouveau_object *, 27 + struct nouveau_oclass *, void *, u32, 28 + struct nouveau_object **); 29 + void nv94_i2c_acquire(struct nouveau_i2c_port *); 30 + void nv94_i2c_release(struct nouveau_i2c_port *); 31 + 32 + #endif
+285
drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
··· 1 + /* 2 + * Copyright 2012 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 "nv50.h" 26 + 27 + #define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) 28 + #define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) 29 + 30 + static void 31 + auxch_fini(struct nouveau_i2c *aux, int ch) 32 + { 33 + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00310000, 0x00000000); 34 + } 35 + 36 + static int 37 + auxch_init(struct nouveau_i2c *aux, int ch) 38 + { 39 + const u32 unksel = 1; /* nfi which to use, or if it matters.. */ 40 + const u32 ureq = unksel ? 0x00100000 : 0x00200000; 41 + const u32 urep = unksel ? 0x01000000 : 0x02000000; 42 + u32 ctrl, timeout; 43 + 44 + /* wait up to 1ms for any previous transaction to be done... */ 45 + timeout = 1000; 46 + do { 47 + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 48 + udelay(1); 49 + if (!timeout--) { 50 + AUX_ERR("begin idle timeout 0x%08x\n", ctrl); 51 + return -EBUSY; 52 + } 53 + } while (ctrl & 0x03010000); 54 + 55 + /* set some magic, and wait up to 1ms for it to appear */ 56 + nv_mask(aux, 0x00e4e4 + (ch * 0x50), 0x00300000, ureq); 57 + timeout = 1000; 58 + do { 59 + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 60 + udelay(1); 61 + if (!timeout--) { 62 + AUX_ERR("magic wait 0x%08x\n", ctrl); 63 + auxch_fini(aux, ch); 64 + return -EBUSY; 65 + } 66 + } while ((ctrl & 0x03000000) != urep); 67 + 68 + return 0; 69 + } 70 + 71 + int 72 + nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size) 73 + { 74 + struct nouveau_i2c *aux = nouveau_i2c(base); 75 + struct nv50_i2c_port *port = (void *)base; 76 + u32 ctrl, stat, timeout, retries; 77 + u32 xbuf[4] = {}; 78 + int ch = port->addr; 79 + int ret, i; 80 + 81 + AUX_DBG("%d: 0x%08x %d\n", type, addr, size); 82 + 83 + ret = auxch_init(aux, ch); 84 + if (ret) 85 + goto out; 86 + 87 + stat = nv_rd32(aux, 0x00e4e8 + (ch * 0x50)); 88 + if (!(stat & 0x10000000)) { 89 + AUX_DBG("sink not detected\n"); 90 + ret = -ENXIO; 91 + goto out; 92 + } 93 + 94 + if (!(type & 1)) { 95 + memcpy(xbuf, data, size); 96 + for (i = 0; i < 16; i += 4) { 97 + AUX_DBG("wr 0x%08x\n", xbuf[i / 4]); 98 + nv_wr32(aux, 0x00e4c0 + (ch * 0x50) + i, xbuf[i / 4]); 99 + } 100 + } 101 + 102 + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 103 + ctrl &= ~0x0001f0ff; 104 + ctrl |= type << 12; 105 + ctrl |= size - 1; 106 + nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); 107 + 108 + /* retry transaction a number of times on failure... */ 109 + ret = -EREMOTEIO; 110 + for (retries = 0; retries < 32; retries++) { 111 + /* reset, and delay a while if this is a retry */ 112 + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); 113 + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); 114 + if (retries) 115 + udelay(400); 116 + 117 + /* transaction request, wait up to 1ms for it to complete */ 118 + nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00010000 | ctrl); 119 + 120 + timeout = 1000; 121 + do { 122 + ctrl = nv_rd32(aux, 0x00e4e4 + (ch * 0x50)); 123 + udelay(1); 124 + if (!timeout--) { 125 + AUX_ERR("tx req timeout 0x%08x\n", ctrl); 126 + goto out; 127 + } 128 + } while (ctrl & 0x00010000); 129 + 130 + /* read status, and check if transaction completed ok */ 131 + stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); 132 + if (!(stat & 0x000f0f00)) { 133 + ret = 0; 134 + break; 135 + } 136 + 137 + AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); 138 + } 139 + 140 + if (type & 1) { 141 + for (i = 0; i < 16; i += 4) { 142 + xbuf[i / 4] = nv_rd32(aux, 0x00e4d0 + (ch * 0x50) + i); 143 + AUX_DBG("rd 0x%08x\n", xbuf[i / 4]); 144 + } 145 + memcpy(data, xbuf, size); 146 + } 147 + 148 + out: 149 + auxch_fini(aux, ch); 150 + return ret; 151 + } 152 + 153 + void 154 + nv94_i2c_acquire(struct nouveau_i2c_port *base) 155 + { 156 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 157 + struct nv50_i2c_port *port = (void *)base; 158 + if (port->ctrl) { 159 + nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000); 160 + nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data); 161 + } 162 + } 163 + 164 + void 165 + nv94_i2c_release(struct nouveau_i2c_port *base) 166 + { 167 + } 168 + 169 + static const struct nouveau_i2c_func 170 + nv94_i2c_func = { 171 + .acquire = nv94_i2c_acquire, 172 + .release = nv94_i2c_release, 173 + .drive_scl = nv50_i2c_drive_scl, 174 + .drive_sda = nv50_i2c_drive_sda, 175 + .sense_scl = nv50_i2c_sense_scl, 176 + .sense_sda = nv50_i2c_sense_sda, 177 + }; 178 + 179 + static int 180 + nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 181 + struct nouveau_oclass *oclass, void *data, u32 index, 182 + struct nouveau_object **pobject) 183 + { 184 + struct dcb_i2c_entry *info = data; 185 + struct nv50_i2c_port *port; 186 + int ret; 187 + 188 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 189 + &nouveau_i2c_bit_algo, &port); 190 + *pobject = nv_object(port); 191 + if (ret) 192 + return ret; 193 + 194 + if (info->drive >= nv50_i2c_addr_nr) 195 + return -EINVAL; 196 + 197 + port->base.func = &nv94_i2c_func; 198 + port->state = 7; 199 + port->addr = nv50_i2c_addr[info->drive]; 200 + if (info->share != DCB_I2C_UNUSED) { 201 + port->ctrl = 0x00e500 + (info->share * 0x50); 202 + port->data = 0x0000e001; 203 + } 204 + return 0; 205 + } 206 + 207 + static const struct nouveau_i2c_func 208 + nv94_aux_func = { 209 + .acquire = nv94_i2c_acquire, 210 + .release = nv94_i2c_release, 211 + .aux = nv94_aux, 212 + }; 213 + 214 + int 215 + nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 216 + struct nouveau_oclass *oclass, void *data, u32 index, 217 + struct nouveau_object **pobject) 218 + { 219 + struct dcb_i2c_entry *info = data; 220 + struct nv50_i2c_port *port; 221 + int ret; 222 + 223 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 224 + &nouveau_i2c_aux_algo, &port); 225 + *pobject = nv_object(port); 226 + if (ret) 227 + return ret; 228 + 229 + port->base.func = &nv94_aux_func; 230 + port->addr = info->drive; 231 + if (info->share != DCB_I2C_UNUSED) { 232 + port->ctrl = 0x00e500 + (info->drive * 0x50); 233 + port->data = 0x00002002; 234 + } 235 + 236 + return 0; 237 + } 238 + 239 + static struct nouveau_oclass 240 + nv94_i2c_sclass[] = { 241 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), 242 + .ofuncs = &(struct nouveau_ofuncs) { 243 + .ctor = nv94_i2c_port_ctor, 244 + .dtor = _nouveau_i2c_port_dtor, 245 + .init = nv50_i2c_port_init, 246 + .fini = _nouveau_i2c_port_fini, 247 + }, 248 + }, 249 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), 250 + .ofuncs = &(struct nouveau_ofuncs) { 251 + .ctor = nv94_aux_port_ctor, 252 + .dtor = _nouveau_i2c_port_dtor, 253 + .init = _nouveau_i2c_port_init, 254 + .fini = _nouveau_i2c_port_fini, 255 + }, 256 + }, 257 + {} 258 + }; 259 + 260 + static int 261 + nv94_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 262 + struct nouveau_oclass *oclass, void *data, u32 size, 263 + struct nouveau_object **pobject) 264 + { 265 + struct nv50_i2c_priv *priv; 266 + int ret; 267 + 268 + ret = nouveau_i2c_create(parent, engine, oclass, nv94_i2c_sclass, &priv); 269 + *pobject = nv_object(priv); 270 + if (ret) 271 + return ret; 272 + 273 + return 0; 274 + } 275 + 276 + struct nouveau_oclass 277 + nv94_i2c_oclass = { 278 + .handle = NV_SUBDEV(I2C, 0x94), 279 + .ofuncs = &(struct nouveau_ofuncs) { 280 + .ctor = nv94_i2c_ctor, 281 + .dtor = _nouveau_i2c_dtor, 282 + .init = _nouveau_i2c_init, 283 + .fini = _nouveau_i2c_fini, 284 + }, 285 + };
+124
drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
··· 1 + /* 2 + * Copyright 2012 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 "nv50.h" 26 + 27 + static int 28 + nvd0_i2c_sense_scl(struct nouveau_i2c_port *base) 29 + { 30 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 31 + struct nv50_i2c_port *port = (void *)base; 32 + return !!(nv_rd32(priv, port->addr) & 0x00000010); 33 + } 34 + 35 + static int 36 + nvd0_i2c_sense_sda(struct nouveau_i2c_port *base) 37 + { 38 + struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 39 + struct nv50_i2c_port *port = (void *)base; 40 + return !!(nv_rd32(priv, port->addr) & 0x00000020); 41 + } 42 + 43 + static const struct nouveau_i2c_func 44 + nvd0_i2c_func = { 45 + .acquire = nv94_i2c_acquire, 46 + .release = nv94_i2c_release, 47 + .drive_scl = nv50_i2c_drive_scl, 48 + .drive_sda = nv50_i2c_drive_sda, 49 + .sense_scl = nvd0_i2c_sense_scl, 50 + .sense_sda = nvd0_i2c_sense_sda, 51 + }; 52 + 53 + static int 54 + nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 55 + struct nouveau_oclass *oclass, void *data, u32 index, 56 + struct nouveau_object **pobject) 57 + { 58 + struct dcb_i2c_entry *info = data; 59 + struct nv50_i2c_port *port; 60 + int ret; 61 + 62 + ret = nouveau_i2c_port_create(parent, engine, oclass, index, 63 + &nouveau_i2c_bit_algo, &port); 64 + *pobject = nv_object(port); 65 + if (ret) 66 + return ret; 67 + 68 + port->base.func = &nvd0_i2c_func; 69 + port->state = 0x00000007; 70 + port->addr = 0x00d014 + (info->drive * 0x20); 71 + if (info->share != DCB_I2C_UNUSED) { 72 + port->ctrl = 0x00e500 + (info->share * 0x50); 73 + port->data = 0x0000e001; 74 + } 75 + return 0; 76 + } 77 + 78 + static struct nouveau_oclass 79 + nvd0_i2c_sclass[] = { 80 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), 81 + .ofuncs = &(struct nouveau_ofuncs) { 82 + .ctor = nvd0_i2c_port_ctor, 83 + .dtor = _nouveau_i2c_port_dtor, 84 + .init = nv50_i2c_port_init, 85 + .fini = _nouveau_i2c_port_fini, 86 + }, 87 + }, 88 + { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX), 89 + .ofuncs = &(struct nouveau_ofuncs) { 90 + .ctor = nv94_aux_port_ctor, 91 + .dtor = _nouveau_i2c_port_dtor, 92 + .init = _nouveau_i2c_port_init, 93 + .fini = _nouveau_i2c_port_fini, 94 + }, 95 + }, 96 + {} 97 + }; 98 + 99 + static int 100 + nvd0_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 101 + struct nouveau_oclass *oclass, void *data, u32 size, 102 + struct nouveau_object **pobject) 103 + { 104 + struct nv50_i2c_priv *priv; 105 + int ret; 106 + 107 + ret = nouveau_i2c_create(parent, engine, oclass, nvd0_i2c_sclass, &priv); 108 + *pobject = nv_object(priv); 109 + if (ret) 110 + return ret; 111 + 112 + return 0; 113 + } 114 + 115 + struct nouveau_oclass 116 + nvd0_i2c_oclass = { 117 + .handle = NV_SUBDEV(I2C, 0xd0), 118 + .ofuncs = &(struct nouveau_ofuncs) { 119 + .ctor = nvd0_i2c_ctor, 120 + .dtor = _nouveau_i2c_dtor, 121 + .init = _nouveau_i2c_init, 122 + .fini = _nouveau_i2c_fini, 123 + }, 124 + };
+1 -1
drivers/gpu/drm/nouveau/core/subdev/mc/nv04.c
··· 37 37 { 0x00100000, NVDEV_SUBDEV_TIMER }, 38 38 { 0x01000000, NVDEV_ENGINE_DISP }, /* NV04- PCRTC0 */ 39 39 { 0x02000000, NVDEV_ENGINE_DISP }, /* NV11- PCRTC1 */ 40 - { 0x10000000, NVDEV_SUBDEV_GPIO }, /* PBUS */ 40 + { 0x10000000, NVDEV_SUBDEV_BUS }, 41 41 { 0x80000000, NVDEV_ENGINE_SW }, 42 42 {} 43 43 };
+1
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
··· 38 38 { 0x00100000, NVDEV_SUBDEV_TIMER }, 39 39 { 0x00200000, NVDEV_SUBDEV_GPIO }, 40 40 { 0x04000000, NVDEV_ENGINE_DISP }, 41 + { 0x10000000, NVDEV_SUBDEV_BUS }, 41 42 { 0x80000000, NVDEV_ENGINE_SW }, 42 43 { 0x0000d101, NVDEV_SUBDEV_FB }, 43 44 {},
+2
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
··· 35 35 { 0x00001000, NVDEV_ENGINE_GR }, 36 36 { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ 37 37 { 0x00008000, NVDEV_ENGINE_BSP }, 38 + { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ 38 39 { 0x00100000, NVDEV_SUBDEV_TIMER }, 39 40 { 0x00200000, NVDEV_SUBDEV_GPIO }, 40 41 { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */ 41 42 { 0x04000000, NVDEV_ENGINE_DISP }, 43 + { 0x10000000, NVDEV_SUBDEV_BUS }, 42 44 { 0x80000000, NVDEV_ENGINE_SW }, 43 45 { 0x0040d101, NVDEV_SUBDEV_FB }, 44 46 {},
+2
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
··· 36 36 { 0x00000100, NVDEV_ENGINE_FIFO }, 37 37 { 0x00001000, NVDEV_ENGINE_GR }, 38 38 { 0x00008000, NVDEV_ENGINE_BSP }, 39 + { 0x00040000, NVDEV_SUBDEV_THERM }, 39 40 { 0x00020000, NVDEV_ENGINE_VP }, 40 41 { 0x00100000, NVDEV_SUBDEV_TIMER }, 41 42 { 0x00200000, NVDEV_SUBDEV_GPIO }, 42 43 { 0x02000000, NVDEV_SUBDEV_LTCG }, 43 44 { 0x04000000, NVDEV_ENGINE_DISP }, 45 + { 0x10000000, NVDEV_SUBDEV_BUS }, 44 46 { 0x40000000, NVDEV_SUBDEV_IBUS }, 45 47 { 0x80000000, NVDEV_ENGINE_SW }, 46 48 {},
+4 -4
drivers/gpu/drm/nouveau/core/subdev/mxm/mxms.c
··· 156 156 157 157 nv_debug(mxm, "%4s: ", mxms_desc_name[type]); 158 158 for (j = headerlen - 1; j >= 0; j--) 159 - printk("%02x", dump[j]); 160 - printk("\n"); 159 + pr_cont("%02x", dump[j]); 160 + pr_cont("\n"); 161 161 dump += headerlen; 162 162 163 163 for (i = 0; i < entries; i++, dump += recordlen) { 164 164 nv_debug(mxm, " "); 165 165 for (j = recordlen - 1; j >= 0; j--) 166 - printk("%02x", dump[j]); 167 - printk("\n"); 166 + pr_cont("%02x", dump[j]); 167 + pr_cont("\n"); 168 168 } 169 169 } 170 170
+202 -16
drivers/gpu/drm/nouveau/core/subdev/therm/base.c
··· 29 29 30 30 #include "priv.h" 31 31 32 + static int 33 + nouveau_therm_update_trip(struct nouveau_therm *therm) 34 + { 35 + struct nouveau_therm_priv *priv = (void *)therm; 36 + struct nouveau_therm_trip_point *trip = priv->fan->bios.trip, 37 + *cur_trip = NULL, 38 + *last_trip = priv->last_trip; 39 + u8 temp = therm->temp_get(therm); 40 + u16 duty, i; 41 + 42 + /* look for the trip point corresponding to the current temperature */ 43 + cur_trip = NULL; 44 + for (i = 0; i < priv->fan->bios.nr_fan_trip; i++) { 45 + if (temp >= trip[i].temp) 46 + cur_trip = &trip[i]; 47 + } 48 + 49 + /* account for the hysteresis cycle */ 50 + if (last_trip && temp <= (last_trip->temp) && 51 + temp > (last_trip->temp - last_trip->hysteresis)) 52 + cur_trip = last_trip; 53 + 54 + if (cur_trip) { 55 + duty = cur_trip->fan_duty; 56 + priv->last_trip = cur_trip; 57 + } else { 58 + duty = 0; 59 + priv->last_trip = NULL; 60 + } 61 + 62 + return duty; 63 + } 64 + 65 + static int 66 + nouveau_therm_update_linear(struct nouveau_therm *therm) 67 + { 68 + struct nouveau_therm_priv *priv = (void *)therm; 69 + u8 linear_min_temp = priv->fan->bios.linear_min_temp; 70 + u8 linear_max_temp = priv->fan->bios.linear_max_temp; 71 + u8 temp = therm->temp_get(therm); 72 + u16 duty; 73 + 74 + /* handle the non-linear part first */ 75 + if (temp < linear_min_temp) 76 + return priv->fan->bios.min_duty; 77 + else if (temp > linear_max_temp) 78 + return priv->fan->bios.max_duty; 79 + 80 + /* we are in the linear zone */ 81 + duty = (temp - linear_min_temp); 82 + duty *= (priv->fan->bios.max_duty - priv->fan->bios.min_duty); 83 + duty /= (linear_max_temp - linear_min_temp); 84 + duty += priv->fan->bios.min_duty; 85 + 86 + return duty; 87 + } 88 + 89 + static void 90 + nouveau_therm_update(struct nouveau_therm *therm, int mode) 91 + { 92 + struct nouveau_timer *ptimer = nouveau_timer(therm); 93 + struct nouveau_therm_priv *priv = (void *)therm; 94 + unsigned long flags; 95 + int duty; 96 + 97 + spin_lock_irqsave(&priv->lock, flags); 98 + if (mode < 0) 99 + mode = priv->mode; 100 + priv->mode = mode; 101 + 102 + switch (mode) { 103 + case NOUVEAU_THERM_CTRL_MANUAL: 104 + duty = nouveau_therm_fan_get(therm); 105 + if (duty < 0) 106 + duty = 100; 107 + break; 108 + case NOUVEAU_THERM_CTRL_AUTO: 109 + if (priv->fan->bios.nr_fan_trip) 110 + duty = nouveau_therm_update_trip(therm); 111 + else 112 + duty = nouveau_therm_update_linear(therm); 113 + break; 114 + case NOUVEAU_THERM_CTRL_NONE: 115 + default: 116 + goto done; 117 + } 118 + 119 + nv_debug(therm, "FAN target request: %d%%\n", duty); 120 + nouveau_therm_fan_set(therm, (mode != NOUVEAU_THERM_CTRL_AUTO), duty); 121 + 122 + done: 123 + if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) 124 + ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); 125 + spin_unlock_irqrestore(&priv->lock, flags); 126 + } 127 + 128 + static void 129 + nouveau_therm_alarm(struct nouveau_alarm *alarm) 130 + { 131 + struct nouveau_therm_priv *priv = 132 + container_of(alarm, struct nouveau_therm_priv, alarm); 133 + nouveau_therm_update(&priv->base, -1); 134 + } 135 + 136 + int 137 + nouveau_therm_mode(struct nouveau_therm *therm, int mode) 138 + { 139 + struct nouveau_therm_priv *priv = (void *)therm; 140 + struct nouveau_device *device = nv_device(therm); 141 + static const char *name[] = { 142 + "disabled", 143 + "manual", 144 + "automatic" 145 + }; 146 + 147 + /* The default PDAEMON ucode interferes with fan management */ 148 + if ((mode >= ARRAY_SIZE(name)) || 149 + (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) 150 + return -EINVAL; 151 + 152 + if (priv->mode == mode) 153 + return 0; 154 + 155 + nv_info(therm, "Thermal management: %s\n", name[mode]); 156 + nouveau_therm_update(therm, mode); 157 + return 0; 158 + } 159 + 32 160 int 33 161 nouveau_therm_attr_get(struct nouveau_therm *therm, 34 162 enum nouveau_therm_attr_type type) ··· 165 37 166 38 switch (type) { 167 39 case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: 168 - return priv->bios_fan.min_duty; 40 + return priv->fan->bios.min_duty; 169 41 case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: 170 - return priv->bios_fan.max_duty; 42 + return priv->fan->bios.max_duty; 171 43 case NOUVEAU_THERM_ATTR_FAN_MODE: 172 - return priv->fan.mode; 44 + return priv->mode; 173 45 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: 174 46 return priv->bios_sensor.thrs_fan_boost.temp; 175 47 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: ··· 201 73 case NOUVEAU_THERM_ATTR_FAN_MIN_DUTY: 202 74 if (value < 0) 203 75 value = 0; 204 - if (value > priv->bios_fan.max_duty) 205 - value = priv->bios_fan.max_duty; 206 - priv->bios_fan.min_duty = value; 76 + if (value > priv->fan->bios.max_duty) 77 + value = priv->fan->bios.max_duty; 78 + priv->fan->bios.min_duty = value; 207 79 return 0; 208 80 case NOUVEAU_THERM_ATTR_FAN_MAX_DUTY: 209 81 if (value < 0) 210 82 value = 0; 211 - if (value < priv->bios_fan.min_duty) 212 - value = priv->bios_fan.min_duty; 213 - priv->bios_fan.max_duty = value; 83 + if (value < priv->fan->bios.min_duty) 84 + value = priv->fan->bios.min_duty; 85 + priv->fan->bios.max_duty = value; 214 86 return 0; 215 87 case NOUVEAU_THERM_ATTR_FAN_MODE: 216 - return nouveau_therm_fan_set_mode(therm, value); 88 + return nouveau_therm_mode(therm, value); 217 89 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: 218 90 priv->bios_sensor.thrs_fan_boost.temp = value; 91 + priv->sensor.program_alarms(therm); 219 92 return 0; 220 93 case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST: 221 94 priv->bios_sensor.thrs_fan_boost.hysteresis = value; 95 + priv->sensor.program_alarms(therm); 222 96 return 0; 223 97 case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK: 224 98 priv->bios_sensor.thrs_down_clock.temp = value; 99 + priv->sensor.program_alarms(therm); 225 100 return 0; 226 101 case NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST: 227 102 priv->bios_sensor.thrs_down_clock.hysteresis = value; 103 + priv->sensor.program_alarms(therm); 228 104 return 0; 229 105 case NOUVEAU_THERM_ATTR_THRS_CRITICAL: 230 106 priv->bios_sensor.thrs_critical.temp = value; 107 + priv->sensor.program_alarms(therm); 231 108 return 0; 232 109 case NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST: 233 110 priv->bios_sensor.thrs_critical.hysteresis = value; 111 + priv->sensor.program_alarms(therm); 234 112 return 0; 235 113 case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN: 236 114 priv->bios_sensor.thrs_shutdown.temp = value; 115 + priv->sensor.program_alarms(therm); 237 116 return 0; 238 117 case NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST: 239 118 priv->bios_sensor.thrs_shutdown.hysteresis = value; 119 + priv->sensor.program_alarms(therm); 240 120 return 0; 241 121 } 242 122 ··· 252 116 } 253 117 254 118 int 255 - nouveau_therm_init(struct nouveau_object *object) 119 + _nouveau_therm_init(struct nouveau_object *object) 256 120 { 257 121 struct nouveau_therm *therm = (void *)object; 258 122 struct nouveau_therm_priv *priv = (void *)therm; ··· 262 126 if (ret) 263 127 return ret; 264 128 265 - if (priv->fan.percent >= 0) 266 - therm->fan_set(therm, priv->fan.percent); 267 - 129 + if (priv->suspend >= 0) 130 + nouveau_therm_mode(therm, priv->mode); 131 + priv->sensor.program_alarms(therm); 268 132 return 0; 269 133 } 270 134 271 135 int 272 - nouveau_therm_fini(struct nouveau_object *object, bool suspend) 136 + _nouveau_therm_fini(struct nouveau_object *object, bool suspend) 273 137 { 274 138 struct nouveau_therm *therm = (void *)object; 275 139 struct nouveau_therm_priv *priv = (void *)therm; 276 140 277 - priv->fan.percent = therm->fan_get(therm); 141 + if (suspend) { 142 + priv->suspend = priv->mode; 143 + priv->mode = NOUVEAU_THERM_CTRL_NONE; 144 + } 278 145 279 146 return nouveau_subdev_fini(&therm->base, suspend); 147 + } 148 + 149 + int 150 + nouveau_therm_create_(struct nouveau_object *parent, 151 + struct nouveau_object *engine, 152 + struct nouveau_oclass *oclass, 153 + int length, void **pobject) 154 + { 155 + struct nouveau_therm_priv *priv; 156 + int ret; 157 + 158 + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "PTHERM", 159 + "therm", length, pobject); 160 + priv = *pobject; 161 + if (ret) 162 + return ret; 163 + 164 + nouveau_alarm_init(&priv->alarm, nouveau_therm_alarm); 165 + spin_lock_init(&priv->lock); 166 + spin_lock_init(&priv->sensor.alarm_program_lock); 167 + 168 + priv->base.fan_get = nouveau_therm_fan_user_get; 169 + priv->base.fan_set = nouveau_therm_fan_user_set; 170 + priv->base.fan_sense = nouveau_therm_fan_sense; 171 + priv->base.attr_get = nouveau_therm_attr_get; 172 + priv->base.attr_set = nouveau_therm_attr_set; 173 + priv->mode = priv->suspend = -1; /* undefined */ 174 + return 0; 175 + } 176 + 177 + int 178 + nouveau_therm_preinit(struct nouveau_therm *therm) 179 + { 180 + nouveau_therm_ic_ctor(therm); 181 + nouveau_therm_sensor_ctor(therm); 182 + nouveau_therm_fan_ctor(therm); 183 + 184 + nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE); 185 + return 0; 186 + } 187 + 188 + void 189 + _nouveau_therm_dtor(struct nouveau_object *object) 190 + { 191 + struct nouveau_therm_priv *priv = (void *)object; 192 + kfree(priv->fan); 193 + nouveau_subdev_destroy(&priv->base.base); 280 194 }
+135 -115
drivers/gpu/drm/nouveau/core/subdev/therm/fan.c
··· 27 27 28 28 #include <core/object.h> 29 29 #include <core/device.h> 30 + 30 31 #include <subdev/gpio.h> 31 32 #include <subdev/timer.h> 33 + 34 + static int 35 + nouveau_fan_update(struct nouveau_fan *fan, bool immediate, int target) 36 + { 37 + struct nouveau_therm *therm = fan->parent; 38 + struct nouveau_therm_priv *priv = (void *)therm; 39 + struct nouveau_timer *ptimer = nouveau_timer(priv); 40 + unsigned long flags; 41 + int ret = 0; 42 + int duty; 43 + 44 + /* update target fan speed, restricting to allowed range */ 45 + spin_lock_irqsave(&fan->lock, flags); 46 + if (target < 0) 47 + target = fan->percent; 48 + target = max_t(u8, target, fan->bios.min_duty); 49 + target = min_t(u8, target, fan->bios.max_duty); 50 + if (fan->percent != target) { 51 + nv_debug(therm, "FAN target: %d\n", target); 52 + fan->percent = target; 53 + } 54 + 55 + /* check that we're not already at the target duty cycle */ 56 + duty = fan->get(therm); 57 + if (duty == target) 58 + goto done; 59 + 60 + /* smooth out the fanspeed increase/decrease */ 61 + if (!immediate && duty >= 0) { 62 + /* the constant "3" is a rough approximation taken from 63 + * nvidia's behaviour. 64 + * it is meant to bump the fan speed more incrementally 65 + */ 66 + if (duty < target) 67 + duty = min(duty + 3, target); 68 + else if (duty > target) 69 + duty = max(duty - 3, target); 70 + } else { 71 + duty = target; 72 + } 73 + 74 + nv_debug(therm, "FAN update: %d\n", duty); 75 + ret = fan->set(therm, duty); 76 + if (ret) 77 + goto done; 78 + 79 + /* schedule next fan update, if not at target speed already */ 80 + if (list_empty(&fan->alarm.head) && target != duty) { 81 + u16 bump_period = fan->bios.bump_period; 82 + u16 slow_down_period = fan->bios.slow_down_period; 83 + u64 delay; 84 + 85 + if (duty > target) 86 + delay = slow_down_period; 87 + else if (duty == target) 88 + delay = min(bump_period, slow_down_period) ; 89 + else 90 + delay = bump_period; 91 + 92 + ptimer->alarm(ptimer, delay * 1000 * 1000, &fan->alarm); 93 + } 94 + 95 + done: 96 + spin_unlock_irqrestore(&fan->lock, flags); 97 + return ret; 98 + } 99 + 100 + static void 101 + nouveau_fan_alarm(struct nouveau_alarm *alarm) 102 + { 103 + struct nouveau_fan *fan = container_of(alarm, struct nouveau_fan, alarm); 104 + nouveau_fan_update(fan, false, -1); 105 + } 32 106 33 107 int 34 108 nouveau_therm_fan_get(struct nouveau_therm *therm) 35 109 { 36 110 struct nouveau_therm_priv *priv = (void *)therm; 37 - struct nouveau_gpio *gpio = nouveau_gpio(therm); 38 - struct dcb_gpio_func func; 39 - int card_type = nv_device(therm)->card_type; 40 - u32 divs, duty; 41 - int ret; 42 - 43 - if (!priv->fan.pwm_get) 44 - return -ENODEV; 45 - 46 - ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); 47 - if (ret == 0) { 48 - ret = priv->fan.pwm_get(therm, func.line, &divs, &duty); 49 - if (ret == 0 && divs) { 50 - divs = max(divs, duty); 51 - if (card_type <= NV_40 || (func.log[0] & 1)) 52 - duty = divs - duty; 53 - return (duty * 100) / divs; 54 - } 55 - 56 - return gpio->get(gpio, 0, func.func, func.line) * 100; 57 - } 58 - 59 - return -ENODEV; 111 + return priv->fan->get(therm); 60 112 } 61 113 62 114 int 63 - nouveau_therm_fan_set(struct nouveau_therm *therm, int percent) 115 + nouveau_therm_fan_set(struct nouveau_therm *therm, bool immediate, int percent) 64 116 { 65 117 struct nouveau_therm_priv *priv = (void *)therm; 66 - struct nouveau_gpio *gpio = nouveau_gpio(therm); 67 - struct dcb_gpio_func func; 68 - int card_type = nv_device(therm)->card_type; 69 - u32 divs, duty; 70 - int ret; 71 - 72 - if (priv->fan.mode == FAN_CONTROL_NONE) 73 - return -EINVAL; 74 - 75 - if (!priv->fan.pwm_set) 76 - return -ENODEV; 77 - 78 - if (percent < priv->bios_fan.min_duty) 79 - percent = priv->bios_fan.min_duty; 80 - if (percent > priv->bios_fan.max_duty) 81 - percent = priv->bios_fan.max_duty; 82 - 83 - ret = gpio->find(gpio, 0, DCB_GPIO_PWM_FAN, 0xff, &func); 84 - if (ret == 0) { 85 - divs = priv->bios_perf_fan.pwm_divisor; 86 - if (priv->bios_fan.pwm_freq) { 87 - divs = 1; 88 - if (priv->fan.pwm_clock) 89 - divs = priv->fan.pwm_clock(therm); 90 - divs /= priv->bios_fan.pwm_freq; 91 - } 92 - 93 - duty = ((divs * percent) + 99) / 100; 94 - if (card_type <= NV_40 || (func.log[0] & 1)) 95 - duty = divs - duty; 96 - 97 - ret = priv->fan.pwm_set(therm, func.line, divs, duty); 98 - return ret; 99 - } 100 - 101 - return -ENODEV; 118 + return nouveau_fan_update(priv->fan, immediate, percent); 102 119 } 103 120 104 121 int 105 122 nouveau_therm_fan_sense(struct nouveau_therm *therm) 106 123 { 124 + struct nouveau_therm_priv *priv = (void *)therm; 107 125 struct nouveau_timer *ptimer = nouveau_timer(therm); 108 126 struct nouveau_gpio *gpio = nouveau_gpio(therm); 109 - struct dcb_gpio_func func; 110 127 u32 cycles, cur, prev; 111 128 u64 start, end, tach; 112 129 113 - if (gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &func)) 130 + if (priv->fan->tach.func == DCB_GPIO_UNUSED) 114 131 return -ENODEV; 115 132 116 133 /* Time a complete rotation and extrapolate to RPM: ··· 135 118 * We get 4 changes (0 -> 1 -> 0 -> 1) per complete rotation. 136 119 */ 137 120 start = ptimer->read(ptimer); 138 - prev = gpio->get(gpio, 0, func.func, func.line); 121 + prev = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line); 139 122 cycles = 0; 140 123 do { 141 124 usleep_range(500, 1000); /* supports 0 < rpm < 7500 */ 142 125 143 - cur = gpio->get(gpio, 0, func.func, func.line); 126 + cur = gpio->get(gpio, 0, priv->fan->tach.func, priv->fan->tach.line); 144 127 if (prev != cur) { 145 128 if (!start) 146 129 start = ptimer->read(ptimer); ··· 159 142 } 160 143 161 144 int 162 - nouveau_therm_fan_set_mode(struct nouveau_therm *therm, 163 - enum nouveau_therm_fan_mode mode) 164 - { 165 - struct nouveau_therm_priv *priv = (void *)therm; 166 - 167 - if (priv->fan.mode == mode) 168 - return 0; 169 - 170 - if (mode < FAN_CONTROL_NONE || mode >= FAN_CONTROL_NR) 171 - return -EINVAL; 172 - 173 - switch (mode) 174 - { 175 - case FAN_CONTROL_NONE: 176 - nv_info(therm, "switch fan to no-control mode\n"); 177 - break; 178 - case FAN_CONTROL_MANUAL: 179 - nv_info(therm, "switch fan to manual mode\n"); 180 - break; 181 - case FAN_CONTROL_NR: 182 - break; 183 - } 184 - 185 - priv->fan.mode = mode; 186 - return 0; 187 - } 188 - 189 - int 190 145 nouveau_therm_fan_user_get(struct nouveau_therm *therm) 191 146 { 192 147 return nouveau_therm_fan_get(therm); ··· 169 180 { 170 181 struct nouveau_therm_priv *priv = (void *)therm; 171 182 172 - if (priv->fan.mode != FAN_CONTROL_MANUAL) 183 + if (priv->mode != NOUVEAU_THERM_CTRL_MANUAL) 173 184 return -EINVAL; 174 185 175 - return nouveau_therm_fan_set(therm, percent); 186 + return nouveau_therm_fan_set(therm, true, percent); 176 187 } 177 188 178 - void 189 + static void 179 190 nouveau_therm_fan_set_defaults(struct nouveau_therm *therm) 180 191 { 181 192 struct nouveau_therm_priv *priv = (void *)therm; 182 193 183 - priv->bios_fan.pwm_freq = 0; 184 - priv->bios_fan.min_duty = 0; 185 - priv->bios_fan.max_duty = 100; 194 + priv->fan->bios.pwm_freq = 0; 195 + priv->fan->bios.min_duty = 0; 196 + priv->fan->bios.max_duty = 100; 197 + priv->fan->bios.bump_period = 500; 198 + priv->fan->bios.slow_down_period = 2000; 199 + priv->fan->bios.linear_min_temp = 40; 200 + priv->fan->bios.linear_max_temp = 85; 186 201 } 187 - 188 202 189 203 static void 190 204 nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) 191 205 { 192 206 struct nouveau_therm_priv *priv = (void *)therm; 193 207 194 - if (priv->bios_fan.min_duty > 100) 195 - priv->bios_fan.min_duty = 100; 196 - if (priv->bios_fan.max_duty > 100) 197 - priv->bios_fan.max_duty = 100; 208 + if (priv->fan->bios.min_duty > 100) 209 + priv->fan->bios.min_duty = 100; 210 + if (priv->fan->bios.max_duty > 100) 211 + priv->fan->bios.max_duty = 100; 198 212 199 - if (priv->bios_fan.min_duty > priv->bios_fan.max_duty) 200 - priv->bios_fan.min_duty = priv->bios_fan.max_duty; 201 - } 202 - 203 - int nouveau_fan_pwm_clock_dummy(struct nouveau_therm *therm) 204 - { 205 - return 1; 213 + if (priv->fan->bios.min_duty > priv->fan->bios.max_duty) 214 + priv->fan->bios.min_duty = priv->fan->bios.max_duty; 206 215 } 207 216 208 217 int 209 218 nouveau_therm_fan_ctor(struct nouveau_therm *therm) 210 219 { 211 220 struct nouveau_therm_priv *priv = (void *)therm; 221 + struct nouveau_gpio *gpio = nouveau_gpio(therm); 212 222 struct nouveau_bios *bios = nouveau_bios(therm); 223 + struct dcb_gpio_func func; 224 + int ret; 213 225 226 + /* attempt to locate a drivable fan, and determine control method */ 227 + ret = gpio->find(gpio, 0, DCB_GPIO_FAN, 0xff, &func); 228 + if (ret == 0) { 229 + if (func.log[0] & DCB_GPIO_LOG_DIR_IN) { 230 + nv_debug(therm, "GPIO_FAN is in input mode\n"); 231 + ret = -EINVAL; 232 + } else { 233 + ret = nouveau_fanpwm_create(therm, &func); 234 + if (ret != 0) 235 + ret = nouveau_fantog_create(therm, &func); 236 + } 237 + } 238 + 239 + /* no controllable fan found, create a dummy fan module */ 240 + if (ret != 0) { 241 + ret = nouveau_fannil_create(therm); 242 + if (ret) 243 + return ret; 244 + } 245 + 246 + nv_info(therm, "FAN control: %s\n", priv->fan->type); 247 + 248 + /* attempt to detect a tachometer connection */ 249 + ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); 250 + if (ret) 251 + priv->fan->tach.func = DCB_GPIO_UNUSED; 252 + 253 + /* initialise fan bump/slow update handling */ 254 + priv->fan->parent = therm; 255 + nouveau_alarm_init(&priv->fan->alarm, nouveau_fan_alarm); 256 + spin_lock_init(&priv->fan->lock); 257 + 258 + /* other random init... */ 214 259 nouveau_therm_fan_set_defaults(therm); 215 - nvbios_perf_fan_parse(bios, &priv->bios_perf_fan); 216 - if (nvbios_therm_fan_parse(bios, &priv->bios_fan)) 260 + nvbios_perf_fan_parse(bios, &priv->fan->perf); 261 + if (nvbios_therm_fan_parse(bios, &priv->fan->bios)) 217 262 nv_error(therm, "parsing the thermal table failed\n"); 218 263 nouveau_therm_fan_safety_checks(therm); 219 - 220 - nouveau_therm_fan_set_mode(therm, FAN_CONTROL_NONE); 221 - 222 264 return 0; 223 265 }
+54
drivers/gpu/drm/nouveau/core/subdev/therm/fannil.c
··· 1 + /* 2 + * Copyright 2012 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 "priv.h" 26 + 27 + static int 28 + nouveau_fannil_get(struct nouveau_therm *therm) 29 + { 30 + return -ENODEV; 31 + } 32 + 33 + static int 34 + nouveau_fannil_set(struct nouveau_therm *therm, int percent) 35 + { 36 + return -ENODEV; 37 + } 38 + 39 + int 40 + nouveau_fannil_create(struct nouveau_therm *therm) 41 + { 42 + struct nouveau_therm_priv *tpriv = (void *)therm; 43 + struct nouveau_fan *priv; 44 + 45 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 46 + tpriv->fan = priv; 47 + if (!priv) 48 + return -ENOMEM; 49 + 50 + priv->type = "none / external"; 51 + priv->get = nouveau_fannil_get; 52 + priv->set = nouveau_fannil_set; 53 + return 0; 54 + }
+107
drivers/gpu/drm/nouveau/core/subdev/therm/fanpwm.c
··· 1 + /* 2 + * Copyright 2012 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 + * Martin Peres 24 + */ 25 + 26 + #include <core/option.h> 27 + #include <subdev/gpio.h> 28 + 29 + #include "priv.h" 30 + 31 + struct nouveau_fanpwm_priv { 32 + struct nouveau_fan base; 33 + struct dcb_gpio_func func; 34 + }; 35 + 36 + static int 37 + nouveau_fanpwm_get(struct nouveau_therm *therm) 38 + { 39 + struct nouveau_therm_priv *tpriv = (void *)therm; 40 + struct nouveau_fanpwm_priv *priv = (void *)tpriv->fan; 41 + struct nouveau_gpio *gpio = nouveau_gpio(therm); 42 + int card_type = nv_device(therm)->card_type; 43 + u32 divs, duty; 44 + int ret; 45 + 46 + ret = therm->pwm_get(therm, priv->func.line, &divs, &duty); 47 + if (ret == 0 && divs) { 48 + divs = max(divs, duty); 49 + if (card_type <= NV_40 || (priv->func.log[0] & 1)) 50 + duty = divs - duty; 51 + return (duty * 100) / divs; 52 + } 53 + 54 + return gpio->get(gpio, 0, priv->func.func, priv->func.line) * 100; 55 + } 56 + 57 + static int 58 + nouveau_fanpwm_set(struct nouveau_therm *therm, int percent) 59 + { 60 + struct nouveau_therm_priv *tpriv = (void *)therm; 61 + struct nouveau_fanpwm_priv *priv = (void *)tpriv->fan; 62 + int card_type = nv_device(therm)->card_type; 63 + u32 divs, duty; 64 + int ret; 65 + 66 + divs = priv->base.perf.pwm_divisor; 67 + if (priv->base.bios.pwm_freq) { 68 + divs = 1; 69 + if (therm->pwm_clock) 70 + divs = therm->pwm_clock(therm); 71 + divs /= priv->base.bios.pwm_freq; 72 + } 73 + 74 + duty = ((divs * percent) + 99) / 100; 75 + if (card_type <= NV_40 || (priv->func.log[0] & 1)) 76 + duty = divs - duty; 77 + 78 + ret = therm->pwm_set(therm, priv->func.line, divs, duty); 79 + if (ret == 0) 80 + ret = therm->pwm_ctrl(therm, priv->func.line, true); 81 + return ret; 82 + } 83 + 84 + int 85 + nouveau_fanpwm_create(struct nouveau_therm *therm, struct dcb_gpio_func *func) 86 + { 87 + struct nouveau_device *device = nv_device(therm); 88 + struct nouveau_therm_priv *tpriv = (void *)therm; 89 + struct nouveau_fanpwm_priv *priv; 90 + u32 divs, duty; 91 + 92 + if (!nouveau_boolopt(device->cfgopt, "NvFanPWM", func->param) || 93 + !therm->pwm_ctrl || 94 + therm->pwm_get(therm, func->line, &divs, &duty) == -ENODEV) 95 + return -ENODEV; 96 + 97 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 98 + tpriv->fan = &priv->base; 99 + if (!priv) 100 + return -ENOMEM; 101 + 102 + priv->base.type = "PWM"; 103 + priv->base.get = nouveau_fanpwm_get; 104 + priv->base.set = nouveau_fanpwm_set; 105 + priv->func = *func; 106 + return 0; 107 + }
+115
drivers/gpu/drm/nouveau/core/subdev/therm/fantog.c
··· 1 + /* 2 + * Copyright 2012 The Nouveau community 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 + 25 + #include "priv.h" 26 + 27 + #include <core/object.h> 28 + #include <core/device.h> 29 + 30 + #include <subdev/gpio.h> 31 + #include <subdev/timer.h> 32 + 33 + struct nouveau_fantog_priv { 34 + struct nouveau_fan base; 35 + struct nouveau_alarm alarm; 36 + spinlock_t lock; 37 + u32 period_us; 38 + u32 percent; 39 + struct dcb_gpio_func func; 40 + }; 41 + 42 + static void 43 + nouveau_fantog_update(struct nouveau_fantog_priv *priv, int percent) 44 + { 45 + struct nouveau_therm_priv *tpriv = (void *)priv->base.parent; 46 + struct nouveau_timer *ptimer = nouveau_timer(tpriv); 47 + struct nouveau_gpio *gpio = nouveau_gpio(tpriv); 48 + unsigned long flags; 49 + int duty; 50 + 51 + spin_lock_irqsave(&priv->lock, flags); 52 + if (percent < 0) 53 + percent = priv->percent; 54 + priv->percent = percent; 55 + 56 + duty = !gpio->get(gpio, 0, DCB_GPIO_FAN, 0xff); 57 + gpio->set(gpio, 0, DCB_GPIO_FAN, 0xff, duty); 58 + 59 + if (list_empty(&priv->alarm.head) && percent != (duty * 100)) { 60 + u64 next_change = (percent * priv->period_us) / 100; 61 + if (!duty) 62 + next_change = priv->period_us - next_change; 63 + ptimer->alarm(ptimer, next_change * 1000, &priv->alarm); 64 + } 65 + spin_unlock_irqrestore(&priv->lock, flags); 66 + } 67 + 68 + static void 69 + nouveau_fantog_alarm(struct nouveau_alarm *alarm) 70 + { 71 + struct nouveau_fantog_priv *priv = 72 + container_of(alarm, struct nouveau_fantog_priv, alarm); 73 + nouveau_fantog_update(priv, -1); 74 + } 75 + 76 + static int 77 + nouveau_fantog_get(struct nouveau_therm *therm) 78 + { 79 + struct nouveau_therm_priv *tpriv = (void *)therm; 80 + struct nouveau_fantog_priv *priv = (void *)tpriv->fan; 81 + return priv->percent; 82 + } 83 + 84 + static int 85 + nouveau_fantog_set(struct nouveau_therm *therm, int percent) 86 + { 87 + struct nouveau_therm_priv *tpriv = (void *)therm; 88 + struct nouveau_fantog_priv *priv = (void *)tpriv->fan; 89 + if (therm->pwm_ctrl) 90 + therm->pwm_ctrl(therm, priv->func.line, false); 91 + nouveau_fantog_update(priv, percent); 92 + return 0; 93 + } 94 + 95 + int 96 + nouveau_fantog_create(struct nouveau_therm *therm, struct dcb_gpio_func *func) 97 + { 98 + struct nouveau_therm_priv *tpriv = (void *)therm; 99 + struct nouveau_fantog_priv *priv; 100 + 101 + priv = kzalloc(sizeof(*priv), GFP_KERNEL); 102 + tpriv->fan = &priv->base; 103 + if (!priv) 104 + return -ENOMEM; 105 + 106 + priv->base.type = "toggle"; 107 + priv->base.get = nouveau_fantog_get; 108 + priv->base.set = nouveau_fantog_set; 109 + nouveau_alarm_init(&priv->alarm, nouveau_fantog_alarm); 110 + priv->period_us = 100000; /* 10Hz */ 111 + priv->percent = 100; 112 + priv->func = *func; 113 + spin_lock_init(&priv->lock); 114 + return 0; 115 + }
+28 -26
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
··· 31 31 probe_monitoring_device(struct nouveau_i2c_port *i2c, 32 32 struct i2c_board_info *info) 33 33 { 34 - struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c->i2c); 34 + struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); 35 35 struct i2c_client *client; 36 36 37 37 request_module("%s%s", I2C_MODULE_PREFIX, info->type); ··· 53 53 return true; 54 54 } 55 55 56 + static struct i2c_board_info 57 + nv_board_infos[] = { 58 + { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 59 + { I2C_BOARD_INFO("w83781d", 0x2d) }, 60 + { I2C_BOARD_INFO("adt7473", 0x2e) }, 61 + { I2C_BOARD_INFO("adt7473", 0x2d) }, 62 + { I2C_BOARD_INFO("adt7473", 0x2c) }, 63 + { I2C_BOARD_INFO("f75375", 0x2e) }, 64 + { I2C_BOARD_INFO("lm99", 0x4c) }, 65 + { I2C_BOARD_INFO("lm90", 0x4c) }, 66 + { I2C_BOARD_INFO("lm90", 0x4d) }, 67 + { I2C_BOARD_INFO("adm1021", 0x18) }, 68 + { I2C_BOARD_INFO("adm1021", 0x19) }, 69 + { I2C_BOARD_INFO("adm1021", 0x1a) }, 70 + { I2C_BOARD_INFO("adm1021", 0x29) }, 71 + { I2C_BOARD_INFO("adm1021", 0x2a) }, 72 + { I2C_BOARD_INFO("adm1021", 0x2b) }, 73 + { I2C_BOARD_INFO("adm1021", 0x4c) }, 74 + { I2C_BOARD_INFO("adm1021", 0x4d) }, 75 + { I2C_BOARD_INFO("adm1021", 0x4e) }, 76 + { I2C_BOARD_INFO("lm63", 0x18) }, 77 + { I2C_BOARD_INFO("lm63", 0x4e) }, 78 + { } 79 + }; 80 + 56 81 void 57 82 nouveau_therm_ic_ctor(struct nouveau_therm *therm) 58 83 { ··· 85 60 struct nouveau_bios *bios = nouveau_bios(therm); 86 61 struct nouveau_i2c *i2c = nouveau_i2c(therm); 87 62 struct nvbios_extdev_func extdev_entry; 88 - struct i2c_board_info info[] = { 89 - { I2C_BOARD_INFO("w83l785ts", 0x2d) }, 90 - { I2C_BOARD_INFO("w83781d", 0x2d) }, 91 - { I2C_BOARD_INFO("adt7473", 0x2e) }, 92 - { I2C_BOARD_INFO("adt7473", 0x2d) }, 93 - { I2C_BOARD_INFO("adt7473", 0x2c) }, 94 - { I2C_BOARD_INFO("f75375", 0x2e) }, 95 - { I2C_BOARD_INFO("lm99", 0x4c) }, 96 - { I2C_BOARD_INFO("lm90", 0x4c) }, 97 - { I2C_BOARD_INFO("lm90", 0x4d) }, 98 - { I2C_BOARD_INFO("adm1021", 0x18) }, 99 - { I2C_BOARD_INFO("adm1021", 0x19) }, 100 - { I2C_BOARD_INFO("adm1021", 0x1a) }, 101 - { I2C_BOARD_INFO("adm1021", 0x29) }, 102 - { I2C_BOARD_INFO("adm1021", 0x2a) }, 103 - { I2C_BOARD_INFO("adm1021", 0x2b) }, 104 - { I2C_BOARD_INFO("adm1021", 0x4c) }, 105 - { I2C_BOARD_INFO("adm1021", 0x4d) }, 106 - { I2C_BOARD_INFO("adm1021", 0x4e) }, 107 - { I2C_BOARD_INFO("lm63", 0x18) }, 108 - { I2C_BOARD_INFO("lm63", 0x4e) }, 109 - { } 110 - }; 111 63 112 64 if (!nvbios_extdev_find(bios, NVBIOS_EXTDEV_LM89, &extdev_entry)) { 113 65 struct i2c_board_info board[] = { ··· 113 111 /* The vbios doesn't provide the address of an exisiting monitoring 114 112 device. Let's try our static list. 115 113 */ 116 - i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", info, 117 - probe_monitoring_device); 114 + i2c->identify(i2c, NV_I2C_DEFAULT(0), "monitoring device", 115 + nv_board_infos, probe_monitoring_device); 118 116 }
+56 -24
drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
··· 25 25 26 26 #include "priv.h" 27 27 28 + struct nv40_therm_priv { 29 + struct nouveau_therm_priv base; 30 + }; 31 + 28 32 static int 29 33 nv40_sensor_setup(struct nouveau_therm *therm) 30 34 { ··· 38 34 if (device->chipset >= 0x46) { 39 35 nv_mask(therm, 0x15b8, 0x80000000, 0); 40 36 nv_wr32(therm, 0x15b0, 0x80003fff); 37 + mdelay(10); /* wait for the temperature to stabilize */ 41 38 return nv_rd32(therm, 0x15b4) & 0x3fff; 42 39 } else { 43 40 nv_wr32(therm, 0x15b0, 0xff); ··· 80 75 return core_temp; 81 76 } 82 77 83 - int 78 + static int 79 + nv40_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable) 80 + { 81 + u32 mask = enable ? 0x80000000 : 0x0000000; 82 + if (line == 2) nv_mask(therm, 0x0010f0, 0x80000000, mask); 83 + else if (line == 9) nv_mask(therm, 0x0015f4, 0x80000000, mask); 84 + else { 85 + nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); 86 + return -ENODEV; 87 + } 88 + return 0; 89 + } 90 + 91 + static int 84 92 nv40_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 85 93 { 86 94 if (line == 2) { ··· 119 101 return -EINVAL; 120 102 } 121 103 122 - int 104 + static int 123 105 nv40_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) 124 106 { 125 107 if (line == 2) { 126 - nv_wr32(therm, 0x0010f0, 0x80000000 | (duty << 16) | divs); 108 + nv_mask(therm, 0x0010f0, 0x7fff7fff, (duty << 16) | divs); 127 109 } else 128 110 if (line == 9) { 129 111 nv_wr32(therm, 0x0015f8, divs); 130 - nv_wr32(therm, 0x0015f4, duty | 0x80000000); 112 + nv_mask(therm, 0x0015f4, 0x7fffffff, duty); 131 113 } else { 132 114 nv_error(therm, "unknown pwm ctrl for gpio %d\n", line); 133 115 return -ENODEV; ··· 136 118 return 0; 137 119 } 138 120 121 + static void 122 + nv40_therm_intr(struct nouveau_subdev *subdev) 123 + { 124 + struct nouveau_therm *therm = nouveau_therm(subdev); 125 + uint32_t stat = nv_rd32(therm, 0x1100); 126 + 127 + /* traitement */ 128 + 129 + /* ack all IRQs */ 130 + nv_wr32(therm, 0x1100, 0x70000); 131 + 132 + nv_error(therm, "THERM received an IRQ: stat = %x\n", stat); 133 + } 134 + 139 135 static int 140 136 nv40_therm_ctor(struct nouveau_object *parent, 141 - struct nouveau_object *engine, 142 - struct nouveau_oclass *oclass, void *data, u32 size, 143 - struct nouveau_object **pobject) 137 + struct nouveau_object *engine, 138 + struct nouveau_oclass *oclass, void *data, u32 size, 139 + struct nouveau_object **pobject) 144 140 { 145 - struct nouveau_therm_priv *priv; 146 - struct nouveau_therm *therm; 141 + struct nv40_therm_priv *priv; 147 142 int ret; 148 143 149 144 ret = nouveau_therm_create(parent, engine, oclass, &priv); 150 145 *pobject = nv_object(priv); 151 - therm = (void *) priv; 152 146 if (ret) 153 147 return ret; 154 148 155 - nouveau_therm_ic_ctor(therm); 156 - nouveau_therm_sensor_ctor(therm); 157 - nouveau_therm_fan_ctor(therm); 149 + priv->base.base.pwm_ctrl = nv40_fan_pwm_ctrl; 150 + priv->base.base.pwm_get = nv40_fan_pwm_get; 151 + priv->base.base.pwm_set = nv40_fan_pwm_set; 152 + priv->base.base.temp_get = nv40_temp_get; 153 + priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; 154 + nv_subdev(priv)->intr = nv40_therm_intr; 155 + return nouveau_therm_preinit(&priv->base.base); 156 + } 158 157 159 - priv->fan.pwm_get = nv40_fan_pwm_get; 160 - priv->fan.pwm_set = nv40_fan_pwm_set; 158 + static int 159 + nv40_therm_init(struct nouveau_object *object) 160 + { 161 + struct nouveau_therm *therm = (void *)object; 161 162 162 - therm->temp_get = nv40_temp_get; 163 - therm->fan_get = nouveau_therm_fan_user_get; 164 - therm->fan_set = nouveau_therm_fan_user_set; 165 - therm->fan_sense = nouveau_therm_fan_sense; 166 - therm->attr_get = nouveau_therm_attr_get; 167 - therm->attr_set = nouveau_therm_attr_set; 163 + nv40_sensor_setup(therm); 168 164 169 - return 0; 165 + return _nouveau_therm_init(object); 170 166 } 171 167 172 168 struct nouveau_oclass ··· 189 157 .ofuncs = &(struct nouveau_ofuncs) { 190 158 .ctor = nv40_therm_ctor, 191 159 .dtor = _nouveau_therm_dtor, 192 - .init = nouveau_therm_init, 193 - .fini = nouveau_therm_fini, 160 + .init = nv40_therm_init, 161 + .fini = _nouveau_therm_fini, 194 162 }, 195 163 };
+176 -23
drivers/gpu/drm/nouveau/core/subdev/therm/nv50.c
··· 25 25 26 26 #include "priv.h" 27 27 28 + struct nv50_therm_priv { 29 + struct nouveau_therm_priv base; 30 + }; 31 + 28 32 static int 29 33 pwm_info(struct nouveau_therm *therm, int *line, int *ctrl, int *indx) 30 34 { ··· 55 51 } 56 52 57 53 int 54 + nv50_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable) 55 + { 56 + u32 data = enable ? 0x00000001 : 0x00000000; 57 + int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); 58 + if (ret == 0) 59 + nv_mask(therm, ctrl, 0x00010001 << line, data << line); 60 + return ret; 61 + } 62 + 63 + int 58 64 nv50_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 59 65 { 60 66 int ctrl, id, ret = pwm_info(therm, &line, &ctrl, &id); ··· 87 73 if (ret) 88 74 return ret; 89 75 90 - nv_mask(therm, ctrl, 0x00010001 << line, 0x00000001 << line); 91 76 nv_wr32(therm, 0x00e114 + (id * 8), divs); 92 77 nv_wr32(therm, 0x00e118 + (id * 8), duty | 0x80000000); 93 78 return 0; ··· 124 111 return nv_rd32(therm, 0x20400); 125 112 } 126 113 114 + static void 115 + nv50_therm_program_alarms(struct nouveau_therm *therm) 116 + { 117 + struct nouveau_therm_priv *priv = (void *)therm; 118 + struct nvbios_therm_sensor *sensor = &priv->bios_sensor; 119 + unsigned long flags; 120 + 121 + spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); 122 + 123 + /* enable RISING and FALLING IRQs for shutdown, THRS 0, 1, 2 and 4 */ 124 + nv_wr32(therm, 0x20000, 0x000003ff); 125 + 126 + /* shutdown: The computer should be shutdown when reached */ 127 + nv_wr32(therm, 0x20484, sensor->thrs_shutdown.hysteresis); 128 + nv_wr32(therm, 0x20480, sensor->thrs_shutdown.temp); 129 + 130 + /* THRS_1 : fan boost*/ 131 + nv_wr32(therm, 0x204c4, sensor->thrs_fan_boost.temp); 132 + 133 + /* THRS_2 : critical */ 134 + nv_wr32(therm, 0x204c0, sensor->thrs_critical.temp); 135 + 136 + /* THRS_4 : down clock */ 137 + nv_wr32(therm, 0x20414, sensor->thrs_down_clock.temp); 138 + spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); 139 + 140 + nv_info(therm, 141 + "Programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", 142 + sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis, 143 + sensor->thrs_down_clock.temp, 144 + sensor->thrs_down_clock.hysteresis, 145 + sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis, 146 + sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis); 147 + 148 + } 149 + 150 + /* must be called with alarm_program_lock taken ! */ 151 + static void 152 + nv50_therm_threshold_hyst_emulation(struct nouveau_therm *therm, 153 + uint32_t thrs_reg, u8 status_bit, 154 + const struct nvbios_therm_threshold *thrs, 155 + enum nouveau_therm_thrs thrs_name) 156 + { 157 + enum nouveau_therm_thrs_direction direction; 158 + enum nouveau_therm_thrs_state prev_state, new_state; 159 + int temp, cur; 160 + 161 + prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name); 162 + temp = nv_rd32(therm, thrs_reg); 163 + 164 + /* program the next threshold */ 165 + if (temp == thrs->temp) { 166 + nv_wr32(therm, thrs_reg, thrs->temp - thrs->hysteresis); 167 + new_state = NOUVEAU_THERM_THRS_HIGHER; 168 + } else { 169 + nv_wr32(therm, thrs_reg, thrs->temp); 170 + new_state = NOUVEAU_THERM_THRS_LOWER; 171 + } 172 + 173 + /* fix the state (in case someone reprogrammed the alarms) */ 174 + cur = therm->temp_get(therm); 175 + if (new_state == NOUVEAU_THERM_THRS_LOWER && cur > thrs->temp) 176 + new_state = NOUVEAU_THERM_THRS_HIGHER; 177 + else if (new_state == NOUVEAU_THERM_THRS_HIGHER && 178 + cur < thrs->temp - thrs->hysteresis) 179 + new_state = NOUVEAU_THERM_THRS_LOWER; 180 + nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state); 181 + 182 + /* find the direction */ 183 + if (prev_state < new_state) 184 + direction = NOUVEAU_THERM_THRS_RISING; 185 + else if (prev_state > new_state) 186 + direction = NOUVEAU_THERM_THRS_FALLING; 187 + else 188 + return; 189 + 190 + /* advertise a change in direction */ 191 + nouveau_therm_sensor_event(therm, thrs_name, direction); 192 + } 193 + 194 + static void 195 + nv50_therm_intr(struct nouveau_subdev *subdev) 196 + { 197 + struct nouveau_therm *therm = nouveau_therm(subdev); 198 + struct nouveau_therm_priv *priv = (void *)therm; 199 + struct nvbios_therm_sensor *sensor = &priv->bios_sensor; 200 + unsigned long flags; 201 + uint32_t intr; 202 + 203 + spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); 204 + 205 + intr = nv_rd32(therm, 0x20100); 206 + 207 + /* THRS_4: downclock */ 208 + if (intr & 0x002) { 209 + nv50_therm_threshold_hyst_emulation(therm, 0x20414, 24, 210 + &sensor->thrs_down_clock, 211 + NOUVEAU_THERM_THRS_DOWNCLOCK); 212 + intr &= ~0x002; 213 + } 214 + 215 + /* shutdown */ 216 + if (intr & 0x004) { 217 + nv50_therm_threshold_hyst_emulation(therm, 0x20480, 20, 218 + &sensor->thrs_shutdown, 219 + NOUVEAU_THERM_THRS_SHUTDOWN); 220 + intr &= ~0x004; 221 + } 222 + 223 + /* THRS_1 : fan boost */ 224 + if (intr & 0x008) { 225 + nv50_therm_threshold_hyst_emulation(therm, 0x204c4, 21, 226 + &sensor->thrs_fan_boost, 227 + NOUVEAU_THERM_THRS_FANBOOST); 228 + intr &= ~0x008; 229 + } 230 + 231 + /* THRS_2 : critical */ 232 + if (intr & 0x010) { 233 + nv50_therm_threshold_hyst_emulation(therm, 0x204c0, 22, 234 + &sensor->thrs_critical, 235 + NOUVEAU_THERM_THRS_CRITICAL); 236 + intr &= ~0x010; 237 + } 238 + 239 + if (intr) 240 + nv_error(therm, "unhandled intr 0x%08x\n", intr); 241 + 242 + /* ACK everything */ 243 + nv_wr32(therm, 0x20100, 0xffffffff); 244 + nv_wr32(therm, 0x1100, 0x10000); /* PBUS */ 245 + 246 + spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); 247 + } 248 + 127 249 static int 128 250 nv50_therm_ctor(struct nouveau_object *parent, 129 - struct nouveau_object *engine, 130 - struct nouveau_oclass *oclass, void *data, u32 size, 131 - struct nouveau_object **pobject) 251 + struct nouveau_object *engine, 252 + struct nouveau_oclass *oclass, void *data, u32 size, 253 + struct nouveau_object **pobject) 132 254 { 133 - struct nouveau_therm_priv *priv; 134 - struct nouveau_therm *therm; 255 + struct nv50_therm_priv *priv; 135 256 int ret; 136 257 137 258 ret = nouveau_therm_create(parent, engine, oclass, &priv); 138 259 *pobject = nv_object(priv); 139 - therm = (void *) priv; 140 260 if (ret) 141 261 return ret; 142 262 143 - nouveau_therm_ic_ctor(therm); 144 - nouveau_therm_sensor_ctor(therm); 145 - nouveau_therm_fan_ctor(therm); 263 + priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; 264 + priv->base.base.pwm_get = nv50_fan_pwm_get; 265 + priv->base.base.pwm_set = nv50_fan_pwm_set; 266 + priv->base.base.pwm_clock = nv50_fan_pwm_clock; 267 + priv->base.base.temp_get = nv50_temp_get; 268 + priv->base.sensor.program_alarms = nv50_therm_program_alarms; 269 + nv_subdev(priv)->intr = nv50_therm_intr; 146 270 147 - priv->fan.pwm_get = nv50_fan_pwm_get; 148 - priv->fan.pwm_set = nv50_fan_pwm_set; 149 - priv->fan.pwm_clock = nv50_fan_pwm_clock; 271 + /* init the thresholds */ 272 + nouveau_therm_sensor_set_threshold_state(&priv->base.base, 273 + NOUVEAU_THERM_THRS_SHUTDOWN, 274 + NOUVEAU_THERM_THRS_LOWER); 275 + nouveau_therm_sensor_set_threshold_state(&priv->base.base, 276 + NOUVEAU_THERM_THRS_FANBOOST, 277 + NOUVEAU_THERM_THRS_LOWER); 278 + nouveau_therm_sensor_set_threshold_state(&priv->base.base, 279 + NOUVEAU_THERM_THRS_CRITICAL, 280 + NOUVEAU_THERM_THRS_LOWER); 281 + nouveau_therm_sensor_set_threshold_state(&priv->base.base, 282 + NOUVEAU_THERM_THRS_DOWNCLOCK, 283 + NOUVEAU_THERM_THRS_LOWER); 150 284 151 - therm->temp_get = nv50_temp_get; 152 - therm->fan_get = nouveau_therm_fan_user_get; 153 - therm->fan_set = nouveau_therm_fan_user_set; 154 - therm->fan_sense = nouveau_therm_fan_sense; 155 - therm->attr_get = nouveau_therm_attr_get; 156 - therm->attr_set = nouveau_therm_attr_set; 157 - 158 - return 0; 285 + return nouveau_therm_preinit(&priv->base.base); 159 286 } 160 287 161 288 struct nouveau_oclass ··· 304 151 .ofuncs = &(struct nouveau_ofuncs) { 305 152 .ctor = nv50_therm_ctor, 306 153 .dtor = _nouveau_therm_dtor, 307 - .init = nouveau_therm_init, 308 - .fini = nouveau_therm_fini, 154 + .init = _nouveau_therm_init, 155 + .fini = _nouveau_therm_fini, 309 156 }, 310 157 };
+99
drivers/gpu/drm/nouveau/core/subdev/therm/nva3.c
··· 1 + /* 2 + * Copyright 2012 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 <subdev/gpio.h> 26 + 27 + #include "priv.h" 28 + 29 + struct nva3_therm_priv { 30 + struct nouveau_therm_priv base; 31 + }; 32 + 33 + int 34 + nva3_therm_fan_sense(struct nouveau_therm *therm) 35 + { 36 + u32 tach = nv_rd32(therm, 0x00e728) & 0x0000ffff; 37 + u32 ctrl = nv_rd32(therm, 0x00e720); 38 + if (ctrl & 0x00000001) 39 + return tach * 60; 40 + return -ENODEV; 41 + } 42 + 43 + static int 44 + nva3_therm_init(struct nouveau_object *object) 45 + { 46 + struct nva3_therm_priv *priv = (void *)object; 47 + struct dcb_gpio_func *tach = &priv->base.fan->tach; 48 + int ret; 49 + 50 + ret = nouveau_therm_init(&priv->base.base); 51 + if (ret) 52 + return ret; 53 + 54 + /* enable fan tach, count revolutions per-second */ 55 + nv_mask(priv, 0x00e720, 0x00000003, 0x00000002); 56 + if (tach->func != DCB_GPIO_UNUSED) { 57 + nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000); 58 + nv_mask(priv, 0x00e720, 0x001f0000, tach->line << 16); 59 + nv_mask(priv, 0x00e720, 0x00000001, 0x00000001); 60 + } 61 + nv_mask(priv, 0x00e720, 0x00000002, 0x00000000); 62 + 63 + return 0; 64 + } 65 + 66 + static int 67 + nva3_therm_ctor(struct nouveau_object *parent, 68 + struct nouveau_object *engine, 69 + struct nouveau_oclass *oclass, void *data, u32 size, 70 + struct nouveau_object **pobject) 71 + { 72 + struct nva3_therm_priv *priv; 73 + int ret; 74 + 75 + ret = nouveau_therm_create(parent, engine, oclass, &priv); 76 + *pobject = nv_object(priv); 77 + if (ret) 78 + return ret; 79 + 80 + priv->base.base.pwm_ctrl = nv50_fan_pwm_ctrl; 81 + priv->base.base.pwm_get = nv50_fan_pwm_get; 82 + priv->base.base.pwm_set = nv50_fan_pwm_set; 83 + priv->base.base.pwm_clock = nv50_fan_pwm_clock; 84 + priv->base.base.temp_get = nv50_temp_get; 85 + priv->base.base.fan_sense = nva3_therm_fan_sense; 86 + priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; 87 + return nouveau_therm_preinit(&priv->base.base); 88 + } 89 + 90 + struct nouveau_oclass 91 + nva3_therm_oclass = { 92 + .handle = NV_SUBDEV(THERM, 0xa3), 93 + .ofuncs = &(struct nouveau_ofuncs) { 94 + .ctor = nva3_therm_ctor, 95 + .dtor = _nouveau_therm_dtor, 96 + .init = nva3_therm_init, 97 + .fini = _nouveau_therm_fini, 98 + }, 99 + };
+153
drivers/gpu/drm/nouveau/core/subdev/therm/nvd0.c
··· 1 + /* 2 + * Copyright 2012 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 "priv.h" 26 + 27 + struct nvd0_therm_priv { 28 + struct nouveau_therm_priv base; 29 + }; 30 + 31 + static int 32 + pwm_info(struct nouveau_therm *therm, int line) 33 + { 34 + u32 gpio = nv_rd32(therm, 0x00d610 + (line * 0x04)); 35 + switch (gpio & 0x000000c0) { 36 + case 0x00000000: /* normal mode, possibly pwm forced off by us */ 37 + case 0x00000040: /* nvio special */ 38 + switch (gpio & 0x0000001f) { 39 + case 0x19: return 1; 40 + case 0x1c: return 0; 41 + default: 42 + break; 43 + } 44 + default: 45 + break; 46 + } 47 + 48 + nv_error(therm, "GPIO %d unknown PWM: 0x%08x\n", line, gpio); 49 + return -ENODEV; 50 + } 51 + 52 + static int 53 + nvd0_fan_pwm_ctrl(struct nouveau_therm *therm, int line, bool enable) 54 + { 55 + u32 data = enable ? 0x00000040 : 0x00000000; 56 + int indx = pwm_info(therm, line); 57 + if (indx < 0) 58 + return indx; 59 + 60 + nv_mask(therm, 0x00d610 + (line * 0x04), 0x000000c0, data); 61 + return 0; 62 + } 63 + 64 + static int 65 + nvd0_fan_pwm_get(struct nouveau_therm *therm, int line, u32 *divs, u32 *duty) 66 + { 67 + int indx = pwm_info(therm, line); 68 + if (indx < 0) 69 + return indx; 70 + 71 + if (nv_rd32(therm, 0x00d610 + (line * 0x04)) & 0x00000040) { 72 + *divs = nv_rd32(therm, 0x00e114 + (indx * 8)); 73 + *duty = nv_rd32(therm, 0x00e118 + (indx * 8)); 74 + return 0; 75 + } 76 + 77 + return -EINVAL; 78 + } 79 + 80 + static int 81 + nvd0_fan_pwm_set(struct nouveau_therm *therm, int line, u32 divs, u32 duty) 82 + { 83 + int indx = pwm_info(therm, line); 84 + if (indx < 0) 85 + return indx; 86 + 87 + nv_wr32(therm, 0x00e114 + (indx * 8), divs); 88 + nv_wr32(therm, 0x00e118 + (indx * 8), duty | 0x80000000); 89 + return 0; 90 + } 91 + 92 + static int 93 + nvd0_fan_pwm_clock(struct nouveau_therm *therm) 94 + { 95 + return (nv_device(therm)->crystal * 1000) / 20; 96 + } 97 + 98 + static int 99 + nvd0_therm_init(struct nouveau_object *object) 100 + { 101 + struct nvd0_therm_priv *priv = (void *)object; 102 + int ret; 103 + 104 + ret = nouveau_therm_init(&priv->base.base); 105 + if (ret) 106 + return ret; 107 + 108 + /* enable fan tach, count revolutions per-second */ 109 + nv_mask(priv, 0x00e720, 0x00000003, 0x00000002); 110 + if (priv->base.fan->tach.func != DCB_GPIO_UNUSED) { 111 + nv_mask(priv, 0x00d79c, 0x000000ff, priv->base.fan->tach.line); 112 + nv_wr32(priv, 0x00e724, nv_device(priv)->crystal * 1000); 113 + nv_mask(priv, 0x00e720, 0x00000001, 0x00000001); 114 + } 115 + nv_mask(priv, 0x00e720, 0x00000002, 0x00000000); 116 + 117 + return 0; 118 + } 119 + 120 + static int 121 + nvd0_therm_ctor(struct nouveau_object *parent, 122 + struct nouveau_object *engine, 123 + struct nouveau_oclass *oclass, void *data, u32 size, 124 + struct nouveau_object **pobject) 125 + { 126 + struct nvd0_therm_priv *priv; 127 + int ret; 128 + 129 + ret = nouveau_therm_create(parent, engine, oclass, &priv); 130 + *pobject = nv_object(priv); 131 + if (ret) 132 + return ret; 133 + 134 + priv->base.base.pwm_ctrl = nvd0_fan_pwm_ctrl; 135 + priv->base.base.pwm_get = nvd0_fan_pwm_get; 136 + priv->base.base.pwm_set = nvd0_fan_pwm_set; 137 + priv->base.base.pwm_clock = nvd0_fan_pwm_clock; 138 + priv->base.base.temp_get = nv50_temp_get; 139 + priv->base.base.fan_sense = nva3_therm_fan_sense; 140 + priv->base.sensor.program_alarms = nouveau_therm_program_alarms_polling; 141 + return nouveau_therm_preinit(&priv->base.base); 142 + } 143 + 144 + struct nouveau_oclass 145 + nvd0_therm_oclass = { 146 + .handle = NV_SUBDEV(THERM, 0xd0), 147 + .ofuncs = &(struct nouveau_ofuncs) { 148 + .ctor = nvd0_therm_ctor, 149 + .dtor = _nouveau_therm_dtor, 150 + .init = nvd0_therm_init, 151 + .fini = _nouveau_therm_fini, 152 + }, 153 + };
+90 -15
drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
··· 1 + #ifndef __NVTHERM_PRIV_H__ 2 + #define __NVTHERM_PRIV_H__ 3 + 1 4 /* 2 5 * Copyright 2012 The Nouveau community 3 6 * ··· 28 25 #include <subdev/therm.h> 29 26 30 27 #include <subdev/bios/extdev.h> 28 + #include <subdev/bios/gpio.h> 31 29 #include <subdev/bios/perf.h> 32 30 #include <subdev/bios/therm.h> 31 + #include <subdev/timer.h> 32 + 33 + struct nouveau_fan { 34 + struct nouveau_therm *parent; 35 + const char *type; 36 + 37 + struct nvbios_therm_fan bios; 38 + struct nvbios_perf_fan perf; 39 + 40 + struct nouveau_alarm alarm; 41 + spinlock_t lock; 42 + int percent; 43 + 44 + int (*get)(struct nouveau_therm *therm); 45 + int (*set)(struct nouveau_therm *therm, int percent); 46 + 47 + struct dcb_gpio_func tach; 48 + }; 49 + 50 + enum nouveau_therm_thrs_direction { 51 + NOUVEAU_THERM_THRS_FALLING = 0, 52 + NOUVEAU_THERM_THRS_RISING = 1 53 + }; 54 + 55 + enum nouveau_therm_thrs_state { 56 + NOUVEAU_THERM_THRS_LOWER = 0, 57 + NOUVEAU_THERM_THRS_HIGHER = 1 58 + }; 59 + 60 + enum nouveau_therm_thrs { 61 + NOUVEAU_THERM_THRS_FANBOOST = 0, 62 + NOUVEAU_THERM_THRS_DOWNCLOCK = 1, 63 + NOUVEAU_THERM_THRS_CRITICAL = 2, 64 + NOUVEAU_THERM_THRS_SHUTDOWN = 3, 65 + NOUVEAU_THERM_THRS_NR 66 + }; 33 67 34 68 struct nouveau_therm_priv { 35 69 struct nouveau_therm base; 36 70 71 + /* automatic thermal management */ 72 + struct nouveau_alarm alarm; 73 + spinlock_t lock; 74 + struct nouveau_therm_trip_point *last_trip; 75 + int mode; 76 + int suspend; 77 + 37 78 /* bios */ 38 79 struct nvbios_therm_sensor bios_sensor; 39 - struct nvbios_therm_fan bios_fan; 40 - struct nvbios_perf_fan bios_perf_fan; 41 80 42 81 /* fan priv */ 43 - struct { 44 - enum nouveau_therm_fan_mode mode; 45 - int percent; 82 + struct nouveau_fan *fan; 46 83 47 - int (*pwm_get)(struct nouveau_therm *, int line, u32*, u32*); 48 - int (*pwm_set)(struct nouveau_therm *, int line, u32, u32); 49 - int (*pwm_clock)(struct nouveau_therm *); 50 - } fan; 84 + /* alarms priv */ 85 + struct { 86 + spinlock_t alarm_program_lock; 87 + struct nouveau_alarm therm_poll_alarm; 88 + enum nouveau_therm_thrs_state alarm_state[NOUVEAU_THERM_THRS_NR]; 89 + void (*program_alarms)(struct nouveau_therm *); 90 + } sensor; 91 + 92 + /* what should be done if the card overheats */ 93 + struct { 94 + void (*downclock)(struct nouveau_therm *, bool active); 95 + void (*pause)(struct nouveau_therm *, bool active); 96 + } emergency; 51 97 52 98 /* ic */ 53 99 struct i2c_client *ic; 54 100 }; 55 101 56 - int nouveau_therm_init(struct nouveau_object *object); 57 - int nouveau_therm_fini(struct nouveau_object *object, bool suspend); 102 + int nouveau_therm_mode(struct nouveau_therm *therm, int mode); 58 103 int nouveau_therm_attr_get(struct nouveau_therm *therm, 59 104 enum nouveau_therm_attr_type type); 60 105 int nouveau_therm_attr_set(struct nouveau_therm *therm, ··· 114 63 115 64 int nouveau_therm_fan_ctor(struct nouveau_therm *therm); 116 65 int nouveau_therm_fan_get(struct nouveau_therm *therm); 117 - int nouveau_therm_fan_set(struct nouveau_therm *therm, int percent); 66 + int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); 118 67 int nouveau_therm_fan_user_get(struct nouveau_therm *therm); 119 68 int nouveau_therm_fan_user_set(struct nouveau_therm *therm, int percent); 120 - int nouveau_therm_fan_set_mode(struct nouveau_therm *therm, 121 - enum nouveau_therm_fan_mode mode); 122 - 123 69 124 70 int nouveau_therm_fan_sense(struct nouveau_therm *therm); 71 + 72 + int nouveau_therm_preinit(struct nouveau_therm *); 73 + 74 + void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, 75 + enum nouveau_therm_thrs thrs, 76 + enum nouveau_therm_thrs_state st); 77 + enum nouveau_therm_thrs_state 78 + nouveau_therm_sensor_get_threshold_state(struct nouveau_therm *therm, 79 + enum nouveau_therm_thrs thrs); 80 + void nouveau_therm_sensor_event(struct nouveau_therm *therm, 81 + enum nouveau_therm_thrs thrs, 82 + enum nouveau_therm_thrs_direction dir); 83 + void nouveau_therm_program_alarms_polling(struct nouveau_therm *therm); 84 + 85 + int nv50_fan_pwm_ctrl(struct nouveau_therm *, int, bool); 86 + int nv50_fan_pwm_get(struct nouveau_therm *, int, u32 *, u32 *); 87 + int nv50_fan_pwm_set(struct nouveau_therm *, int, u32, u32); 88 + int nv50_fan_pwm_clock(struct nouveau_therm *); 89 + int nv50_temp_get(struct nouveau_therm *therm); 90 + 91 + int nva3_therm_fan_sense(struct nouveau_therm *); 92 + 93 + int nouveau_fanpwm_create(struct nouveau_therm *, struct dcb_gpio_func *); 94 + int nouveau_fantog_create(struct nouveau_therm *, struct dcb_gpio_func *); 95 + int nouveau_fannil_create(struct nouveau_therm *); 96 + 97 + #endif
+162
drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
··· 58 58 nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) 59 59 { 60 60 struct nouveau_therm_priv *priv = (void *)therm; 61 + struct nvbios_therm_sensor *s = &priv->bios_sensor; 61 62 62 63 if (!priv->bios_sensor.slope_div) 63 64 priv->bios_sensor.slope_div = 1; 64 65 if (!priv->bios_sensor.offset_den) 65 66 priv->bios_sensor.offset_den = 1; 67 + 68 + /* enforce a minimum hysteresis on thresholds */ 69 + s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); 70 + s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); 71 + s->thrs_critical.hysteresis = max_t(u8, s->thrs_critical.hysteresis, 2); 72 + s->thrs_shutdown.hysteresis = max_t(u8, s->thrs_shutdown.hysteresis, 2); 73 + } 74 + 75 + /* must be called with alarm_program_lock taken ! */ 76 + void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, 77 + enum nouveau_therm_thrs thrs, 78 + enum nouveau_therm_thrs_state st) 79 + { 80 + struct nouveau_therm_priv *priv = (void *)therm; 81 + priv->sensor.alarm_state[thrs] = st; 82 + } 83 + 84 + /* must be called with alarm_program_lock taken ! */ 85 + enum nouveau_therm_thrs_state 86 + nouveau_therm_sensor_get_threshold_state(struct nouveau_therm *therm, 87 + enum nouveau_therm_thrs thrs) 88 + { 89 + struct nouveau_therm_priv *priv = (void *)therm; 90 + return priv->sensor.alarm_state[thrs]; 91 + } 92 + 93 + static void 94 + nv_poweroff_work(struct work_struct *work) 95 + { 96 + orderly_poweroff(true); 97 + kfree(work); 98 + } 99 + 100 + void nouveau_therm_sensor_event(struct nouveau_therm *therm, 101 + enum nouveau_therm_thrs thrs, 102 + enum nouveau_therm_thrs_direction dir) 103 + { 104 + struct nouveau_therm_priv *priv = (void *)therm; 105 + bool active; 106 + const char *thresolds[] = { 107 + "fanboost", "downclock", "critical", "shutdown" 108 + }; 109 + uint8_t temperature = therm->temp_get(therm); 110 + 111 + if (thrs < 0 || thrs > 3) 112 + return; 113 + 114 + if (dir == NOUVEAU_THERM_THRS_FALLING) 115 + nv_info(therm, "temperature (%u C) went below the '%s' threshold\n", 116 + temperature, thresolds[thrs]); 117 + else 118 + nv_info(therm, "temperature (%u C) hit the '%s' threshold\n", 119 + temperature, thresolds[thrs]); 120 + 121 + active = (dir == NOUVEAU_THERM_THRS_RISING); 122 + switch (thrs) { 123 + case NOUVEAU_THERM_THRS_FANBOOST: 124 + if (active) { 125 + nouveau_therm_fan_set(therm, true, 100); 126 + nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO); 127 + } 128 + break; 129 + case NOUVEAU_THERM_THRS_DOWNCLOCK: 130 + if (priv->emergency.downclock) 131 + priv->emergency.downclock(therm, active); 132 + break; 133 + case NOUVEAU_THERM_THRS_CRITICAL: 134 + if (priv->emergency.pause) 135 + priv->emergency.pause(therm, active); 136 + break; 137 + case NOUVEAU_THERM_THRS_SHUTDOWN: 138 + if (active) { 139 + struct work_struct *work; 140 + 141 + work = kmalloc(sizeof(*work), GFP_ATOMIC); 142 + if (work) { 143 + INIT_WORK(work, nv_poweroff_work); 144 + schedule_work(work); 145 + } 146 + } 147 + break; 148 + case NOUVEAU_THERM_THRS_NR: 149 + break; 150 + } 151 + 152 + } 153 + 154 + /* must be called with alarm_program_lock taken ! */ 155 + static void 156 + nouveau_therm_threshold_hyst_polling(struct nouveau_therm *therm, 157 + const struct nvbios_therm_threshold *thrs, 158 + enum nouveau_therm_thrs thrs_name) 159 + { 160 + enum nouveau_therm_thrs_direction direction; 161 + enum nouveau_therm_thrs_state prev_state, new_state; 162 + int temp = therm->temp_get(therm); 163 + 164 + prev_state = nouveau_therm_sensor_get_threshold_state(therm, thrs_name); 165 + 166 + if (temp >= thrs->temp && prev_state == NOUVEAU_THERM_THRS_LOWER) { 167 + direction = NOUVEAU_THERM_THRS_RISING; 168 + new_state = NOUVEAU_THERM_THRS_HIGHER; 169 + } else if (temp <= thrs->temp - thrs->hysteresis && 170 + prev_state == NOUVEAU_THERM_THRS_HIGHER) { 171 + direction = NOUVEAU_THERM_THRS_FALLING; 172 + new_state = NOUVEAU_THERM_THRS_LOWER; 173 + } else 174 + return; /* nothing to do */ 175 + 176 + nouveau_therm_sensor_set_threshold_state(therm, thrs_name, new_state); 177 + nouveau_therm_sensor_event(therm, thrs_name, direction); 178 + } 179 + 180 + static void 181 + alarm_timer_callback(struct nouveau_alarm *alarm) 182 + { 183 + struct nouveau_therm_priv *priv = 184 + container_of(alarm, struct nouveau_therm_priv, sensor.therm_poll_alarm); 185 + struct nvbios_therm_sensor *sensor = &priv->bios_sensor; 186 + struct nouveau_timer *ptimer = nouveau_timer(priv); 187 + struct nouveau_therm *therm = &priv->base; 188 + unsigned long flags; 189 + 190 + spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); 191 + 192 + nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, 193 + NOUVEAU_THERM_THRS_FANBOOST); 194 + 195 + nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_down_clock, 196 + NOUVEAU_THERM_THRS_DOWNCLOCK); 197 + 198 + nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_critical, 199 + NOUVEAU_THERM_THRS_CRITICAL); 200 + 201 + nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_shutdown, 202 + NOUVEAU_THERM_THRS_SHUTDOWN); 203 + 204 + /* schedule the next poll in one second */ 205 + if (list_empty(&alarm->head)) 206 + ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); 207 + 208 + spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); 209 + } 210 + 211 + void 212 + nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) 213 + { 214 + struct nouveau_therm_priv *priv = (void *)therm; 215 + struct nvbios_therm_sensor *sensor = &priv->bios_sensor; 216 + 217 + nv_info(therm, 218 + "programmed thresholds [ %d(%d), %d(%d), %d(%d), %d(%d) ]\n", 219 + sensor->thrs_fan_boost.temp, sensor->thrs_fan_boost.hysteresis, 220 + sensor->thrs_down_clock.temp, 221 + sensor->thrs_down_clock.hysteresis, 222 + sensor->thrs_critical.temp, sensor->thrs_critical.hysteresis, 223 + sensor->thrs_shutdown.temp, sensor->thrs_shutdown.hysteresis); 224 + 225 + alarm_timer_callback(&priv->sensor.therm_poll_alarm); 66 226 } 67 227 68 228 int ··· 230 70 { 231 71 struct nouveau_therm_priv *priv = (void *)therm; 232 72 struct nouveau_bios *bios = nouveau_bios(therm); 73 + 74 + nouveau_alarm_init(&priv->sensor.therm_poll_alarm, alarm_timer_callback); 233 75 234 76 nouveau_therm_temp_set_defaults(therm); 235 77 if (nvbios_therm_sensor_parse(bios, NVBIOS_THERM_DOMAIN_CORE,
+1 -1
drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c
··· 79 79 80 80 /* execute any pending alarm handlers */ 81 81 list_for_each_entry_safe(alarm, atemp, &exec, head) { 82 - list_del(&alarm->head); 82 + list_del_init(&alarm->head); 83 83 alarm->func(alarm); 84 84 } 85 85 }
+1 -1
drivers/gpu/drm/nouveau/nouveau_acpi.h
··· 3 3 4 4 #define ROM_BIOS_PAGE 4096 5 5 6 - #if defined(CONFIG_ACPI) 6 + #if defined(CONFIG_ACPI) && defined(CONFIG_X86) 7 7 bool nouveau_is_optimus(void); 8 8 bool nouveau_is_v1_dsm(void); 9 9 void nouveau_register_dsm_handler(void);
+2
drivers/gpu/drm/nouveau/nouveau_backlight.c
··· 84 84 props.max_brightness = 31; 85 85 bd = backlight_device_register("nv_backlight", &connector->kdev, drm, 86 86 &nv40_bl_ops, &props); 87 + if (IS_ERR(bd)) 88 + return PTR_ERR(bd); 87 89 drm->backlight = bd; 88 90 bd->props.brightness = nv40_get_intensity(bd); 89 91 backlight_update_status(bd);
+27 -97
drivers/gpu/drm/nouveau/nouveau_bios.c
··· 678 678 return 0; 679 679 } 680 680 681 - static void parse_bios_version(struct drm_device *dev, struct nvbios *bios, uint16_t offset) 682 - { 683 - /* 684 - * offset + 0 (8 bits): Micro version 685 - * offset + 1 (8 bits): Minor version 686 - * offset + 2 (8 bits): Chip version 687 - * offset + 3 (8 bits): Major version 688 - */ 689 - struct nouveau_drm *drm = nouveau_drm(dev); 690 - 691 - bios->major_version = bios->data[offset + 3]; 692 - bios->chip_version = bios->data[offset + 2]; 693 - NV_INFO(drm, "Bios version %02x.%02x.%02x.%02x\n", 694 - bios->data[offset + 3], bios->data[offset + 2], 695 - bios->data[offset + 1], bios->data[offset]); 696 - } 697 - 698 681 static void parse_script_table_pointers(struct nvbios *bios, uint16_t offset) 699 682 { 700 683 /* ··· 693 710 */ 694 711 695 712 bios->init_script_tbls_ptr = ROM16(bios->data[offset]); 696 - bios->macro_index_tbl_ptr = ROM16(bios->data[offset + 2]); 697 - bios->macro_tbl_ptr = ROM16(bios->data[offset + 4]); 698 - bios->condition_tbl_ptr = ROM16(bios->data[offset + 6]); 699 - bios->io_condition_tbl_ptr = ROM16(bios->data[offset + 8]); 700 - bios->io_flag_condition_tbl_ptr = ROM16(bios->data[offset + 10]); 701 - bios->init_function_tbl_ptr = ROM16(bios->data[offset + 12]); 702 713 } 703 714 704 715 static int parse_bit_A_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) ··· 742 765 return 0; 743 766 } 744 767 745 - static int parse_bit_C_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) 746 - { 747 - /* 748 - * offset + 8 (16 bits): PLL limits table pointer 749 - * 750 - * There's more in here, but that's unknown. 751 - */ 752 - struct nouveau_drm *drm = nouveau_drm(dev); 753 - 754 - if (bitentry->length < 10) { 755 - NV_ERROR(drm, "Do not understand BIT C table\n"); 756 - return -EINVAL; 757 - } 758 - 759 - bios->pll_limit_tbl_ptr = ROM16(bios->data[bitentry->offset + 8]); 760 - 761 - return 0; 762 - } 763 - 764 768 static int parse_bit_display_tbl_entry(struct drm_device *dev, struct nvbios *bios, struct bit_entry *bitentry) 765 769 { 766 770 /* ··· 779 821 } 780 822 781 823 parse_script_table_pointers(bios, bitentry->offset); 782 - 783 - if (bitentry->length >= 16) 784 - bios->some_script_ptr = ROM16(bios->data[bitentry->offset + 14]); 785 - if (bitentry->length >= 18) 786 - bios->init96_tbl_ptr = ROM16(bios->data[bitentry->offset + 16]); 787 - 788 824 return 0; 789 825 } 790 826 ··· 803 851 NV_ERROR(drm, "BIT i table too short for needed information\n"); 804 852 return -EINVAL; 805 853 } 806 - 807 - parse_bios_version(dev, bios, bitentry->offset); 808 854 809 855 /* 810 856 * bit 4 seems to indicate a mobile bios (doesn't suffer from BMP's ··· 1028 1078 return ret; 1029 1079 if (bios->major_version >= 0x60) /* g80+ */ 1030 1080 parse_bit_table(bios, bitoffset, &BIT_TABLE('A', A)); 1031 - ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('C', C)); 1032 - if (ret) 1033 - return ret; 1034 1081 parse_bit_table(bios, bitoffset, &BIT_TABLE('D', display)); 1035 1082 ret = parse_bit_table(bios, bitoffset, &BIT_TABLE('I', init)); 1036 1083 if (ret) ··· 1175 1228 */ 1176 1229 bios->feature_byte = bmp[9]; 1177 1230 1178 - parse_bios_version(dev, bios, offset + 10); 1179 - 1180 1231 if (bmp_version_major < 5 || bmp_version_minor < 0x10) 1181 1232 bios->old_style_init = true; 1182 1233 legacy_scripts_offset = 18; ··· 1221 1276 bios->fp.lvdsmanufacturerpointer = ROM16(bmp[117]); 1222 1277 bios->fp.fpxlatemanufacturertableptr = ROM16(bmp[119]); 1223 1278 } 1279 + #if 0 1224 1280 if (bmplength > 143) 1225 1281 bios->pll_limit_tbl_ptr = ROM16(bmp[142]); 1282 + #endif 1226 1283 1227 1284 if (bmplength > 157) 1228 1285 bios->fp.duallink_transition_clk = ROM16(bmp[156]) * 10; ··· 1469 1522 } 1470 1523 case DCB_OUTPUT_DP: 1471 1524 entry->dpconf.sor.link = (conf & 0x00000030) >> 4; 1525 + entry->extdev = (conf & 0x0000ff00) >> 8; 1472 1526 switch ((conf & 0x00e00000) >> 21) { 1473 1527 case 0: 1474 1528 entry->dpconf.link_bw = 162000; ··· 1491 1543 } 1492 1544 break; 1493 1545 case DCB_OUTPUT_TMDS: 1494 - if (dcb->version >= 0x40) 1546 + if (dcb->version >= 0x40) { 1495 1547 entry->tmdsconf.sor.link = (conf & 0x00000030) >> 4; 1548 + entry->extdev = (conf & 0x0000ff00) >> 8; 1549 + } 1496 1550 else if (dcb->version >= 0x30) 1497 1551 entry->tmdsconf.slave_addr = (conf & 0x00000700) >> 8; 1498 1552 else if (dcb->version >= 0x22) ··· 1887 1937 if (conn[0] != 0xff) { 1888 1938 NV_INFO(drm, "DCB conn %02d: ", idx); 1889 1939 if (olddcb_conntab(dev)[3] < 4) 1890 - printk("%04x\n", ROM16(conn[0])); 1940 + pr_cont("%04x\n", ROM16(conn[0])); 1891 1941 else 1892 - printk("%08x\n", ROM32(conn[0])); 1942 + pr_cont("%08x\n", ROM32(conn[0])); 1893 1943 } 1894 1944 } 1895 1945 dcb_fake_connectors(bios); ··· 2002 2052 static bool NVInitVBIOS(struct drm_device *dev) 2003 2053 { 2004 2054 struct nouveau_drm *drm = nouveau_drm(dev); 2005 - struct nvbios *bios = &drm->vbios; 2055 + struct nouveau_bios *bios = nouveau_bios(drm->device); 2056 + struct nvbios *legacy = &drm->vbios; 2006 2057 2007 - memset(bios, 0, sizeof(struct nvbios)); 2008 - spin_lock_init(&bios->lock); 2009 - bios->dev = dev; 2058 + memset(legacy, 0, sizeof(struct nvbios)); 2059 + spin_lock_init(&legacy->lock); 2060 + legacy->dev = dev; 2010 2061 2011 - bios->data = nouveau_bios(drm->device)->data; 2012 - bios->length = nouveau_bios(drm->device)->size; 2013 - return true; 2014 - } 2015 - 2016 - static int nouveau_parse_vbios_struct(struct drm_device *dev) 2017 - { 2018 - struct nouveau_drm *drm = nouveau_drm(dev); 2019 - struct nvbios *bios = &drm->vbios; 2020 - const uint8_t bit_signature[] = { 0xff, 0xb8, 'B', 'I', 'T' }; 2021 - const uint8_t bmp_signature[] = { 0xff, 0x7f, 'N', 'V', 0x0 }; 2022 - int offset; 2023 - 2024 - offset = findstr(bios->data, bios->length, 2025 - bit_signature, sizeof(bit_signature)); 2026 - if (offset) { 2027 - NV_INFO(drm, "BIT BIOS found\n"); 2028 - bios->type = NVBIOS_BIT; 2029 - bios->offset = offset; 2030 - return parse_bit_structure(bios, offset + 6); 2062 + legacy->data = bios->data; 2063 + legacy->length = bios->size; 2064 + legacy->major_version = bios->version.major; 2065 + legacy->chip_version = bios->version.chip; 2066 + if (bios->bit_offset) { 2067 + legacy->type = NVBIOS_BIT; 2068 + legacy->offset = bios->bit_offset; 2069 + return !parse_bit_structure(legacy, legacy->offset + 6); 2070 + } else 2071 + if (bios->bmp_offset) { 2072 + legacy->type = NVBIOS_BMP; 2073 + legacy->offset = bios->bmp_offset; 2074 + return !parse_bmp_structure(dev, legacy, legacy->offset); 2031 2075 } 2032 2076 2033 - offset = findstr(bios->data, bios->length, 2034 - bmp_signature, sizeof(bmp_signature)); 2035 - if (offset) { 2036 - NV_INFO(drm, "BMP BIOS found\n"); 2037 - bios->type = NVBIOS_BMP; 2038 - bios->offset = offset; 2039 - return parse_bmp_structure(dev, bios, offset); 2040 - } 2041 - 2042 - NV_ERROR(drm, "No known BIOS signature found\n"); 2043 - return -ENODEV; 2077 + return false; 2044 2078 } 2045 2079 2046 2080 int ··· 2079 2145 2080 2146 if (!NVInitVBIOS(dev)) 2081 2147 return -ENODEV; 2082 - 2083 - ret = nouveau_parse_vbios_struct(dev); 2084 - if (ret) 2085 - return ret; 2086 2148 2087 2149 ret = parse_dcb_table(dev, bios); 2088 2150 if (ret)
-10
drivers/gpu/drm/nouveau/nouveau_bios.h
··· 107 107 bool old_style_init; 108 108 uint16_t init_script_tbls_ptr; 109 109 uint16_t extra_init_script_tbl_ptr; 110 - uint16_t macro_index_tbl_ptr; 111 - uint16_t macro_tbl_ptr; 112 - uint16_t condition_tbl_ptr; 113 - uint16_t io_condition_tbl_ptr; 114 - uint16_t io_flag_condition_tbl_ptr; 115 - uint16_t init_function_tbl_ptr; 116 110 117 - uint16_t pll_limit_tbl_ptr; 118 111 uint16_t ram_restrict_tbl_ptr; 119 112 uint8_t ram_restrict_group_count; 120 - 121 - uint16_t some_script_ptr; /* BIT I + 14 */ 122 - uint16_t init96_tbl_ptr; /* BIT I + 16 */ 123 113 124 114 struct dcb_table dcb; 125 115
+1 -1
drivers/gpu/drm/nouveau/nouveau_bo.c
··· 562 562 struct nouveau_fence *fence = NULL; 563 563 int ret; 564 564 565 - ret = nouveau_fence_new(chan, &fence); 565 + ret = nouveau_fence_new(chan, false, &fence); 566 566 if (ret) 567 567 return ret; 568 568
+3 -2
drivers/gpu/drm/nouveau/nouveau_chan.c
··· 51 51 struct nouveau_fence *fence = NULL; 52 52 int ret; 53 53 54 - ret = nouveau_fence_new(chan, &fence); 54 + ret = nouveau_fence_new(chan, false, &fence); 55 55 if (!ret) { 56 56 ret = nouveau_fence_wait(fence, false, false); 57 57 nouveau_fence_unref(&fence); 58 58 } 59 59 60 60 if (ret) 61 - NV_ERROR(cli, "failed to idle channel 0x%08x\n", chan->handle); 61 + NV_ERROR(cli, "failed to idle channel 0x%08x [%s]\n", 62 + chan->handle, cli->base.name); 62 63 return ret; 63 64 } 64 65
+45 -51
drivers/gpu/drm/nouveau/nouveau_connector.c
··· 55 55 static int nouveau_duallink = 1; 56 56 module_param_named(duallink, nouveau_duallink, int, 0400); 57 57 58 - static void nouveau_connector_hotplug(void *, int); 59 - 60 58 struct nouveau_encoder * 61 59 find_encoder(struct drm_connector *connector, int type) 62 60 { ··· 98 100 nouveau_connector_destroy(struct drm_connector *connector) 99 101 { 100 102 struct nouveau_connector *nv_connector = nouveau_connector(connector); 101 - struct nouveau_gpio *gpio; 102 - struct nouveau_drm *drm; 103 - struct drm_device *dev; 104 - 105 - if (!nv_connector) 106 - return; 107 - 108 - dev = nv_connector->base.dev; 109 - drm = nouveau_drm(dev); 110 - gpio = nouveau_gpio(drm->device); 111 - 112 - if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { 113 - gpio->isr_del(gpio, 0, nv_connector->hpd, 0xff, 114 - nouveau_connector_hotplug, connector); 115 - } 116 - 117 103 kfree(nv_connector->edid); 118 104 drm_sysfs_connector_remove(connector); 119 105 drm_connector_cleanup(connector); ··· 112 130 struct nouveau_connector *nv_connector = nouveau_connector(connector); 113 131 struct nouveau_drm *drm = nouveau_drm(dev); 114 132 struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 115 - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 116 133 struct nouveau_i2c_port *port = NULL; 117 134 int i, panel = -ENODEV; 118 135 ··· 141 160 continue; 142 161 nv_encoder = nouveau_encoder(obj_to_encoder(obj)); 143 162 144 - if (nv_encoder->dcb->i2c_index < 0xf) 145 - port = i2c->find(i2c, nv_encoder->dcb->i2c_index); 163 + port = nv_encoder->i2c; 146 164 if (port && nv_probe_i2c(port, 0x50)) { 147 165 *pnv_encoder = nv_encoder; 148 166 break; ··· 379 399 struct edid *edid = 380 400 (struct edid *)nouveau_bios_embedded_edid(dev); 381 401 if (edid) { 382 - nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); 383 - *(nv_connector->edid) = *edid; 384 - status = connector_status_connected; 402 + nv_connector->edid = 403 + kmemdup(edid, EDID_LENGTH, GFP_KERNEL); 404 + if (nv_connector->edid) 405 + status = connector_status_connected; 385 406 } 386 407 } 387 408 ··· 892 911 .force = nouveau_connector_force 893 912 }; 894 913 914 + static void 915 + nouveau_connector_hotplug_work(struct work_struct *work) 916 + { 917 + struct nouveau_connector *nv_connector = 918 + container_of(work, struct nouveau_connector, hpd_work); 919 + struct drm_connector *connector = &nv_connector->base; 920 + struct drm_device *dev = connector->dev; 921 + struct nouveau_drm *drm = nouveau_drm(dev); 922 + struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 923 + bool plugged = gpio->get(gpio, 0, nv_connector->hpd.func, 0xff); 924 + 925 + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", 926 + drm_get_connector_name(connector)); 927 + 928 + if (plugged) 929 + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); 930 + else 931 + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); 932 + 933 + drm_helper_hpd_irq_event(dev); 934 + } 935 + 936 + static int 937 + nouveau_connector_hotplug(struct nouveau_eventh *event, int index) 938 + { 939 + struct nouveau_connector *nv_connector = 940 + container_of(event, struct nouveau_connector, hpd_func); 941 + schedule_work(&nv_connector->hpd_work); 942 + return NVKM_EVENT_KEEP; 943 + } 944 + 895 945 static int 896 946 drm_conntype_from_dcb(enum dcb_connector_type dcb) 897 947 { ··· 973 961 return ERR_PTR(-ENOMEM); 974 962 975 963 connector = &nv_connector->base; 964 + INIT_WORK(&nv_connector->hpd_work, nouveau_connector_hotplug_work); 976 965 nv_connector->index = index; 977 966 978 967 /* attempt to parse vbios connector type and hotplug gpio */ ··· 988 975 if (olddcb_conntab(dev)[3] >= 4) 989 976 entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; 990 977 991 - nv_connector->hpd = ffs((entry & 0x07033000) >> 12); 992 - nv_connector->hpd = hpd[nv_connector->hpd]; 978 + ret = gpio->find(gpio, 0, hpd[ffs((entry & 0x07033000) >> 12)], 979 + DCB_GPIO_UNUSED, &nv_connector->hpd); 980 + nv_connector->hpd_func.func = nouveau_connector_hotplug; 981 + if (ret) 982 + nv_connector->hpd.func = DCB_GPIO_UNUSED; 993 983 994 984 nv_connector->type = nv_connector->dcb[0]; 995 985 if (drm_conntype_from_dcb(nv_connector->type) == ··· 1015 999 } 1016 1000 } else { 1017 1001 nv_connector->type = DCB_CONNECTOR_NONE; 1018 - nv_connector->hpd = DCB_GPIO_UNUSED; 1002 + nv_connector->hpd.func = DCB_GPIO_UNUSED; 1019 1003 } 1020 1004 1021 1005 /* no vbios data, or an unknown dcb connector type - attempt to ··· 1142 1126 } 1143 1127 1144 1128 connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1145 - if (gpio && nv_connector->hpd != DCB_GPIO_UNUSED) { 1146 - ret = gpio->isr_add(gpio, 0, nv_connector->hpd, 0xff, 1147 - nouveau_connector_hotplug, connector); 1148 - if (ret == 0) 1149 - connector->polled = DRM_CONNECTOR_POLL_HPD; 1150 - } 1129 + if (nv_connector->hpd.func != DCB_GPIO_UNUSED) 1130 + connector->polled = DRM_CONNECTOR_POLL_HPD; 1151 1131 1152 1132 drm_sysfs_connector_add(connector); 1153 1133 return connector; 1154 - } 1155 - 1156 - static void 1157 - nouveau_connector_hotplug(void *data, int plugged) 1158 - { 1159 - struct drm_connector *connector = data; 1160 - struct drm_device *dev = connector->dev; 1161 - struct nouveau_drm *drm = nouveau_drm(dev); 1162 - 1163 - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", 1164 - drm_get_connector_name(connector)); 1165 - 1166 - if (plugged) 1167 - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); 1168 - else 1169 - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); 1170 - 1171 - drm_helper_hpd_irq_event(dev); 1172 1134 }
+9 -1
drivers/gpu/drm/nouveau/nouveau_connector.h
··· 30 30 #include <drm/drm_edid.h> 31 31 #include "nouveau_crtc.h" 32 32 33 + #include <core/event.h> 34 + 35 + #include <subdev/bios.h> 36 + #include <subdev/bios/gpio.h> 37 + 33 38 struct nouveau_i2c_port; 34 39 35 40 enum nouveau_underscan_type { ··· 66 61 enum dcb_connector_type type; 67 62 u8 index; 68 63 u8 *dcb; 69 - u8 hpd; 64 + 65 + struct dcb_gpio_func hpd; 66 + struct work_struct hpd_work; 67 + struct nouveau_eventh hpd_func; 70 68 71 69 int dithering_mode; 72 70 int dithering_depth;
+15 -70
drivers/gpu/drm/nouveau/nouveau_display.c
··· 41 41 #include <subdev/gpio.h> 42 42 #include <engine/disp.h> 43 43 44 + #include <core/class.h> 45 + 44 46 static void 45 47 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) 46 48 { ··· 233 231 /* enable hotplug interrupts */ 234 232 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 235 233 struct nouveau_connector *conn = nouveau_connector(connector); 236 - if (gpio) 237 - gpio->irq(gpio, 0, conn->hpd, 0xff, true); 234 + if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) { 235 + nouveau_event_get(gpio->events, conn->hpd.line, 236 + &conn->hpd_func); 237 + } 238 238 } 239 239 240 240 return ret; ··· 253 249 /* disable hotplug interrupts */ 254 250 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 255 251 struct nouveau_connector *conn = nouveau_connector(connector); 256 - if (gpio) 257 - gpio->irq(gpio, 0, conn->hpd, 0xff, false); 252 + if (gpio && conn->hpd.func != DCB_GPIO_UNUSED) { 253 + nouveau_event_put(gpio->events, conn->hpd.line, 254 + &conn->hpd_func); 255 + } 258 256 } 259 257 260 258 drm_kms_helper_poll_disable(dev); 261 259 disp->fini(dev); 262 260 } 263 261 264 - static void 265 - nouveau_display_vblank_notify(void *data, int crtc) 266 - { 267 - drm_handle_vblank(data, crtc); 268 - } 269 - 270 - static void 271 - nouveau_display_vblank_get(void *data, int crtc) 272 - { 273 - drm_vblank_get(data, crtc); 274 - } 275 - 276 - static void 277 - nouveau_display_vblank_put(void *data, int crtc) 278 - { 279 - drm_vblank_put(data, crtc); 280 - } 281 - 282 262 int 283 263 nouveau_display_create(struct drm_device *dev) 284 264 { 285 265 struct nouveau_drm *drm = nouveau_drm(dev); 286 - struct nouveau_disp *pdisp = nouveau_disp(drm->device); 287 266 struct nouveau_display *disp; 288 267 u32 pclass = dev->pdev->class >> 8; 289 268 int ret, gen; ··· 274 287 disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); 275 288 if (!disp) 276 289 return -ENOMEM; 277 - 278 - pdisp->vblank.data = dev; 279 - pdisp->vblank.notify = nouveau_display_vblank_notify; 280 - pdisp->vblank.get = nouveau_display_vblank_get; 281 - pdisp->vblank.put = nouveau_display_vblank_put; 282 290 283 291 drm_mode_config_init(dev); 284 292 drm_mode_create_scaling_mode_property(dev); ··· 298 316 drm_property_create_range(dev, 0, "underscan vborder", 0, 128); 299 317 300 318 if (gen >= 1) { 319 + /* -90..+90 */ 301 320 disp->vibrant_hue_property = 302 - drm_property_create(dev, DRM_MODE_PROP_RANGE, 303 - "vibrant hue", 2); 304 - disp->vibrant_hue_property->values[0] = 0; 305 - disp->vibrant_hue_property->values[1] = 180; /* -90..+90 */ 321 + drm_property_create_range(dev, 0, "vibrant hue", 0, 180); 306 322 323 + /* -100..+100 */ 307 324 disp->color_vibrance_property = 308 - drm_property_create(dev, DRM_MODE_PROP_RANGE, 309 - "color vibrance", 2); 310 - disp->color_vibrance_property->values[0] = 0; 311 - disp->color_vibrance_property->values[1] = 200; /* -100..+100 */ 325 + drm_property_create_range(dev, 0, "color vibrance", 0, 200); 312 326 } 313 327 314 328 dev->mode_config.funcs = &nouveau_mode_config_funcs; ··· 456 478 } 457 479 } 458 480 459 - int 460 - nouveau_vblank_enable(struct drm_device *dev, int crtc) 461 - { 462 - struct nouveau_device *device = nouveau_dev(dev); 463 - 464 - if (device->card_type >= NV_D0) 465 - nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 1); 466 - else 467 - if (device->card_type >= NV_50) 468 - nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 0, 469 - NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc)); 470 - else 471 - NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 472 - NV_PCRTC_INTR_0_VBLANK); 473 - 474 - return 0; 475 - } 476 - 477 - void 478 - nouveau_vblank_disable(struct drm_device *dev, int crtc) 479 - { 480 - struct nouveau_device *device = nouveau_dev(dev); 481 - 482 - if (device->card_type >= NV_D0) 483 - nv_mask(device, 0x6100c0 + (crtc * 0x800), 1, 0); 484 - else 485 - if (device->card_type >= NV_50) 486 - nv_mask(device, NV50_PDISPLAY_INTR_EN_1, 487 - NV50_PDISPLAY_INTR_EN_1_VBLANK_CRTC_(crtc), 0); 488 - else 489 - NVWriteCRTC(dev, crtc, NV_PCRTC_INTR_EN_0, 0); 490 - } 491 - 492 481 static int 493 482 nouveau_page_flip_reserve(struct nouveau_bo *old_bo, 494 483 struct nouveau_bo *new_bo) ··· 540 595 } 541 596 FIRE_RING (chan); 542 597 543 - ret = nouveau_fence_new(chan, pfence); 598 + ret = nouveau_fence_new(chan, false, pfence); 544 599 if (ret) 545 600 goto fail; 546 601
-3
drivers/gpu/drm/nouveau/nouveau_display.h
··· 59 59 int nouveau_display_suspend(struct drm_device *dev); 60 60 void nouveau_display_resume(struct drm_device *dev); 61 61 62 - int nouveau_vblank_enable(struct drm_device *dev, int crtc); 63 - void nouveau_vblank_disable(struct drm_device *dev, int crtc); 64 - 65 62 int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 66 63 struct drm_pending_vblank_event *event); 67 64 int nouveau_finish_page_flip(struct nouveau_channel *,
+1 -1
drivers/gpu/drm/nouveau/nouveau_dma.h
··· 191 191 #define NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG 0x00000002 192 192 #define NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL 0x00000004 193 193 #define NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD 0x00001000 194 - #define NV84_SUBCHAN_NOTIFY_INTR 0x00000020 194 + #define NV84_SUBCHAN_UEVENT 0x00000020 195 195 #define NV84_SUBCHAN_WRCACHE_FLUSH 0x00000024 196 196 #define NV10_SUBCHAN_REF_CNT 0x00000050 197 197 #define NVSW_SUBCHAN_PAGE_FLIP 0x00000054
+1 -296
drivers/gpu/drm/nouveau/nouveau_dp.c
··· 35 35 #include <subdev/gpio.h> 36 36 #include <subdev/i2c.h> 37 37 38 - /****************************************************************************** 39 - * link training 40 - *****************************************************************************/ 41 - struct dp_state { 42 - struct nouveau_i2c_port *auxch; 43 - struct nouveau_object *core; 44 - struct dcb_output *dcb; 45 - int crtc; 46 - u8 *dpcd; 47 - int link_nr; 48 - u32 link_bw; 49 - u8 stat[6]; 50 - u8 conf[4]; 51 - }; 52 - 53 - static void 54 - dp_set_link_config(struct drm_device *dev, struct dp_state *dp) 55 - { 56 - struct nouveau_drm *drm = nouveau_drm(dev); 57 - struct dcb_output *dcb = dp->dcb; 58 - const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); 59 - const u32 moff = (dp->crtc << 3) | (link << 2) | or; 60 - u8 sink[2]; 61 - u32 data; 62 - 63 - NV_DEBUG(drm, "%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); 64 - 65 - /* set desired link configuration on the source */ 66 - data = ((dp->link_bw / 27000) << 8) | dp->link_nr; 67 - if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) 68 - data |= NV94_DISP_SOR_DP_LNKCTL_FRAME_ENH; 69 - 70 - nv_call(dp->core, NV94_DISP_SOR_DP_LNKCTL + moff, data); 71 - 72 - /* inform the sink of the new configuration */ 73 - sink[0] = dp->link_bw / 27000; 74 - sink[1] = dp->link_nr; 75 - if (dp->dpcd[2] & DP_ENHANCED_FRAME_CAP) 76 - sink[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN; 77 - 78 - nv_wraux(dp->auxch, DP_LINK_BW_SET, sink, 2); 79 - } 80 - 81 - static void 82 - dp_set_training_pattern(struct drm_device *dev, struct dp_state *dp, u8 pattern) 83 - { 84 - struct nouveau_drm *drm = nouveau_drm(dev); 85 - struct dcb_output *dcb = dp->dcb; 86 - const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); 87 - const u32 moff = (dp->crtc << 3) | (link << 2) | or; 88 - u8 sink_tp; 89 - 90 - NV_DEBUG(drm, "training pattern %d\n", pattern); 91 - 92 - nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, pattern); 93 - 94 - nv_rdaux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 95 - sink_tp &= ~DP_TRAINING_PATTERN_MASK; 96 - sink_tp |= pattern; 97 - nv_wraux(dp->auxch, DP_TRAINING_PATTERN_SET, &sink_tp, 1); 98 - } 99 - 100 - static int 101 - dp_link_train_commit(struct drm_device *dev, struct dp_state *dp) 102 - { 103 - struct nouveau_drm *drm = nouveau_drm(dev); 104 - struct dcb_output *dcb = dp->dcb; 105 - const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); 106 - const u32 moff = (dp->crtc << 3) | (link << 2) | or; 107 - int i; 108 - 109 - for (i = 0; i < dp->link_nr; i++) { 110 - u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; 111 - u8 lpre = (lane & 0x0c) >> 2; 112 - u8 lvsw = (lane & 0x03) >> 0; 113 - 114 - dp->conf[i] = (lpre << 3) | lvsw; 115 - if (lvsw == DP_TRAIN_VOLTAGE_SWING_1200) 116 - dp->conf[i] |= DP_TRAIN_MAX_SWING_REACHED; 117 - if ((lpre << 3) == DP_TRAIN_PRE_EMPHASIS_9_5) 118 - dp->conf[i] |= DP_TRAIN_MAX_PRE_EMPHASIS_REACHED; 119 - 120 - NV_DEBUG(drm, "config lane %d %02x\n", i, dp->conf[i]); 121 - 122 - nv_call(dp->core, NV94_DISP_SOR_DP_DRVCTL(i) + moff, (lvsw << 8) | lpre); 123 - } 124 - 125 - return nv_wraux(dp->auxch, DP_TRAINING_LANE0_SET, dp->conf, 4); 126 - } 127 - 128 - static int 129 - dp_link_train_update(struct drm_device *dev, struct dp_state *dp, u32 delay) 130 - { 131 - struct nouveau_drm *drm = nouveau_drm(dev); 132 - int ret; 133 - 134 - udelay(delay); 135 - 136 - ret = nv_rdaux(dp->auxch, DP_LANE0_1_STATUS, dp->stat, 6); 137 - if (ret) 138 - return ret; 139 - 140 - NV_DEBUG(drm, "status %*ph\n", 6, dp->stat); 141 - return 0; 142 - } 143 - 144 - static int 145 - dp_link_train_cr(struct drm_device *dev, struct dp_state *dp) 146 - { 147 - bool cr_done = false, abort = false; 148 - int voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 149 - int tries = 0, i; 150 - 151 - dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_1); 152 - 153 - do { 154 - if (dp_link_train_commit(dev, dp) || 155 - dp_link_train_update(dev, dp, 100)) 156 - break; 157 - 158 - cr_done = true; 159 - for (i = 0; i < dp->link_nr; i++) { 160 - u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; 161 - if (!(lane & DP_LANE_CR_DONE)) { 162 - cr_done = false; 163 - if (dp->conf[i] & DP_TRAIN_MAX_SWING_REACHED) 164 - abort = true; 165 - break; 166 - } 167 - } 168 - 169 - if ((dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK) != voltage) { 170 - voltage = dp->conf[0] & DP_TRAIN_VOLTAGE_SWING_MASK; 171 - tries = 0; 172 - } 173 - } while (!cr_done && !abort && ++tries < 5); 174 - 175 - return cr_done ? 0 : -1; 176 - } 177 - 178 - static int 179 - dp_link_train_eq(struct drm_device *dev, struct dp_state *dp) 180 - { 181 - bool eq_done, cr_done = true; 182 - int tries = 0, i; 183 - 184 - dp_set_training_pattern(dev, dp, DP_TRAINING_PATTERN_2); 185 - 186 - do { 187 - if (dp_link_train_update(dev, dp, 400)) 188 - break; 189 - 190 - eq_done = !!(dp->stat[2] & DP_INTERLANE_ALIGN_DONE); 191 - for (i = 0; i < dp->link_nr && eq_done; i++) { 192 - u8 lane = (dp->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; 193 - if (!(lane & DP_LANE_CR_DONE)) 194 - cr_done = false; 195 - if (!(lane & DP_LANE_CHANNEL_EQ_DONE) || 196 - !(lane & DP_LANE_SYMBOL_LOCKED)) 197 - eq_done = false; 198 - } 199 - 200 - if (dp_link_train_commit(dev, dp)) 201 - break; 202 - } while (!eq_done && cr_done && ++tries <= 5); 203 - 204 - return eq_done ? 0 : -1; 205 - } 206 - 207 - static void 208 - dp_link_train_init(struct drm_device *dev, struct dp_state *dp, bool spread) 209 - { 210 - struct dcb_output *dcb = dp->dcb; 211 - const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); 212 - const u32 moff = (dp->crtc << 3) | (link << 2) | or; 213 - 214 - nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, (spread ? 215 - NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_ON : 216 - NV94_DISP_SOR_DP_TRAIN_INIT_SPREAD_OFF) | 217 - NV94_DISP_SOR_DP_TRAIN_OP_INIT); 218 - } 219 - 220 - static void 221 - dp_link_train_fini(struct drm_device *dev, struct dp_state *dp) 222 - { 223 - struct dcb_output *dcb = dp->dcb; 224 - const u32 or = ffs(dcb->or) - 1, link = !(dcb->sorconf.link & 1); 225 - const u32 moff = (dp->crtc << 3) | (link << 2) | or; 226 - 227 - nv_call(dp->core, NV94_DISP_SOR_DP_TRAIN + moff, 228 - NV94_DISP_SOR_DP_TRAIN_OP_FINI); 229 - } 230 - 231 - static bool 232 - nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate, 233 - struct nouveau_object *core) 234 - { 235 - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 236 - struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 237 - struct nouveau_connector *nv_connector = 238 - nouveau_encoder_connector_get(nv_encoder); 239 - struct drm_device *dev = encoder->dev; 240 - struct nouveau_drm *drm = nouveau_drm(dev); 241 - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 242 - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 243 - const u32 bw_list[] = { 270000, 162000, 0 }; 244 - const u32 *link_bw = bw_list; 245 - struct dp_state dp; 246 - 247 - dp.auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); 248 - if (!dp.auxch) 249 - return false; 250 - 251 - dp.core = core; 252 - dp.dcb = nv_encoder->dcb; 253 - dp.crtc = nv_crtc->index; 254 - dp.dpcd = nv_encoder->dp.dpcd; 255 - 256 - /* adjust required bandwidth for 8B/10B coding overhead */ 257 - datarate = (datarate / 8) * 10; 258 - 259 - /* some sinks toggle hotplug in response to some of the actions 260 - * we take during link training (DP_SET_POWER is one), we need 261 - * to ignore them for the moment to avoid races. 262 - */ 263 - gpio->irq(gpio, 0, nv_connector->hpd, 0xff, false); 264 - 265 - /* enable down-spreading and execute pre-train script from vbios */ 266 - dp_link_train_init(dev, &dp, nv_encoder->dp.dpcd[3] & 1); 267 - 268 - /* start off at highest link rate supported by encoder and display */ 269 - while (*link_bw > nv_encoder->dp.link_bw) 270 - link_bw++; 271 - 272 - while (link_bw[0]) { 273 - /* find minimum required lane count at this link rate */ 274 - dp.link_nr = nv_encoder->dp.link_nr; 275 - while ((dp.link_nr >> 1) * link_bw[0] > datarate) 276 - dp.link_nr >>= 1; 277 - 278 - /* drop link rate to minimum with this lane count */ 279 - while ((link_bw[1] * dp.link_nr) > datarate) 280 - link_bw++; 281 - dp.link_bw = link_bw[0]; 282 - 283 - /* program selected link configuration */ 284 - dp_set_link_config(dev, &dp); 285 - 286 - /* attempt to train the link at this configuration */ 287 - memset(dp.stat, 0x00, sizeof(dp.stat)); 288 - if (!dp_link_train_cr(dev, &dp) && 289 - !dp_link_train_eq(dev, &dp)) 290 - break; 291 - 292 - /* retry at lower rate */ 293 - link_bw++; 294 - } 295 - 296 - /* finish link training */ 297 - dp_set_training_pattern(dev, &dp, DP_TRAINING_PATTERN_DISABLE); 298 - 299 - /* execute post-train script from vbios */ 300 - dp_link_train_fini(dev, &dp); 301 - 302 - /* re-enable hotplug detect */ 303 - gpio->irq(gpio, 0, nv_connector->hpd, 0xff, true); 304 - return true; 305 - } 306 - 307 - void 308 - nouveau_dp_dpms(struct drm_encoder *encoder, int mode, u32 datarate, 309 - struct nouveau_object *core) 310 - { 311 - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 312 - struct nouveau_drm *drm = nouveau_drm(encoder->dev); 313 - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 314 - struct nouveau_i2c_port *auxch; 315 - u8 status; 316 - 317 - auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); 318 - if (!auxch) 319 - return; 320 - 321 - if (mode == DRM_MODE_DPMS_ON) 322 - status = DP_SET_POWER_D0; 323 - else 324 - status = DP_SET_POWER_D3; 325 - 326 - nv_wraux(auxch, DP_SET_POWER, &status, 1); 327 - 328 - if (mode == DRM_MODE_DPMS_ON) 329 - nouveau_dp_link_train(encoder, datarate, core); 330 - } 331 - 332 38 static void 333 39 nouveau_dp_probe_oui(struct drm_device *dev, struct nouveau_i2c_port *auxch, 334 40 u8 *dpcd) ··· 61 355 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 62 356 struct drm_device *dev = encoder->dev; 63 357 struct nouveau_drm *drm = nouveau_drm(dev); 64 - struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 65 358 struct nouveau_i2c_port *auxch; 66 359 u8 *dpcd = nv_encoder->dp.dpcd; 67 360 int ret; 68 361 69 - auxch = i2c->find(i2c, nv_encoder->dcb->i2c_index); 362 + auxch = nv_encoder->i2c; 70 363 if (!auxch) 71 364 return false; 72 365
+38 -7
drivers/gpu/drm/nouveau/nouveau_drm.c
··· 34 34 #include <subdev/device.h> 35 35 #include <subdev/vm.h> 36 36 37 + #include <engine/disp.h> 38 + 37 39 #include "nouveau_drm.h" 38 40 #include "nouveau_irq.h" 39 41 #include "nouveau_dma.h" ··· 69 67 module_param_named(modeset, nouveau_modeset, int, 0400); 70 68 71 69 static struct drm_driver driver; 70 + 71 + static int 72 + nouveau_drm_vblank_enable(struct drm_device *dev, int head) 73 + { 74 + struct nouveau_drm *drm = nouveau_drm(dev); 75 + struct nouveau_disp *pdisp = nouveau_disp(drm->device); 76 + nouveau_event_get(pdisp->vblank, head, &drm->vblank); 77 + return 0; 78 + } 79 + 80 + static void 81 + nouveau_drm_vblank_disable(struct drm_device *dev, int head) 82 + { 83 + struct nouveau_drm *drm = nouveau_drm(dev); 84 + struct nouveau_disp *pdisp = nouveau_disp(drm->device); 85 + nouveau_event_put(pdisp->vblank, head, &drm->vblank); 86 + } 87 + 88 + static int 89 + nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head) 90 + { 91 + struct nouveau_drm *drm = 92 + container_of(event, struct nouveau_drm, vblank); 93 + drm_handle_vblank(drm->dev, head); 94 + return NVKM_EVENT_KEEP; 95 + } 72 96 73 97 static u64 74 98 nouveau_name(struct pci_dev *pdev) ··· 160 132 161 133 /* initialise synchronisation routines */ 162 134 if (device->card_type < NV_10) ret = nv04_fence_create(drm); 163 - else if (device->card_type < NV_50) ret = nv10_fence_create(drm); 135 + else if (device->chipset < 0x17) ret = nv10_fence_create(drm); 136 + else if (device->card_type < NV_50) ret = nv17_fence_create(drm); 164 137 else if (device->chipset < 0x84) ret = nv50_fence_create(drm); 165 138 else if (device->card_type < NV_C0) ret = nv84_fence_create(drm); 166 139 else ret = nvc0_fence_create(drm); ··· 288 259 289 260 dev->dev_private = drm; 290 261 drm->dev = dev; 262 + drm->vblank.func = nouveau_drm_vblank_handler; 291 263 292 264 INIT_LIST_HEAD(&drm->clients); 293 265 spin_lock_init(&drm->tile.lock); ··· 428 398 nouveau_object_debug(); 429 399 } 430 400 431 - int 401 + static int 432 402 nouveau_do_suspend(struct drm_device *dev) 433 403 { 434 404 struct nouveau_drm *drm = nouveau_drm(dev); ··· 499 469 return 0; 500 470 } 501 471 502 - int 472 + static int 503 473 nouveau_do_resume(struct drm_device *dev) 504 474 { 505 475 struct nouveau_drm *drm = nouveau_drm(dev); ··· 573 543 struct pci_dev *pdev = dev->pdev; 574 544 struct nouveau_drm *drm = nouveau_drm(dev); 575 545 struct nouveau_cli *cli; 576 - char name[16]; 546 + char name[32], tmpname[TASK_COMM_LEN]; 577 547 int ret; 578 548 579 - snprintf(name, sizeof(name), "%d", pid_nr(fpriv->pid)); 549 + get_task_comm(tmpname, current); 550 + snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); 580 551 581 552 ret = nouveau_cli_create(pdev, name, sizeof(*cli), (void **)&cli); 582 553 if (ret) ··· 673 642 .irq_handler = nouveau_irq_handler, 674 643 675 644 .get_vblank_counter = drm_vblank_count, 676 - .enable_vblank = nouveau_vblank_enable, 677 - .disable_vblank = nouveau_vblank_disable, 645 + .enable_vblank = nouveau_drm_vblank_enable, 646 + .disable_vblank = nouveau_drm_vblank_disable, 678 647 679 648 .ioctls = nouveau_ioctls, 680 649 .fops = &nouveau_driver_fops,
+2
drivers/gpu/drm/nouveau/nouveau_drm.h
··· 13 13 #define DRIVER_PATCHLEVEL 0 14 14 15 15 #include <core/client.h> 16 + #include <core/event.h> 16 17 17 18 #include <subdev/vm.h> 18 19 ··· 113 112 struct nvbios vbios; 114 113 struct nouveau_display *display; 115 114 struct backlight_device *backlight; 115 + struct nouveau_eventh vblank; 116 116 117 117 /* power management */ 118 118 struct nouveau_pm *pm;
+1 -8
drivers/gpu/drm/nouveau/nouveau_encoder.h
··· 36 36 37 37 struct nouveau_i2c_port; 38 38 39 - struct dp_train_func { 40 - void (*link_set)(struct drm_device *, struct dcb_output *, int crtc, 41 - int nr, u32 bw, bool enhframe); 42 - void (*train_set)(struct drm_device *, struct dcb_output *, u8 pattern); 43 - void (*train_adj)(struct drm_device *, struct dcb_output *, 44 - u8 lane, u8 swing, u8 preem); 45 - }; 46 - 47 39 struct nouveau_encoder { 48 40 struct drm_encoder_slave base; 49 41 50 42 struct dcb_output *dcb; 51 43 int or; 44 + struct nouveau_i2c_port *i2c; 52 45 53 46 /* different to drm_encoder.crtc, this reflects what's 54 47 * actually programmed on the hw, not the proposed crtc */
+87 -16
drivers/gpu/drm/nouveau/nouveau_fence.c
··· 33 33 #include "nouveau_dma.h" 34 34 #include "nouveau_fence.h" 35 35 36 + #include <engine/fifo.h> 37 + 36 38 void 37 39 nouveau_fence_context_del(struct nouveau_fence_chan *fctx) 38 40 { 39 41 struct nouveau_fence *fence, *fnext; 40 42 spin_lock(&fctx->lock); 41 43 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { 42 - if (fence->work) 43 - fence->work(fence->priv, false); 44 44 fence->channel = NULL; 45 45 list_del(&fence->head); 46 46 nouveau_fence_unref(&fence); ··· 59 59 static void 60 60 nouveau_fence_update(struct nouveau_channel *chan) 61 61 { 62 - struct nouveau_fence_priv *priv = chan->drm->fence; 63 62 struct nouveau_fence_chan *fctx = chan->fence; 64 63 struct nouveau_fence *fence, *fnext; 65 64 66 65 spin_lock(&fctx->lock); 67 66 list_for_each_entry_safe(fence, fnext, &fctx->pending, head) { 68 - if (priv->read(chan) < fence->sequence) 67 + if (fctx->read(chan) < fence->sequence) 69 68 break; 70 69 71 - if (fence->work) 72 - fence->work(fence->priv, true); 73 70 fence->channel = NULL; 74 71 list_del(&fence->head); 75 72 nouveau_fence_unref(&fence); ··· 77 80 int 78 81 nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) 79 82 { 80 - struct nouveau_fence_priv *priv = chan->drm->fence; 81 83 struct nouveau_fence_chan *fctx = chan->fence; 82 84 int ret; 83 85 ··· 84 88 fence->timeout = jiffies + (3 * DRM_HZ); 85 89 fence->sequence = ++fctx->sequence; 86 90 87 - ret = priv->emit(fence); 91 + ret = fctx->emit(fence); 88 92 if (!ret) { 89 93 kref_get(&fence->kref); 90 94 spin_lock(&fctx->lock); ··· 103 107 return !fence->channel; 104 108 } 105 109 110 + struct nouveau_fence_uevent { 111 + struct nouveau_eventh handler; 112 + struct nouveau_fence_priv *priv; 113 + }; 114 + 115 + static int 116 + nouveau_fence_wait_uevent_handler(struct nouveau_eventh *event, int index) 117 + { 118 + struct nouveau_fence_uevent *uevent = 119 + container_of(event, struct nouveau_fence_uevent, handler); 120 + wake_up_all(&uevent->priv->waiting); 121 + return NVKM_EVENT_KEEP; 122 + } 123 + 124 + static int 125 + nouveau_fence_wait_uevent(struct nouveau_fence *fence, bool intr) 126 + 127 + { 128 + struct nouveau_channel *chan = fence->channel; 129 + struct nouveau_fifo *pfifo = nouveau_fifo(chan->drm->device); 130 + struct nouveau_fence_priv *priv = chan->drm->fence; 131 + struct nouveau_fence_uevent uevent = { 132 + .handler.func = nouveau_fence_wait_uevent_handler, 133 + .priv = priv, 134 + }; 135 + int ret = 0; 136 + 137 + nouveau_event_get(pfifo->uevent, 0, &uevent.handler); 138 + 139 + if (fence->timeout) { 140 + unsigned long timeout = fence->timeout - jiffies; 141 + 142 + if (time_before(jiffies, fence->timeout)) { 143 + if (intr) { 144 + ret = wait_event_interruptible_timeout( 145 + priv->waiting, 146 + nouveau_fence_done(fence), 147 + timeout); 148 + } else { 149 + ret = wait_event_timeout(priv->waiting, 150 + nouveau_fence_done(fence), 151 + timeout); 152 + } 153 + } 154 + 155 + if (ret >= 0) { 156 + fence->timeout = jiffies + ret; 157 + if (time_after_eq(jiffies, fence->timeout)) 158 + ret = -EBUSY; 159 + } 160 + } else { 161 + if (intr) { 162 + ret = wait_event_interruptible(priv->waiting, 163 + nouveau_fence_done(fence)); 164 + } else { 165 + wait_event(priv->waiting, nouveau_fence_done(fence)); 166 + } 167 + } 168 + 169 + nouveau_event_put(pfifo->uevent, 0, &uevent.handler); 170 + if (unlikely(ret < 0)) 171 + return ret; 172 + 173 + return 0; 174 + } 175 + 106 176 int 107 177 nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr) 108 178 { 179 + struct nouveau_channel *chan = fence->channel; 180 + struct nouveau_fence_priv *priv = chan ? chan->drm->fence : NULL; 109 181 unsigned long sleep_time = NSEC_PER_MSEC / 1000; 110 182 ktime_t t; 111 183 int ret = 0; 184 + 185 + while (priv && priv->uevent && lazy && !nouveau_fence_done(fence)) { 186 + ret = nouveau_fence_wait_uevent(fence, intr); 187 + if (ret < 0) 188 + return ret; 189 + } 112 190 113 191 while (!nouveau_fence_done(fence)) { 114 192 if (fence->timeout && time_after_eq(jiffies, fence->timeout)) { ··· 213 143 int 214 144 nouveau_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *chan) 215 145 { 216 - struct nouveau_fence_priv *priv = chan->drm->fence; 146 + struct nouveau_fence_chan *fctx = chan->fence; 217 147 struct nouveau_channel *prev; 218 148 int ret = 0; 219 149 220 150 prev = fence ? fence->channel : NULL; 221 151 if (prev) { 222 152 if (unlikely(prev != chan && !nouveau_fence_done(fence))) { 223 - ret = priv->sync(fence, prev, chan); 153 + ret = fctx->sync(fence, prev, chan); 224 154 if (unlikely(ret)) 225 155 ret = nouveau_fence_wait(fence, true, false); 226 156 } ··· 252 182 } 253 183 254 184 int 255 - nouveau_fence_new(struct nouveau_channel *chan, struct nouveau_fence **pfence) 185 + nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, 186 + struct nouveau_fence **pfence) 256 187 { 257 188 struct nouveau_fence *fence; 258 189 int ret = 0; ··· 264 193 fence = kzalloc(sizeof(*fence), GFP_KERNEL); 265 194 if (!fence) 266 195 return -ENOMEM; 196 + 197 + fence->sysmem = sysmem; 267 198 kref_init(&fence->kref); 268 199 269 - if (chan) { 270 - ret = nouveau_fence_emit(fence, chan); 271 - if (ret) 272 - nouveau_fence_unref(&fence); 273 - } 200 + ret = nouveau_fence_emit(fence, chan); 201 + if (ret) 202 + nouveau_fence_unref(&fence); 274 203 275 204 *pfence = fence; 276 205 return ret;
+33 -9
drivers/gpu/drm/nouveau/nouveau_fence.h
··· 7 7 struct list_head head; 8 8 struct kref kref; 9 9 10 + bool sysmem; 11 + 10 12 struct nouveau_channel *channel; 11 13 unsigned long timeout; 12 14 u32 sequence; 13 - 14 - void (*work)(void *priv, bool signalled); 15 - void *priv; 16 15 }; 17 16 18 - int nouveau_fence_new(struct nouveau_channel *, struct nouveau_fence **); 17 + int nouveau_fence_new(struct nouveau_channel *, bool sysmem, 18 + struct nouveau_fence **); 19 19 struct nouveau_fence * 20 20 nouveau_fence_ref(struct nouveau_fence *); 21 21 void nouveau_fence_unref(struct nouveau_fence **); ··· 29 29 struct list_head pending; 30 30 struct list_head flip; 31 31 32 + int (*emit)(struct nouveau_fence *); 33 + int (*sync)(struct nouveau_fence *, struct nouveau_channel *, 34 + struct nouveau_channel *); 35 + u32 (*read)(struct nouveau_channel *); 36 + int (*emit32)(struct nouveau_channel *, u64, u32); 37 + int (*sync32)(struct nouveau_channel *, u64, u32); 38 + 32 39 spinlock_t lock; 33 40 u32 sequence; 34 41 }; ··· 46 39 void (*resume)(struct nouveau_drm *); 47 40 int (*context_new)(struct nouveau_channel *); 48 41 void (*context_del)(struct nouveau_channel *); 49 - int (*emit)(struct nouveau_fence *); 50 - int (*sync)(struct nouveau_fence *, struct nouveau_channel *, 51 - struct nouveau_channel *); 52 - u32 (*read)(struct nouveau_channel *); 42 + 43 + wait_queue_head_t waiting; 44 + bool uevent; 53 45 }; 54 46 55 47 #define nouveau_fence(drm) ((struct nouveau_fence_priv *)(drm)->fence) ··· 66 60 void nv10_fence_context_del(struct nouveau_channel *); 67 61 void nv10_fence_destroy(struct nouveau_drm *); 68 62 int nv10_fence_create(struct nouveau_drm *); 63 + 64 + int nv17_fence_create(struct nouveau_drm *); 69 65 void nv17_fence_resume(struct nouveau_drm *drm); 70 66 71 67 int nv50_fence_create(struct nouveau_drm *); 72 68 int nv84_fence_create(struct nouveau_drm *); 73 69 int nvc0_fence_create(struct nouveau_drm *); 74 - u64 nvc0_fence_crtc(struct nouveau_channel *, int crtc); 75 70 76 71 int nouveau_flip_complete(void *chan); 72 + 73 + struct nv84_fence_chan { 74 + struct nouveau_fence_chan base; 75 + struct nouveau_vma vma; 76 + struct nouveau_vma vma_gart; 77 + struct nouveau_vma dispc_vma[4]; 78 + }; 79 + 80 + struct nv84_fence_priv { 81 + struct nouveau_fence_priv base; 82 + struct nouveau_bo *bo; 83 + struct nouveau_bo *bo_gart; 84 + u32 *suspend; 85 + }; 86 + 87 + u64 nv84_fence_crtc(struct nouveau_channel *, int); 88 + int nv84_fence_context_new(struct nouveau_channel *); 77 89 78 90 #endif
+42 -39
drivers/gpu/drm/nouveau/nouveau_gem.c
··· 203 203 struct drm_file *file_priv) 204 204 { 205 205 struct nouveau_drm *drm = nouveau_drm(dev); 206 + struct nouveau_cli *cli = nouveau_cli(file_priv); 206 207 struct nouveau_fb *pfb = nouveau_fb(drm->device); 207 208 struct drm_nouveau_gem_new *req = data; 208 209 struct nouveau_bo *nvbo = NULL; ··· 212 211 drm->ttm.bdev.dev_mapping = drm->dev->dev_mapping; 213 212 214 213 if (!pfb->memtype_valid(pfb, req->info.tile_flags)) { 215 - NV_ERROR(drm, "bad page flags: 0x%08x\n", req->info.tile_flags); 214 + NV_ERROR(cli, "bad page flags: 0x%08x\n", req->info.tile_flags); 216 215 return -EINVAL; 217 216 } 218 217 ··· 314 313 struct drm_nouveau_gem_pushbuf_bo *pbbo, 315 314 int nr_buffers, struct validate_op *op) 316 315 { 316 + struct nouveau_cli *cli = nouveau_cli(file_priv); 317 317 struct drm_device *dev = chan->drm->dev; 318 318 struct nouveau_drm *drm = nouveau_drm(dev); 319 319 uint32_t sequence; ··· 325 323 sequence = atomic_add_return(1, &drm->ttm.validate_sequence); 326 324 retry: 327 325 if (++trycnt > 100000) { 328 - NV_ERROR(drm, "%s failed and gave up.\n", __func__); 326 + NV_ERROR(cli, "%s failed and gave up.\n", __func__); 329 327 return -EINVAL; 330 328 } 331 329 ··· 336 334 337 335 gem = drm_gem_object_lookup(dev, file_priv, b->handle); 338 336 if (!gem) { 339 - NV_ERROR(drm, "Unknown handle 0x%08x\n", b->handle); 337 + NV_ERROR(cli, "Unknown handle 0x%08x\n", b->handle); 340 338 validate_fini(op, NULL); 341 339 return -ENOENT; 342 340 } ··· 348 346 } 349 347 350 348 if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { 351 - NV_ERROR(drm, "multiple instances of buffer %d on " 349 + NV_ERROR(cli, "multiple instances of buffer %d on " 352 350 "validation list\n", b->handle); 353 351 drm_gem_object_unreference_unlocked(gem); 354 352 validate_fini(op, NULL); ··· 368 366 if (unlikely(ret)) { 369 367 drm_gem_object_unreference_unlocked(gem); 370 368 if (ret != -ERESTARTSYS) 371 - NV_ERROR(drm, "fail reserve\n"); 369 + NV_ERROR(cli, "fail reserve\n"); 372 370 return ret; 373 371 } 374 372 } ··· 386 384 if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) 387 385 list_add_tail(&nvbo->entry, &op->gart_list); 388 386 else { 389 - NV_ERROR(drm, "invalid valid domains: 0x%08x\n", 387 + NV_ERROR(cli, "invalid valid domains: 0x%08x\n", 390 388 b->valid_domains); 391 389 list_add_tail(&nvbo->entry, &op->both_list); 392 390 validate_fini(op, NULL); ··· 419 417 } 420 418 421 419 static int 422 - validate_list(struct nouveau_channel *chan, struct list_head *list, 423 - struct drm_nouveau_gem_pushbuf_bo *pbbo, uint64_t user_pbbo_ptr) 420 + validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, 421 + struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo, 422 + uint64_t user_pbbo_ptr) 424 423 { 425 424 struct nouveau_drm *drm = chan->drm; 426 425 struct drm_nouveau_gem_pushbuf_bo __user *upbbo = ··· 434 431 435 432 ret = validate_sync(chan, nvbo); 436 433 if (unlikely(ret)) { 437 - NV_ERROR(drm, "fail pre-validate sync\n"); 434 + NV_ERROR(cli, "fail pre-validate sync\n"); 438 435 return ret; 439 436 } 440 437 ··· 442 439 b->write_domains, 443 440 b->valid_domains); 444 441 if (unlikely(ret)) { 445 - NV_ERROR(drm, "fail set_domain\n"); 442 + NV_ERROR(cli, "fail set_domain\n"); 446 443 return ret; 447 444 } 448 445 449 446 ret = nouveau_bo_validate(nvbo, true, false); 450 447 if (unlikely(ret)) { 451 448 if (ret != -ERESTARTSYS) 452 - NV_ERROR(drm, "fail ttm_validate\n"); 449 + NV_ERROR(cli, "fail ttm_validate\n"); 453 450 return ret; 454 451 } 455 452 456 453 ret = validate_sync(chan, nvbo); 457 454 if (unlikely(ret)) { 458 - NV_ERROR(drm, "fail post-validate sync\n"); 455 + NV_ERROR(cli, "fail post-validate sync\n"); 459 456 return ret; 460 457 } 461 458 ··· 491 488 uint64_t user_buffers, int nr_buffers, 492 489 struct validate_op *op, int *apply_relocs) 493 490 { 494 - struct nouveau_drm *drm = chan->drm; 491 + struct nouveau_cli *cli = nouveau_cli(file_priv); 495 492 int ret, relocs = 0; 496 493 497 494 INIT_LIST_HEAD(&op->vram_list); ··· 504 501 ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); 505 502 if (unlikely(ret)) { 506 503 if (ret != -ERESTARTSYS) 507 - NV_ERROR(drm, "validate_init\n"); 504 + NV_ERROR(cli, "validate_init\n"); 508 505 return ret; 509 506 } 510 507 511 - ret = validate_list(chan, &op->vram_list, pbbo, user_buffers); 508 + ret = validate_list(chan, cli, &op->vram_list, pbbo, user_buffers); 512 509 if (unlikely(ret < 0)) { 513 510 if (ret != -ERESTARTSYS) 514 - NV_ERROR(drm, "validate vram_list\n"); 511 + NV_ERROR(cli, "validate vram_list\n"); 515 512 validate_fini(op, NULL); 516 513 return ret; 517 514 } 518 515 relocs += ret; 519 516 520 - ret = validate_list(chan, &op->gart_list, pbbo, user_buffers); 517 + ret = validate_list(chan, cli, &op->gart_list, pbbo, user_buffers); 521 518 if (unlikely(ret < 0)) { 522 519 if (ret != -ERESTARTSYS) 523 - NV_ERROR(drm, "validate gart_list\n"); 520 + NV_ERROR(cli, "validate gart_list\n"); 524 521 validate_fini(op, NULL); 525 522 return ret; 526 523 } 527 524 relocs += ret; 528 525 529 - ret = validate_list(chan, &op->both_list, pbbo, user_buffers); 526 + ret = validate_list(chan, cli, &op->both_list, pbbo, user_buffers); 530 527 if (unlikely(ret < 0)) { 531 528 if (ret != -ERESTARTSYS) 532 - NV_ERROR(drm, "validate both_list\n"); 529 + NV_ERROR(cli, "validate both_list\n"); 533 530 validate_fini(op, NULL); 534 531 return ret; 535 532 } ··· 558 555 } 559 556 560 557 static int 561 - nouveau_gem_pushbuf_reloc_apply(struct drm_device *dev, 558 + nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, 562 559 struct drm_nouveau_gem_pushbuf *req, 563 560 struct drm_nouveau_gem_pushbuf_bo *bo) 564 561 { 565 - struct nouveau_drm *drm = nouveau_drm(dev); 566 562 struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; 567 563 int ret = 0; 568 564 unsigned i; ··· 577 575 uint32_t data; 578 576 579 577 if (unlikely(r->bo_index > req->nr_buffers)) { 580 - NV_ERROR(drm, "reloc bo index invalid\n"); 578 + NV_ERROR(cli, "reloc bo index invalid\n"); 581 579 ret = -EINVAL; 582 580 break; 583 581 } ··· 587 585 continue; 588 586 589 587 if (unlikely(r->reloc_bo_index > req->nr_buffers)) { 590 - NV_ERROR(drm, "reloc container bo index invalid\n"); 588 + NV_ERROR(cli, "reloc container bo index invalid\n"); 591 589 ret = -EINVAL; 592 590 break; 593 591 } ··· 595 593 596 594 if (unlikely(r->reloc_bo_offset + 4 > 597 595 nvbo->bo.mem.num_pages << PAGE_SHIFT)) { 598 - NV_ERROR(drm, "reloc outside of bo\n"); 596 + NV_ERROR(cli, "reloc outside of bo\n"); 599 597 ret = -EINVAL; 600 598 break; 601 599 } ··· 604 602 ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, 605 603 &nvbo->kmap); 606 604 if (ret) { 607 - NV_ERROR(drm, "failed kmap for reloc\n"); 605 + NV_ERROR(cli, "failed kmap for reloc\n"); 608 606 break; 609 607 } 610 608 nvbo->validate_mapped = true; ··· 629 627 ret = ttm_bo_wait(&nvbo->bo, false, false, false); 630 628 spin_unlock(&nvbo->bo.bdev->fence_lock); 631 629 if (ret) { 632 - NV_ERROR(drm, "reloc wait_idle failed: %d\n", ret); 630 + NV_ERROR(cli, "reloc wait_idle failed: %d\n", ret); 633 631 break; 634 632 } 635 633 ··· 645 643 struct drm_file *file_priv) 646 644 { 647 645 struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev); 646 + struct nouveau_cli *cli = nouveau_cli(file_priv); 648 647 struct nouveau_abi16_chan *temp; 649 648 struct nouveau_drm *drm = nouveau_drm(dev); 650 649 struct drm_nouveau_gem_pushbuf *req = data; ··· 675 672 goto out_next; 676 673 677 674 if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { 678 - NV_ERROR(drm, "pushbuf push count exceeds limit: %d max %d\n", 675 + NV_ERROR(cli, "pushbuf push count exceeds limit: %d max %d\n", 679 676 req->nr_push, NOUVEAU_GEM_MAX_PUSH); 680 677 return nouveau_abi16_put(abi16, -EINVAL); 681 678 } 682 679 683 680 if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { 684 - NV_ERROR(drm, "pushbuf bo count exceeds limit: %d max %d\n", 681 + NV_ERROR(cli, "pushbuf bo count exceeds limit: %d max %d\n", 685 682 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); 686 683 return nouveau_abi16_put(abi16, -EINVAL); 687 684 } 688 685 689 686 if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { 690 - NV_ERROR(drm, "pushbuf reloc count exceeds limit: %d max %d\n", 687 + NV_ERROR(cli, "pushbuf reloc count exceeds limit: %d max %d\n", 691 688 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); 692 689 return nouveau_abi16_put(abi16, -EINVAL); 693 690 } ··· 705 702 /* Ensure all push buffers are on validate list */ 706 703 for (i = 0; i < req->nr_push; i++) { 707 704 if (push[i].bo_index >= req->nr_buffers) { 708 - NV_ERROR(drm, "push %d buffer not in list\n", i); 705 + NV_ERROR(cli, "push %d buffer not in list\n", i); 709 706 ret = -EINVAL; 710 707 goto out_prevalid; 711 708 } ··· 716 713 req->nr_buffers, &op, &do_reloc); 717 714 if (ret) { 718 715 if (ret != -ERESTARTSYS) 719 - NV_ERROR(drm, "validate: %d\n", ret); 716 + NV_ERROR(cli, "validate: %d\n", ret); 720 717 goto out_prevalid; 721 718 } 722 719 723 720 /* Apply any relocations that are required */ 724 721 if (do_reloc) { 725 - ret = nouveau_gem_pushbuf_reloc_apply(dev, req, bo); 722 + ret = nouveau_gem_pushbuf_reloc_apply(cli, req, bo); 726 723 if (ret) { 727 - NV_ERROR(drm, "reloc apply: %d\n", ret); 724 + NV_ERROR(cli, "reloc apply: %d\n", ret); 728 725 goto out; 729 726 } 730 727 } ··· 732 729 if (chan->dma.ib_max) { 733 730 ret = nouveau_dma_wait(chan, req->nr_push + 1, 16); 734 731 if (ret) { 735 - NV_ERROR(drm, "nv50cal_space: %d\n", ret); 732 + NV_ERROR(cli, "nv50cal_space: %d\n", ret); 736 733 goto out; 737 734 } 738 735 ··· 747 744 if (nv_device(drm->device)->chipset >= 0x25) { 748 745 ret = RING_SPACE(chan, req->nr_push * 2); 749 746 if (ret) { 750 - NV_ERROR(drm, "cal_space: %d\n", ret); 747 + NV_ERROR(cli, "cal_space: %d\n", ret); 751 748 goto out; 752 749 } 753 750 ··· 761 758 } else { 762 759 ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); 763 760 if (ret) { 764 - NV_ERROR(drm, "jmp_space: %d\n", ret); 761 + NV_ERROR(cli, "jmp_space: %d\n", ret); 765 762 goto out; 766 763 } 767 764 ··· 797 794 } 798 795 } 799 796 800 - ret = nouveau_fence_new(chan, &fence); 797 + ret = nouveau_fence_new(chan, false, &fence); 801 798 if (ret) { 802 - NV_ERROR(drm, "error fencing pushbuf: %d\n", ret); 799 + NV_ERROR(cli, "error fencing pushbuf: %d\n", ret); 803 800 WIND_RING(chan); 804 801 goto out; 805 802 }
+224 -9
drivers/gpu/drm/nouveau/nouveau_pm.c
··· 409 409 NULL, 0); 410 410 411 411 static ssize_t 412 + nouveau_hwmon_show_temp1_auto_point1_pwm(struct device *d, 413 + struct device_attribute *a, char *buf) 414 + { 415 + return snprintf(buf, PAGE_SIZE, "%d\n", 100); 416 + } 417 + static SENSOR_DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO, 418 + nouveau_hwmon_show_temp1_auto_point1_pwm, NULL, 0); 419 + 420 + static ssize_t 421 + nouveau_hwmon_temp1_auto_point1_temp(struct device *d, 422 + struct device_attribute *a, char *buf) 423 + { 424 + struct drm_device *dev = dev_get_drvdata(d); 425 + struct nouveau_drm *drm = nouveau_drm(dev); 426 + struct nouveau_therm *therm = nouveau_therm(drm->device); 427 + 428 + return snprintf(buf, PAGE_SIZE, "%d\n", 429 + therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST) * 1000); 430 + } 431 + static ssize_t 432 + nouveau_hwmon_set_temp1_auto_point1_temp(struct device *d, 433 + struct device_attribute *a, 434 + const char *buf, size_t count) 435 + { 436 + struct drm_device *dev = dev_get_drvdata(d); 437 + struct nouveau_drm *drm = nouveau_drm(dev); 438 + struct nouveau_therm *therm = nouveau_therm(drm->device); 439 + long value; 440 + 441 + if (kstrtol(buf, 10, &value) == -EINVAL) 442 + return count; 443 + 444 + therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST, 445 + value / 1000); 446 + 447 + return count; 448 + } 449 + static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IRUGO | S_IWUSR, 450 + nouveau_hwmon_temp1_auto_point1_temp, 451 + nouveau_hwmon_set_temp1_auto_point1_temp, 0); 452 + 453 + static ssize_t 454 + nouveau_hwmon_temp1_auto_point1_temp_hyst(struct device *d, 455 + struct device_attribute *a, char *buf) 456 + { 457 + struct drm_device *dev = dev_get_drvdata(d); 458 + struct nouveau_drm *drm = nouveau_drm(dev); 459 + struct nouveau_therm *therm = nouveau_therm(drm->device); 460 + 461 + return snprintf(buf, PAGE_SIZE, "%d\n", 462 + therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST) * 1000); 463 + } 464 + static ssize_t 465 + nouveau_hwmon_set_temp1_auto_point1_temp_hyst(struct device *d, 466 + struct device_attribute *a, 467 + const char *buf, size_t count) 468 + { 469 + struct drm_device *dev = dev_get_drvdata(d); 470 + struct nouveau_drm *drm = nouveau_drm(dev); 471 + struct nouveau_therm *therm = nouveau_therm(drm->device); 472 + long value; 473 + 474 + if (kstrtol(buf, 10, &value) == -EINVAL) 475 + return count; 476 + 477 + therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_FAN_BOOST_HYST, 478 + value / 1000); 479 + 480 + return count; 481 + } 482 + static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp_hyst, S_IRUGO | S_IWUSR, 483 + nouveau_hwmon_temp1_auto_point1_temp_hyst, 484 + nouveau_hwmon_set_temp1_auto_point1_temp_hyst, 0); 485 + 486 + static ssize_t 412 487 nouveau_hwmon_max_temp(struct device *d, struct device_attribute *a, char *buf) 413 488 { 414 489 struct drm_device *dev = dev_get_drvdata(d); ··· 512 437 static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, nouveau_hwmon_max_temp, 513 438 nouveau_hwmon_set_max_temp, 514 439 0); 440 + 441 + static ssize_t 442 + nouveau_hwmon_max_temp_hyst(struct device *d, struct device_attribute *a, 443 + char *buf) 444 + { 445 + struct drm_device *dev = dev_get_drvdata(d); 446 + struct nouveau_drm *drm = nouveau_drm(dev); 447 + struct nouveau_therm *therm = nouveau_therm(drm->device); 448 + 449 + return snprintf(buf, PAGE_SIZE, "%d\n", 450 + therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST) * 1000); 451 + } 452 + static ssize_t 453 + nouveau_hwmon_set_max_temp_hyst(struct device *d, struct device_attribute *a, 454 + const char *buf, size_t count) 455 + { 456 + struct drm_device *dev = dev_get_drvdata(d); 457 + struct nouveau_drm *drm = nouveau_drm(dev); 458 + struct nouveau_therm *therm = nouveau_therm(drm->device); 459 + long value; 460 + 461 + if (kstrtol(buf, 10, &value) == -EINVAL) 462 + return count; 463 + 464 + therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_DOWN_CLK_HYST, 465 + value / 1000); 466 + 467 + return count; 468 + } 469 + static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, 470 + nouveau_hwmon_max_temp_hyst, 471 + nouveau_hwmon_set_max_temp_hyst, 0); 515 472 516 473 static ssize_t 517 474 nouveau_hwmon_critical_temp(struct device *d, struct device_attribute *a, ··· 578 471 nouveau_hwmon_set_critical_temp, 579 472 0); 580 473 474 + static ssize_t 475 + nouveau_hwmon_critical_temp_hyst(struct device *d, struct device_attribute *a, 476 + char *buf) 477 + { 478 + struct drm_device *dev = dev_get_drvdata(d); 479 + struct nouveau_drm *drm = nouveau_drm(dev); 480 + struct nouveau_therm *therm = nouveau_therm(drm->device); 481 + 482 + return snprintf(buf, PAGE_SIZE, "%d\n", 483 + therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST) * 1000); 484 + } 485 + static ssize_t 486 + nouveau_hwmon_set_critical_temp_hyst(struct device *d, 487 + struct device_attribute *a, 488 + const char *buf, 489 + size_t count) 490 + { 491 + struct drm_device *dev = dev_get_drvdata(d); 492 + struct nouveau_drm *drm = nouveau_drm(dev); 493 + struct nouveau_therm *therm = nouveau_therm(drm->device); 494 + long value; 495 + 496 + if (kstrtol(buf, 10, &value) == -EINVAL) 497 + return count; 498 + 499 + therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_CRITICAL_HYST, 500 + value / 1000); 501 + 502 + return count; 503 + } 504 + static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR, 505 + nouveau_hwmon_critical_temp_hyst, 506 + nouveau_hwmon_set_critical_temp_hyst, 0); 507 + static ssize_t 508 + nouveau_hwmon_emergency_temp(struct device *d, struct device_attribute *a, 509 + char *buf) 510 + { 511 + struct drm_device *dev = dev_get_drvdata(d); 512 + struct nouveau_drm *drm = nouveau_drm(dev); 513 + struct nouveau_therm *therm = nouveau_therm(drm->device); 514 + 515 + return snprintf(buf, PAGE_SIZE, "%d\n", 516 + therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN) * 1000); 517 + } 518 + static ssize_t 519 + nouveau_hwmon_set_emergency_temp(struct device *d, struct device_attribute *a, 520 + const char *buf, 521 + size_t count) 522 + { 523 + struct drm_device *dev = dev_get_drvdata(d); 524 + struct nouveau_drm *drm = nouveau_drm(dev); 525 + struct nouveau_therm *therm = nouveau_therm(drm->device); 526 + long value; 527 + 528 + if (kstrtol(buf, 10, &value) == -EINVAL) 529 + return count; 530 + 531 + therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN, value / 1000); 532 + 533 + return count; 534 + } 535 + static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO | S_IWUSR, 536 + nouveau_hwmon_emergency_temp, 537 + nouveau_hwmon_set_emergency_temp, 538 + 0); 539 + 540 + static ssize_t 541 + nouveau_hwmon_emergency_temp_hyst(struct device *d, struct device_attribute *a, 542 + char *buf) 543 + { 544 + struct drm_device *dev = dev_get_drvdata(d); 545 + struct nouveau_drm *drm = nouveau_drm(dev); 546 + struct nouveau_therm *therm = nouveau_therm(drm->device); 547 + 548 + return snprintf(buf, PAGE_SIZE, "%d\n", 549 + therm->attr_get(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST) * 1000); 550 + } 551 + static ssize_t 552 + nouveau_hwmon_set_emergency_temp_hyst(struct device *d, 553 + struct device_attribute *a, 554 + const char *buf, 555 + size_t count) 556 + { 557 + struct drm_device *dev = dev_get_drvdata(d); 558 + struct nouveau_drm *drm = nouveau_drm(dev); 559 + struct nouveau_therm *therm = nouveau_therm(drm->device); 560 + long value; 561 + 562 + if (kstrtol(buf, 10, &value) == -EINVAL) 563 + return count; 564 + 565 + therm->attr_set(therm, NOUVEAU_THERM_ATTR_THRS_SHUTDOWN_HYST, 566 + value / 1000); 567 + 568 + return count; 569 + } 570 + static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO | S_IWUSR, 571 + nouveau_hwmon_emergency_temp_hyst, 572 + nouveau_hwmon_set_emergency_temp_hyst, 573 + 0); 574 + 581 575 static ssize_t nouveau_hwmon_show_name(struct device *dev, 582 576 struct device_attribute *attr, 583 577 char *buf) ··· 698 490 NULL, 0); 699 491 700 492 static ssize_t 701 - nouveau_hwmon_show_fan0_input(struct device *d, struct device_attribute *attr, 493 + nouveau_hwmon_show_fan1_input(struct device *d, struct device_attribute *attr, 702 494 char *buf) 703 495 { 704 496 struct drm_device *dev = dev_get_drvdata(d); ··· 707 499 708 500 return snprintf(buf, PAGE_SIZE, "%d\n", therm->fan_sense(therm)); 709 501 } 710 - static SENSOR_DEVICE_ATTR(fan0_input, S_IRUGO, nouveau_hwmon_show_fan0_input, 502 + static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, nouveau_hwmon_show_fan1_input, 711 503 NULL, 0); 712 504 713 505 static ssize_t ··· 873 665 874 666 static struct attribute *hwmon_attributes[] = { 875 667 &sensor_dev_attr_temp1_input.dev_attr.attr, 668 + &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, 669 + &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, 670 + &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr, 876 671 &sensor_dev_attr_temp1_max.dev_attr.attr, 672 + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, 877 673 &sensor_dev_attr_temp1_crit.dev_attr.attr, 674 + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, 675 + &sensor_dev_attr_temp1_emergency.dev_attr.attr, 676 + &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, 878 677 &sensor_dev_attr_name.dev_attr.attr, 879 678 &sensor_dev_attr_update_rate.dev_attr.attr, 880 679 NULL 881 680 }; 882 681 static struct attribute *hwmon_fan_rpm_attributes[] = { 883 - &sensor_dev_attr_fan0_input.dev_attr.attr, 682 + &sensor_dev_attr_fan1_input.dev_attr.attr, 884 683 NULL 885 684 }; 886 685 static struct attribute *hwmon_pwm_fan_attributes[] = { ··· 932 717 dev_set_drvdata(hwmon_dev, dev); 933 718 934 719 /* default sysfs entries */ 935 - ret = sysfs_create_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); 720 + ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup); 936 721 if (ret) { 937 722 if (ret) 938 723 goto error; ··· 943 728 * the gpio entries for pwm fan control even when there's no 944 729 * actual fan connected to it... therm table? */ 945 730 if (therm->fan_get && therm->fan_get(therm) >= 0) { 946 - ret = sysfs_create_group(&dev->pdev->dev.kobj, 731 + ret = sysfs_create_group(&hwmon_dev->kobj, 947 732 &hwmon_pwm_fan_attrgroup); 948 733 if (ret) 949 734 goto error; ··· 951 736 952 737 /* if the card can read the fan rpm */ 953 738 if (therm->fan_sense(therm) >= 0) { 954 - ret = sysfs_create_group(&dev->pdev->dev.kobj, 739 + ret = sysfs_create_group(&hwmon_dev->kobj, 955 740 &hwmon_fan_rpm_attrgroup); 956 741 if (ret) 957 742 goto error; ··· 979 764 struct nouveau_pm *pm = nouveau_pm(dev); 980 765 981 766 if (pm->hwmon) { 982 - sysfs_remove_group(&dev->pdev->dev.kobj, &hwmon_attrgroup); 983 - sysfs_remove_group(&dev->pdev->dev.kobj, 767 + sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); 768 + sysfs_remove_group(&pm->hwmon->kobj, 984 769 &hwmon_pwm_fan_attrgroup); 985 - sysfs_remove_group(&dev->pdev->dev.kobj, 770 + sysfs_remove_group(&pm->hwmon->kobj, 986 771 &hwmon_fan_rpm_attrgroup); 987 772 988 773 hwmon_device_unregister(pm->hwmon);
+2 -2
drivers/gpu/drm/nouveau/nv04_dfp.c
··· 490 490 /* BIOS scripts usually take care of the backlight, thanks 491 491 * Apple for your consistency. 492 492 */ 493 - if (dev->pci_device == 0x0179 || dev->pci_device == 0x0189 || 494 - dev->pci_device == 0x0329) { 493 + if (dev->pci_device == 0x0174 || dev->pci_device == 0x0179 || 494 + dev->pci_device == 0x0189 || dev->pci_device == 0x0329) { 495 495 if (mode == DRM_MODE_DPMS_ON) { 496 496 nv_mask(device, NV_PBUS_DEBUG_DUALHEAD_CTL, 0, 1 << 31); 497 497 nv_mask(device, NV_PCRTC_GPIO_EXT, 3, 1);
+16
drivers/gpu/drm/nouveau/nv04_display.c
··· 22 22 * Author: Ben Skeggs 23 23 */ 24 24 25 + #include <core/object.h> 26 + #include <core/class.h> 27 + 25 28 #include <drm/drmP.h> 26 29 #include <drm/drm_crtc_helper.h> 27 30 ··· 33 30 #include "nouveau_hw.h" 34 31 #include "nouveau_encoder.h" 35 32 #include "nouveau_connector.h" 33 + 34 + #include <subdev/i2c.h> 36 35 37 36 int 38 37 nv04_display_early_init(struct drm_device *dev) ··· 58 53 nv04_display_create(struct drm_device *dev) 59 54 { 60 55 struct nouveau_drm *drm = nouveau_drm(dev); 56 + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 61 57 struct dcb_table *dcb = &drm->vbios.dcb; 62 58 struct drm_connector *connector, *ct; 63 59 struct drm_encoder *encoder; ··· 76 70 nouveau_display(dev)->fini = nv04_display_fini; 77 71 78 72 nouveau_hw_save_vga_fonts(dev, 1); 73 + 74 + ret = nouveau_object_new(nv_object(drm), NVDRM_DEVICE, 0xd1500000, 75 + NV04_DISP_CLASS, NULL, 0, &disp->core); 76 + if (ret) 77 + return ret; 79 78 80 79 nv04_crtc_create(dev, 0); 81 80 if (nv_two_heads(dev)) ··· 123 112 drm_get_connector_name(connector)); 124 113 connector->funcs->destroy(connector); 125 114 } 115 + } 116 + 117 + list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { 118 + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 119 + nv_encoder->i2c = i2c->find(i2c, nv_encoder->dcb->i2c_index); 126 120 } 127 121 128 122 /* Save previous state */
+1
drivers/gpu/drm/nouveau/nv04_display.h
··· 80 80 struct nv04_mode_state saved_reg; 81 81 uint32_t saved_vga_font[4][16384]; 82 82 uint32_t dac_users[4]; 83 + struct nouveau_object *core; 83 84 }; 84 85 85 86 static inline struct nv04_display *
+3 -3
drivers/gpu/drm/nouveau/nv04_fence.c
··· 78 78 struct nv04_fence_chan *fctx = kzalloc(sizeof(*fctx), GFP_KERNEL); 79 79 if (fctx) { 80 80 nouveau_fence_context_new(&fctx->base); 81 + fctx->base.emit = nv04_fence_emit; 82 + fctx->base.sync = nv04_fence_sync; 83 + fctx->base.read = nv04_fence_read; 81 84 chan->fence = fctx; 82 85 return 0; 83 86 } ··· 107 104 priv->base.dtor = nv04_fence_destroy; 108 105 priv->base.context_new = nv04_fence_context_new; 109 106 priv->base.context_del = nv04_fence_context_del; 110 - priv->base.emit = nv04_fence_emit; 111 - priv->base.sync = nv04_fence_sync; 112 - priv->base.read = nv04_fence_read; 113 107 return 0; 114 108 }
+7 -111
drivers/gpu/drm/nouveau/nv10_fence.c
··· 27 27 28 28 #include "nouveau_drm.h" 29 29 #include "nouveau_dma.h" 30 - #include "nouveau_fence.h" 31 - 32 - struct nv10_fence_chan { 33 - struct nouveau_fence_chan base; 34 - }; 35 - 36 - struct nv10_fence_priv { 37 - struct nouveau_fence_priv base; 38 - struct nouveau_bo *bo; 39 - spinlock_t lock; 40 - u32 sequence; 41 - }; 30 + #include "nv10_fence.h" 42 31 43 32 int 44 33 nv10_fence_emit(struct nouveau_fence *fence) ··· 50 61 return -ENODEV; 51 62 } 52 63 53 - int 54 - nv17_fence_sync(struct nouveau_fence *fence, 55 - struct nouveau_channel *prev, struct nouveau_channel *chan) 56 - { 57 - struct nv10_fence_priv *priv = chan->drm->fence; 58 - u32 value; 59 - int ret; 60 - 61 - if (!mutex_trylock(&prev->cli->mutex)) 62 - return -EBUSY; 63 - 64 - spin_lock(&priv->lock); 65 - value = priv->sequence; 66 - priv->sequence += 2; 67 - spin_unlock(&priv->lock); 68 - 69 - ret = RING_SPACE(prev, 5); 70 - if (!ret) { 71 - BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); 72 - OUT_RING (prev, NvSema); 73 - OUT_RING (prev, 0); 74 - OUT_RING (prev, value + 0); 75 - OUT_RING (prev, value + 1); 76 - FIRE_RING (prev); 77 - } 78 - 79 - if (!ret && !(ret = RING_SPACE(chan, 5))) { 80 - BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); 81 - OUT_RING (chan, NvSema); 82 - OUT_RING (chan, 0); 83 - OUT_RING (chan, value + 1); 84 - OUT_RING (chan, value + 2); 85 - FIRE_RING (chan); 86 - } 87 - 88 - mutex_unlock(&prev->cli->mutex); 89 - return 0; 90 - } 91 - 92 64 u32 93 65 nv10_fence_read(struct nouveau_channel *chan) 94 66 { ··· 65 115 kfree(fctx); 66 116 } 67 117 68 - static int 118 + int 69 119 nv10_fence_context_new(struct nouveau_channel *chan) 70 120 { 71 - struct nv10_fence_priv *priv = chan->drm->fence; 72 121 struct nv10_fence_chan *fctx; 73 - int ret = 0; 74 122 75 123 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 76 124 if (!fctx) 77 125 return -ENOMEM; 78 126 79 127 nouveau_fence_context_new(&fctx->base); 80 - 81 - if (priv->bo) { 82 - struct ttm_mem_reg *mem = &priv->bo->bo.mem; 83 - struct nouveau_object *object; 84 - u32 start = mem->start * PAGE_SIZE; 85 - u32 limit = mem->start + mem->size - 1; 86 - 87 - ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 88 - NvSema, 0x0002, 89 - &(struct nv_dma_class) { 90 - .flags = NV_DMA_TARGET_VRAM | 91 - NV_DMA_ACCESS_RDWR, 92 - .start = start, 93 - .limit = limit, 94 - }, sizeof(struct nv_dma_class), 95 - &object); 96 - } 97 - 98 - if (ret) 99 - nv10_fence_context_del(chan); 100 - return ret; 128 + fctx->base.emit = nv10_fence_emit; 129 + fctx->base.read = nv10_fence_read; 130 + fctx->base.sync = nv10_fence_sync; 131 + return 0; 101 132 } 102 133 103 134 void ··· 93 162 kfree(priv); 94 163 } 95 164 96 - void nv17_fence_resume(struct nouveau_drm *drm) 97 - { 98 - struct nv10_fence_priv *priv = drm->fence; 99 - 100 - nouveau_bo_wr32(priv->bo, 0, priv->sequence); 101 - } 102 - 103 165 int 104 166 nv10_fence_create(struct nouveau_drm *drm) 105 167 { 106 168 struct nv10_fence_priv *priv; 107 - int ret = 0; 108 169 109 170 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); 110 171 if (!priv) ··· 105 182 priv->base.dtor = nv10_fence_destroy; 106 183 priv->base.context_new = nv10_fence_context_new; 107 184 priv->base.context_del = nv10_fence_context_del; 108 - priv->base.emit = nv10_fence_emit; 109 - priv->base.read = nv10_fence_read; 110 - priv->base.sync = nv10_fence_sync; 111 185 spin_lock_init(&priv->lock); 112 - 113 - if (nv_device(drm->device)->chipset >= 0x17) { 114 - ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 115 - 0, 0x0000, NULL, &priv->bo); 116 - if (!ret) { 117 - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 118 - if (!ret) { 119 - ret = nouveau_bo_map(priv->bo); 120 - if (ret) 121 - nouveau_bo_unpin(priv->bo); 122 - } 123 - if (ret) 124 - nouveau_bo_ref(NULL, &priv->bo); 125 - } 126 - 127 - if (ret == 0) { 128 - nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); 129 - priv->base.sync = nv17_fence_sync; 130 - priv->base.resume = nv17_fence_resume; 131 - } 132 - } 133 - 134 - if (ret) 135 - nv10_fence_destroy(drm); 136 - return ret; 186 + return 0; 137 187 }
+19
drivers/gpu/drm/nouveau/nv10_fence.h
··· 1 + #ifndef __NV10_FENCE_H_ 2 + #define __NV10_FENCE_H_ 3 + 4 + #include <core/os.h> 5 + #include "nouveau_fence.h" 6 + #include "nouveau_bo.h" 7 + 8 + struct nv10_fence_chan { 9 + struct nouveau_fence_chan base; 10 + }; 11 + 12 + struct nv10_fence_priv { 13 + struct nouveau_fence_priv base; 14 + struct nouveau_bo *bo; 15 + spinlock_t lock; 16 + u32 sequence; 17 + }; 18 + 19 + #endif
+149
drivers/gpu/drm/nouveau/nv17_fence.c
··· 1 + /* 2 + * Copyright 2012 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 + 25 + #include <core/object.h> 26 + #include <core/class.h> 27 + 28 + #include "nouveau_drm.h" 29 + #include "nouveau_dma.h" 30 + #include "nv10_fence.h" 31 + 32 + int 33 + nv17_fence_sync(struct nouveau_fence *fence, 34 + struct nouveau_channel *prev, struct nouveau_channel *chan) 35 + { 36 + struct nv10_fence_priv *priv = chan->drm->fence; 37 + u32 value; 38 + int ret; 39 + 40 + if (!mutex_trylock(&prev->cli->mutex)) 41 + return -EBUSY; 42 + 43 + spin_lock(&priv->lock); 44 + value = priv->sequence; 45 + priv->sequence += 2; 46 + spin_unlock(&priv->lock); 47 + 48 + ret = RING_SPACE(prev, 5); 49 + if (!ret) { 50 + BEGIN_NV04(prev, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); 51 + OUT_RING (prev, NvSema); 52 + OUT_RING (prev, 0); 53 + OUT_RING (prev, value + 0); 54 + OUT_RING (prev, value + 1); 55 + FIRE_RING (prev); 56 + } 57 + 58 + if (!ret && !(ret = RING_SPACE(chan, 5))) { 59 + BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 4); 60 + OUT_RING (chan, NvSema); 61 + OUT_RING (chan, 0); 62 + OUT_RING (chan, value + 1); 63 + OUT_RING (chan, value + 2); 64 + FIRE_RING (chan); 65 + } 66 + 67 + mutex_unlock(&prev->cli->mutex); 68 + return 0; 69 + } 70 + 71 + static int 72 + nv17_fence_context_new(struct nouveau_channel *chan) 73 + { 74 + struct nv10_fence_priv *priv = chan->drm->fence; 75 + struct nv10_fence_chan *fctx; 76 + struct ttm_mem_reg *mem = &priv->bo->bo.mem; 77 + struct nouveau_object *object; 78 + u32 start = mem->start * PAGE_SIZE; 79 + u32 limit = mem->start + mem->size - 1; 80 + int ret = 0; 81 + 82 + fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 83 + if (!fctx) 84 + return -ENOMEM; 85 + 86 + nouveau_fence_context_new(&fctx->base); 87 + fctx->base.emit = nv10_fence_emit; 88 + fctx->base.read = nv10_fence_read; 89 + fctx->base.sync = nv17_fence_sync; 90 + 91 + ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 92 + NvSema, 0x0002, 93 + &(struct nv_dma_class) { 94 + .flags = NV_DMA_TARGET_VRAM | 95 + NV_DMA_ACCESS_RDWR, 96 + .start = start, 97 + .limit = limit, 98 + }, sizeof(struct nv_dma_class), 99 + &object); 100 + if (ret) 101 + nv10_fence_context_del(chan); 102 + return ret; 103 + } 104 + 105 + void 106 + nv17_fence_resume(struct nouveau_drm *drm) 107 + { 108 + struct nv10_fence_priv *priv = drm->fence; 109 + 110 + nouveau_bo_wr32(priv->bo, 0, priv->sequence); 111 + } 112 + 113 + int 114 + nv17_fence_create(struct nouveau_drm *drm) 115 + { 116 + struct nv10_fence_priv *priv; 117 + int ret = 0; 118 + 119 + priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); 120 + if (!priv) 121 + return -ENOMEM; 122 + 123 + priv->base.dtor = nv10_fence_destroy; 124 + priv->base.resume = nv17_fence_resume; 125 + priv->base.context_new = nv17_fence_context_new; 126 + priv->base.context_del = nv10_fence_context_del; 127 + spin_lock_init(&priv->lock); 128 + 129 + ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, 130 + 0, 0x0000, NULL, &priv->bo); 131 + if (!ret) { 132 + ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 133 + if (!ret) { 134 + ret = nouveau_bo_map(priv->bo); 135 + if (ret) 136 + nouveau_bo_unpin(priv->bo); 137 + } 138 + if (ret) 139 + nouveau_bo_ref(NULL, &priv->bo); 140 + } 141 + 142 + if (ret) { 143 + nv10_fence_destroy(drm); 144 + return ret; 145 + } 146 + 147 + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); 148 + return ret; 149 + }
+250 -44
drivers/gpu/drm/nouveau/nv50_display.c
··· 43 43 #include <subdev/timer.h> 44 44 #include <subdev/bar.h> 45 45 #include <subdev/fb.h> 46 + #include <subdev/i2c.h> 46 47 47 48 #define EVO_DMA_NR 9 48 49 ··· 434 433 static bool 435 434 evo_sync_wait(void *data) 436 435 { 437 - return nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000; 436 + if (nouveau_bo_rd32(data, EVO_MAST_NTFY) != 0x00000000) 437 + return true; 438 + usleep_range(1, 2); 439 + return false; 438 440 } 439 441 440 442 static int ··· 516 512 if (ret) 517 513 return ret; 518 514 519 - if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { 515 + if (nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) { 520 516 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); 521 517 OUT_RING (chan, NvEvoSema0 + nv_crtc->index); 522 518 OUT_RING (chan, sync->sem.offset); ··· 526 522 OUT_RING (chan, sync->sem.offset ^ 0x10); 527 523 OUT_RING (chan, 0x74b1e000); 528 524 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 529 - if (nv_mclass(chan->object) < NV84_CHANNEL_DMA_CLASS) 530 - OUT_RING (chan, NvSema); 531 - else 532 - OUT_RING (chan, chan->vram); 525 + OUT_RING (chan, NvSema); 526 + } else 527 + if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { 528 + u64 offset = nv84_fence_crtc(chan, nv_crtc->index); 529 + offset += sync->sem.offset; 530 + 531 + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 532 + OUT_RING (chan, upper_32_bits(offset)); 533 + OUT_RING (chan, lower_32_bits(offset)); 534 + OUT_RING (chan, 0xf00d0000 | sync->sem.value); 535 + OUT_RING (chan, 0x00000002); 536 + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 537 + OUT_RING (chan, upper_32_bits(offset)); 538 + OUT_RING (chan, lower_32_bits(offset ^ 0x10)); 539 + OUT_RING (chan, 0x74b1e000); 540 + OUT_RING (chan, 0x00000001); 533 541 } else { 534 - u64 offset = nvc0_fence_crtc(chan, nv_crtc->index); 542 + u64 offset = nv84_fence_crtc(chan, nv_crtc->index); 535 543 offset += sync->sem.offset; 536 544 537 545 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 538 546 OUT_RING (chan, upper_32_bits(offset)); 539 547 OUT_RING (chan, lower_32_bits(offset)); 540 548 OUT_RING (chan, 0xf00d0000 | sync->sem.value); 541 - OUT_RING (chan, 0x1002); 549 + OUT_RING (chan, 0x00001002); 542 550 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 543 551 OUT_RING (chan, upper_32_bits(offset)); 544 552 OUT_RING (chan, lower_32_bits(offset ^ 0x10)); 545 553 OUT_RING (chan, 0x74b1e000); 546 - OUT_RING (chan, 0x1001); 554 + OUT_RING (chan, 0x00001001); 547 555 } 548 556 549 557 FIRE_RING (chan); ··· 1568 1552 static int 1569 1553 nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) 1570 1554 { 1571 - struct drm_device *dev = connector->dev; 1555 + struct nouveau_drm *drm = nouveau_drm(connector->dev); 1556 + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 1572 1557 struct nouveau_encoder *nv_encoder; 1573 1558 struct drm_encoder *encoder; 1559 + int type = DRM_MODE_ENCODER_DAC; 1574 1560 1575 1561 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 1576 1562 if (!nv_encoder) 1577 1563 return -ENOMEM; 1578 1564 nv_encoder->dcb = dcbe; 1579 1565 nv_encoder->or = ffs(dcbe->or) - 1; 1566 + nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index); 1580 1567 1581 1568 encoder = to_drm_encoder(nv_encoder); 1582 1569 encoder->possible_crtcs = dcbe->heads; 1583 1570 encoder->possible_clones = 0; 1584 - drm_encoder_init(dev, encoder, &nv50_dac_func, DRM_MODE_ENCODER_DAC); 1571 + drm_encoder_init(connector->dev, encoder, &nv50_dac_func, type); 1585 1572 drm_encoder_helper_add(encoder, &nv50_dac_hfunc); 1586 1573 1587 1574 drm_mode_connector_attach_encoder(connector, encoder); ··· 1693 1674 } 1694 1675 1695 1676 nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); 1696 - 1697 - if (nv_encoder->dcb->type == DCB_OUTPUT_DP) 1698 - nouveau_dp_dpms(encoder, mode, nv_encoder->dp.datarate, disp->core); 1699 1677 } 1700 1678 1701 1679 static bool ··· 1746 1730 1747 1731 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 1748 1732 nv_encoder->crtc = NULL; 1749 - } 1750 - 1751 - static void 1752 - nv50_sor_prepare(struct drm_encoder *encoder) 1753 - { 1754 - nv50_sor_disconnect(encoder); 1755 - if (nouveau_encoder(encoder)->dcb->type == DCB_OUTPUT_DP) 1756 - evo_sync(encoder->dev); 1757 1733 } 1758 1734 1759 1735 static void ··· 1843 1835 push = evo_wait(nv50_mast(dev), 8); 1844 1836 if (push) { 1845 1837 if (nv50_vers(mast) < NVD0_DISP_CLASS) { 1838 + u32 ctrl = (depth << 16) | (proto << 8) | owner; 1839 + if (mode->flags & DRM_MODE_FLAG_NHSYNC) 1840 + ctrl |= 0x00001000; 1841 + if (mode->flags & DRM_MODE_FLAG_NVSYNC) 1842 + ctrl |= 0x00002000; 1846 1843 evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1); 1847 - evo_data(push, (depth << 16) | (proto << 8) | owner); 1844 + evo_data(push, ctrl); 1848 1845 } else { 1849 1846 u32 magic = 0x31ec6000 | (nv_crtc->index << 25); 1850 1847 u32 syncs = 0x00000001; ··· 1885 1872 static const struct drm_encoder_helper_funcs nv50_sor_hfunc = { 1886 1873 .dpms = nv50_sor_dpms, 1887 1874 .mode_fixup = nv50_sor_mode_fixup, 1888 - .prepare = nv50_sor_prepare, 1875 + .prepare = nv50_sor_disconnect, 1889 1876 .commit = nv50_sor_commit, 1890 1877 .mode_set = nv50_sor_mode_set, 1891 1878 .disable = nv50_sor_disconnect, ··· 1899 1886 static int 1900 1887 nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) 1901 1888 { 1902 - struct drm_device *dev = connector->dev; 1889 + struct nouveau_drm *drm = nouveau_drm(connector->dev); 1890 + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 1903 1891 struct nouveau_encoder *nv_encoder; 1904 1892 struct drm_encoder *encoder; 1893 + int type; 1894 + 1895 + switch (dcbe->type) { 1896 + case DCB_OUTPUT_LVDS: type = DRM_MODE_ENCODER_LVDS; break; 1897 + case DCB_OUTPUT_TMDS: 1898 + case DCB_OUTPUT_DP: 1899 + default: 1900 + type = DRM_MODE_ENCODER_TMDS; 1901 + break; 1902 + } 1905 1903 1906 1904 nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 1907 1905 if (!nv_encoder) 1908 1906 return -ENOMEM; 1909 1907 nv_encoder->dcb = dcbe; 1910 1908 nv_encoder->or = ffs(dcbe->or) - 1; 1909 + nv_encoder->i2c = i2c->find(i2c, dcbe->i2c_index); 1911 1910 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 1912 1911 1913 1912 encoder = to_drm_encoder(nv_encoder); 1914 1913 encoder->possible_crtcs = dcbe->heads; 1915 1914 encoder->possible_clones = 0; 1916 - drm_encoder_init(dev, encoder, &nv50_sor_func, DRM_MODE_ENCODER_TMDS); 1915 + drm_encoder_init(connector->dev, encoder, &nv50_sor_func, type); 1917 1916 drm_encoder_helper_add(encoder, &nv50_sor_hfunc); 1917 + 1918 + drm_mode_connector_attach_encoder(connector, encoder); 1919 + return 0; 1920 + } 1921 + 1922 + /****************************************************************************** 1923 + * PIOR 1924 + *****************************************************************************/ 1925 + 1926 + static void 1927 + nv50_pior_dpms(struct drm_encoder *encoder, int mode) 1928 + { 1929 + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1930 + struct nv50_disp *disp = nv50_disp(encoder->dev); 1931 + u32 mthd = (nv_encoder->dcb->type << 12) | nv_encoder->or; 1932 + u32 ctrl = (mode == DRM_MODE_DPMS_ON); 1933 + nv_call(disp->core, NV50_DISP_PIOR_PWR + mthd, ctrl); 1934 + } 1935 + 1936 + static bool 1937 + nv50_pior_mode_fixup(struct drm_encoder *encoder, 1938 + const struct drm_display_mode *mode, 1939 + struct drm_display_mode *adjusted_mode) 1940 + { 1941 + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1942 + struct nouveau_connector *nv_connector; 1943 + 1944 + nv_connector = nouveau_encoder_connector_get(nv_encoder); 1945 + if (nv_connector && nv_connector->native_mode) { 1946 + if (nv_connector->scaling_mode != DRM_MODE_SCALE_NONE) { 1947 + int id = adjusted_mode->base.id; 1948 + *adjusted_mode = *nv_connector->native_mode; 1949 + adjusted_mode->base.id = id; 1950 + } 1951 + } 1952 + 1953 + adjusted_mode->clock *= 2; 1954 + return true; 1955 + } 1956 + 1957 + static void 1958 + nv50_pior_commit(struct drm_encoder *encoder) 1959 + { 1960 + } 1961 + 1962 + static void 1963 + nv50_pior_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, 1964 + struct drm_display_mode *adjusted_mode) 1965 + { 1966 + struct nv50_mast *mast = nv50_mast(encoder->dev); 1967 + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1968 + struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 1969 + struct nouveau_connector *nv_connector; 1970 + u8 owner = 1 << nv_crtc->index; 1971 + u8 proto, depth; 1972 + u32 *push; 1973 + 1974 + nv_connector = nouveau_encoder_connector_get(nv_encoder); 1975 + switch (nv_connector->base.display_info.bpc) { 1976 + case 10: depth = 0x6; break; 1977 + case 8: depth = 0x5; break; 1978 + case 6: depth = 0x2; break; 1979 + default: depth = 0x0; break; 1980 + } 1981 + 1982 + switch (nv_encoder->dcb->type) { 1983 + case DCB_OUTPUT_TMDS: 1984 + case DCB_OUTPUT_DP: 1985 + proto = 0x0; 1986 + break; 1987 + default: 1988 + BUG_ON(1); 1989 + break; 1990 + } 1991 + 1992 + nv50_pior_dpms(encoder, DRM_MODE_DPMS_ON); 1993 + 1994 + push = evo_wait(mast, 8); 1995 + if (push) { 1996 + if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { 1997 + u32 ctrl = (depth << 16) | (proto << 8) | owner; 1998 + if (mode->flags & DRM_MODE_FLAG_NHSYNC) 1999 + ctrl |= 0x00001000; 2000 + if (mode->flags & DRM_MODE_FLAG_NVSYNC) 2001 + ctrl |= 0x00002000; 2002 + evo_mthd(push, 0x0700 + (nv_encoder->or * 0x040), 1); 2003 + evo_data(push, ctrl); 2004 + } 2005 + 2006 + evo_kick(push, mast); 2007 + } 2008 + 2009 + nv_encoder->crtc = encoder->crtc; 2010 + } 2011 + 2012 + static void 2013 + nv50_pior_disconnect(struct drm_encoder *encoder) 2014 + { 2015 + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 2016 + struct nv50_mast *mast = nv50_mast(encoder->dev); 2017 + const int or = nv_encoder->or; 2018 + u32 *push; 2019 + 2020 + if (nv_encoder->crtc) { 2021 + nv50_crtc_prepare(nv_encoder->crtc); 2022 + 2023 + push = evo_wait(mast, 4); 2024 + if (push) { 2025 + if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { 2026 + evo_mthd(push, 0x0700 + (or * 0x040), 1); 2027 + evo_data(push, 0x00000000); 2028 + } 2029 + 2030 + evo_mthd(push, 0x0080, 1); 2031 + evo_data(push, 0x00000000); 2032 + evo_kick(push, mast); 2033 + } 2034 + } 2035 + 2036 + nv_encoder->crtc = NULL; 2037 + } 2038 + 2039 + static void 2040 + nv50_pior_destroy(struct drm_encoder *encoder) 2041 + { 2042 + drm_encoder_cleanup(encoder); 2043 + kfree(encoder); 2044 + } 2045 + 2046 + static const struct drm_encoder_helper_funcs nv50_pior_hfunc = { 2047 + .dpms = nv50_pior_dpms, 2048 + .mode_fixup = nv50_pior_mode_fixup, 2049 + .prepare = nv50_pior_disconnect, 2050 + .commit = nv50_pior_commit, 2051 + .mode_set = nv50_pior_mode_set, 2052 + .disable = nv50_pior_disconnect, 2053 + .get_crtc = nv50_display_crtc_get, 2054 + }; 2055 + 2056 + static const struct drm_encoder_funcs nv50_pior_func = { 2057 + .destroy = nv50_pior_destroy, 2058 + }; 2059 + 2060 + static int 2061 + nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) 2062 + { 2063 + struct nouveau_drm *drm = nouveau_drm(connector->dev); 2064 + struct nouveau_i2c *i2c = nouveau_i2c(drm->device); 2065 + struct nouveau_i2c_port *ddc = NULL; 2066 + struct nouveau_encoder *nv_encoder; 2067 + struct drm_encoder *encoder; 2068 + int type; 2069 + 2070 + switch (dcbe->type) { 2071 + case DCB_OUTPUT_TMDS: 2072 + ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(dcbe->extdev)); 2073 + type = DRM_MODE_ENCODER_TMDS; 2074 + break; 2075 + case DCB_OUTPUT_DP: 2076 + ddc = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(dcbe->extdev)); 2077 + type = DRM_MODE_ENCODER_TMDS; 2078 + break; 2079 + default: 2080 + return -ENODEV; 2081 + } 2082 + 2083 + nv_encoder = kzalloc(sizeof(*nv_encoder), GFP_KERNEL); 2084 + if (!nv_encoder) 2085 + return -ENOMEM; 2086 + nv_encoder->dcb = dcbe; 2087 + nv_encoder->or = ffs(dcbe->or) - 1; 2088 + nv_encoder->i2c = ddc; 2089 + 2090 + encoder = to_drm_encoder(nv_encoder); 2091 + encoder->possible_crtcs = dcbe->heads; 2092 + encoder->possible_clones = 0; 2093 + drm_encoder_init(connector->dev, encoder, &nv50_pior_func, type); 2094 + drm_encoder_helper_add(encoder, &nv50_pior_hfunc); 1918 2095 1919 2096 drm_mode_connector_attach_encoder(connector, encoder); 1920 2097 return 0; ··· 2126 1923 evo_mthd(push, 0x0088, 1); 2127 1924 evo_data(push, NvEvoSync); 2128 1925 evo_kick(push, nv50_mast(dev)); 2129 - return evo_sync(dev); 1926 + return 0; 2130 1927 } 2131 1928 2132 1929 return -EBUSY; ··· 2232 2029 if (IS_ERR(connector)) 2233 2030 continue; 2234 2031 2235 - if (dcbe->location != DCB_LOC_ON_CHIP) { 2236 - NV_WARN(drm, "skipping off-chip encoder %d/%d\n", 2237 - dcbe->type, ffs(dcbe->or) - 1); 2238 - continue; 2032 + if (dcbe->location == DCB_LOC_ON_CHIP) { 2033 + switch (dcbe->type) { 2034 + case DCB_OUTPUT_TMDS: 2035 + case DCB_OUTPUT_LVDS: 2036 + case DCB_OUTPUT_DP: 2037 + ret = nv50_sor_create(connector, dcbe); 2038 + break; 2039 + case DCB_OUTPUT_ANALOG: 2040 + ret = nv50_dac_create(connector, dcbe); 2041 + break; 2042 + default: 2043 + ret = -ENODEV; 2044 + break; 2045 + } 2046 + } else { 2047 + ret = nv50_pior_create(connector, dcbe); 2239 2048 } 2240 2049 2241 - switch (dcbe->type) { 2242 - case DCB_OUTPUT_TMDS: 2243 - case DCB_OUTPUT_LVDS: 2244 - case DCB_OUTPUT_DP: 2245 - nv50_sor_create(connector, dcbe); 2246 - break; 2247 - case DCB_OUTPUT_ANALOG: 2248 - nv50_dac_create(connector, dcbe); 2249 - break; 2250 - default: 2251 - NV_WARN(drm, "skipping unsupported encoder %d/%d\n", 2252 - dcbe->type, ffs(dcbe->or) - 1); 2253 - continue; 2050 + if (ret) { 2051 + NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n", 2052 + dcbe->location, dcbe->type, 2053 + ffs(dcbe->or) - 1, ret); 2254 2054 } 2255 2055 } 2256 2056
+12 -24
drivers/gpu/drm/nouveau/nv50_fence.c
··· 27 27 28 28 #include "nouveau_drm.h" 29 29 #include "nouveau_dma.h" 30 - #include "nouveau_fence.h" 30 + #include "nv10_fence.h" 31 31 32 32 #include "nv50_display.h" 33 - 34 - struct nv50_fence_chan { 35 - struct nouveau_fence_chan base; 36 - }; 37 - 38 - struct nv50_fence_priv { 39 - struct nouveau_fence_priv base; 40 - struct nouveau_bo *bo; 41 - spinlock_t lock; 42 - u32 sequence; 43 - }; 44 33 45 34 static int 46 35 nv50_fence_context_new(struct nouveau_channel *chan) 47 36 { 48 37 struct drm_device *dev = chan->drm->dev; 49 - struct nv50_fence_priv *priv = chan->drm->fence; 50 - struct nv50_fence_chan *fctx; 38 + struct nv10_fence_priv *priv = chan->drm->fence; 39 + struct nv10_fence_chan *fctx; 51 40 struct ttm_mem_reg *mem = &priv->bo->bo.mem; 52 41 struct nouveau_object *object; 53 42 int ret, i; ··· 46 57 return -ENOMEM; 47 58 48 59 nouveau_fence_context_new(&fctx->base); 60 + fctx->base.emit = nv10_fence_emit; 61 + fctx->base.read = nv10_fence_read; 62 + fctx->base.sync = nv17_fence_sync; 49 63 50 64 ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 51 65 NvSema, 0x0002, ··· 83 91 int 84 92 nv50_fence_create(struct nouveau_drm *drm) 85 93 { 86 - struct nv50_fence_priv *priv; 94 + struct nv10_fence_priv *priv; 87 95 int ret = 0; 88 96 89 97 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); ··· 91 99 return -ENOMEM; 92 100 93 101 priv->base.dtor = nv10_fence_destroy; 102 + priv->base.resume = nv17_fence_resume; 94 103 priv->base.context_new = nv50_fence_context_new; 95 104 priv->base.context_del = nv10_fence_context_del; 96 - priv->base.emit = nv10_fence_emit; 97 - priv->base.read = nv10_fence_read; 98 - priv->base.sync = nv17_fence_sync; 99 105 spin_lock_init(&priv->lock); 100 106 101 107 ret = nouveau_bo_new(drm->dev, 4096, 0x1000, TTM_PL_FLAG_VRAM, ··· 109 119 nouveau_bo_ref(NULL, &priv->bo); 110 120 } 111 121 112 - if (ret == 0) { 113 - nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); 114 - priv->base.sync = nv17_fence_sync; 115 - priv->base.resume = nv17_fence_resume; 122 + if (ret) { 123 + nv10_fence_destroy(drm); 124 + return ret; 116 125 } 117 126 118 - if (ret) 119 - nv10_fence_destroy(drm); 127 + nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); 120 128 return ret; 121 129 }
+159 -65
drivers/gpu/drm/nouveau/nv84_fence.c
··· 23 23 */ 24 24 25 25 #include <core/object.h> 26 + #include <core/client.h> 26 27 #include <core/class.h> 27 28 28 29 #include <engine/fifo.h> ··· 34 33 35 34 #include "nv50_display.h" 36 35 37 - struct nv84_fence_chan { 38 - struct nouveau_fence_chan base; 39 - }; 40 - 41 - struct nv84_fence_priv { 42 - struct nouveau_fence_priv base; 43 - struct nouveau_gpuobj *mem; 44 - }; 36 + u64 37 + nv84_fence_crtc(struct nouveau_channel *chan, int crtc) 38 + { 39 + struct nv84_fence_chan *fctx = chan->fence; 40 + return fctx->dispc_vma[crtc].offset; 41 + } 45 42 46 43 static int 47 - nv84_fence_emit(struct nouveau_fence *fence) 44 + nv84_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) 48 45 { 49 - struct nouveau_channel *chan = fence->channel; 50 - struct nouveau_fifo_chan *fifo = (void *)chan->object; 51 - int ret = RING_SPACE(chan, 7); 46 + int ret = RING_SPACE(chan, 8); 52 47 if (ret == 0) { 53 48 BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 54 - OUT_RING (chan, NvSema); 55 - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 56 - OUT_RING (chan, upper_32_bits(fifo->chid * 16)); 57 - OUT_RING (chan, lower_32_bits(fifo->chid * 16)); 58 - OUT_RING (chan, fence->sequence); 49 + OUT_RING (chan, chan->vram); 50 + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); 51 + OUT_RING (chan, upper_32_bits(virtual)); 52 + OUT_RING (chan, lower_32_bits(virtual)); 53 + OUT_RING (chan, sequence); 59 54 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 55 + OUT_RING (chan, 0x00000000); 60 56 FIRE_RING (chan); 61 57 } 62 58 return ret; 63 59 } 64 60 61 + static int 62 + nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) 63 + { 64 + int ret = RING_SPACE(chan, 7); 65 + if (ret == 0) { 66 + BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 67 + OUT_RING (chan, chan->vram); 68 + BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 69 + OUT_RING (chan, upper_32_bits(virtual)); 70 + OUT_RING (chan, lower_32_bits(virtual)); 71 + OUT_RING (chan, sequence); 72 + OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL); 73 + FIRE_RING (chan); 74 + } 75 + return ret; 76 + } 77 + 78 + static int 79 + nv84_fence_emit(struct nouveau_fence *fence) 80 + { 81 + struct nouveau_channel *chan = fence->channel; 82 + struct nv84_fence_chan *fctx = chan->fence; 83 + struct nouveau_fifo_chan *fifo = (void *)chan->object; 84 + u64 addr = fifo->chid * 16; 85 + 86 + if (fence->sysmem) 87 + addr += fctx->vma_gart.offset; 88 + else 89 + addr += fctx->vma.offset; 90 + 91 + return fctx->base.emit32(chan, addr, fence->sequence); 92 + } 65 93 66 94 static int 67 95 nv84_fence_sync(struct nouveau_fence *fence, 68 96 struct nouveau_channel *prev, struct nouveau_channel *chan) 69 97 { 98 + struct nv84_fence_chan *fctx = chan->fence; 70 99 struct nouveau_fifo_chan *fifo = (void *)prev->object; 71 - int ret = RING_SPACE(chan, 7); 72 - if (ret == 0) { 73 - BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); 74 - OUT_RING (chan, NvSema); 75 - BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 76 - OUT_RING (chan, upper_32_bits(fifo->chid * 16)); 77 - OUT_RING (chan, lower_32_bits(fifo->chid * 16)); 78 - OUT_RING (chan, fence->sequence); 79 - OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL); 80 - FIRE_RING (chan); 81 - } 82 - return ret; 100 + u64 addr = fifo->chid * 16; 101 + 102 + if (fence->sysmem) 103 + addr += fctx->vma_gart.offset; 104 + else 105 + addr += fctx->vma.offset; 106 + 107 + return fctx->base.sync32(chan, addr, fence->sequence); 83 108 } 84 109 85 110 static u32 ··· 113 86 { 114 87 struct nouveau_fifo_chan *fifo = (void *)chan->object; 115 88 struct nv84_fence_priv *priv = chan->drm->fence; 116 - return nv_ro32(priv->mem, fifo->chid * 16); 89 + return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); 117 90 } 118 91 119 92 static void 120 93 nv84_fence_context_del(struct nouveau_channel *chan) 121 94 { 95 + struct drm_device *dev = chan->drm->dev; 96 + struct nv84_fence_priv *priv = chan->drm->fence; 122 97 struct nv84_fence_chan *fctx = chan->fence; 98 + int i; 99 + 100 + for (i = 0; i < dev->mode_config.num_crtc; i++) { 101 + struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); 102 + nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); 103 + } 104 + 105 + nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); 106 + nouveau_bo_vma_del(priv->bo, &fctx->vma); 123 107 nouveau_fence_context_del(&fctx->base); 124 108 chan->fence = NULL; 125 109 kfree(fctx); 126 110 } 127 111 128 - static int 112 + int 129 113 nv84_fence_context_new(struct nouveau_channel *chan) 130 114 { 131 - struct drm_device *dev = chan->drm->dev; 132 115 struct nouveau_fifo_chan *fifo = (void *)chan->object; 116 + struct nouveau_client *client = nouveau_client(fifo); 133 117 struct nv84_fence_priv *priv = chan->drm->fence; 134 118 struct nv84_fence_chan *fctx; 135 - struct nouveau_object *object; 136 119 int ret, i; 137 120 138 121 fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); ··· 150 113 return -ENOMEM; 151 114 152 115 nouveau_fence_context_new(&fctx->base); 116 + fctx->base.emit = nv84_fence_emit; 117 + fctx->base.sync = nv84_fence_sync; 118 + fctx->base.read = nv84_fence_read; 119 + fctx->base.emit32 = nv84_fence_emit32; 120 + fctx->base.sync32 = nv84_fence_sync32; 153 121 154 - ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 155 - NvSema, 0x0002, 156 - &(struct nv_dma_class) { 157 - .flags = NV_DMA_TARGET_VRAM | 158 - NV_DMA_ACCESS_RDWR, 159 - .start = priv->mem->addr, 160 - .limit = priv->mem->addr + 161 - priv->mem->size - 1, 162 - }, sizeof(struct nv_dma_class), 163 - &object); 164 - 165 - /* dma objects for display sync channel semaphore blocks */ 166 - for (i = 0; !ret && i < dev->mode_config.num_crtc; i++) { 167 - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); 168 - 169 - ret = nouveau_object_new(nv_object(chan->cli), chan->handle, 170 - NvEvoSema0 + i, 0x003d, 171 - &(struct nv_dma_class) { 172 - .flags = NV_DMA_TARGET_VRAM | 173 - NV_DMA_ACCESS_RDWR, 174 - .start = bo->bo.offset, 175 - .limit = bo->bo.offset + 0xfff, 176 - }, sizeof(struct nv_dma_class), 177 - &object); 122 + ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); 123 + if (ret == 0) { 124 + ret = nouveau_bo_vma_add(priv->bo_gart, client->vm, 125 + &fctx->vma_gart); 178 126 } 127 + 128 + /* map display semaphore buffers into channel's vm */ 129 + for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { 130 + struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i); 131 + ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); 132 + } 133 + 134 + nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); 179 135 180 136 if (ret) 181 137 nv84_fence_context_del(chan); 182 - nv_wo32(priv->mem, fifo->chid * 16, 0x00000000); 183 138 return ret; 139 + } 140 + 141 + static bool 142 + nv84_fence_suspend(struct nouveau_drm *drm) 143 + { 144 + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 145 + struct nv84_fence_priv *priv = drm->fence; 146 + int i; 147 + 148 + priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); 149 + if (priv->suspend) { 150 + for (i = 0; i <= pfifo->max; i++) 151 + priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4); 152 + } 153 + 154 + return priv->suspend != NULL; 155 + } 156 + 157 + static void 158 + nv84_fence_resume(struct nouveau_drm *drm) 159 + { 160 + struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 161 + struct nv84_fence_priv *priv = drm->fence; 162 + int i; 163 + 164 + if (priv->suspend) { 165 + for (i = 0; i <= pfifo->max; i++) 166 + nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]); 167 + vfree(priv->suspend); 168 + priv->suspend = NULL; 169 + } 184 170 } 185 171 186 172 static void 187 173 nv84_fence_destroy(struct nouveau_drm *drm) 188 174 { 189 175 struct nv84_fence_priv *priv = drm->fence; 190 - nouveau_gpuobj_ref(NULL, &priv->mem); 176 + nouveau_bo_unmap(priv->bo_gart); 177 + if (priv->bo_gart) 178 + nouveau_bo_unpin(priv->bo_gart); 179 + nouveau_bo_ref(NULL, &priv->bo_gart); 180 + nouveau_bo_unmap(priv->bo); 181 + if (priv->bo) 182 + nouveau_bo_unpin(priv->bo); 183 + nouveau_bo_ref(NULL, &priv->bo); 191 184 drm->fence = NULL; 192 185 kfree(priv); 193 186 } ··· 227 160 { 228 161 struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 229 162 struct nv84_fence_priv *priv; 230 - u32 chan = pfifo->max + 1; 231 163 int ret; 232 164 233 165 priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); ··· 234 168 return -ENOMEM; 235 169 236 170 priv->base.dtor = nv84_fence_destroy; 171 + priv->base.suspend = nv84_fence_suspend; 172 + priv->base.resume = nv84_fence_resume; 237 173 priv->base.context_new = nv84_fence_context_new; 238 174 priv->base.context_del = nv84_fence_context_del; 239 - priv->base.emit = nv84_fence_emit; 240 - priv->base.sync = nv84_fence_sync; 241 - priv->base.read = nv84_fence_read; 242 175 243 - ret = nouveau_gpuobj_new(drm->device, NULL, chan * 16, 0x1000, 0, 244 - &priv->mem); 176 + init_waitqueue_head(&priv->base.waiting); 177 + priv->base.uevent = true; 178 + 179 + ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, 180 + TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); 181 + if (ret == 0) { 182 + ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 183 + if (ret == 0) { 184 + ret = nouveau_bo_map(priv->bo); 185 + if (ret) 186 + nouveau_bo_unpin(priv->bo); 187 + } 188 + if (ret) 189 + nouveau_bo_ref(NULL, &priv->bo); 190 + } 191 + 192 + if (ret == 0) 193 + ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, 194 + TTM_PL_FLAG_TT, 0, 0, NULL, 195 + &priv->bo_gart); 196 + if (ret == 0) { 197 + ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT); 198 + if (ret == 0) { 199 + ret = nouveau_bo_map(priv->bo_gart); 200 + if (ret) 201 + nouveau_bo_unpin(priv->bo_gart); 202 + } 203 + if (ret) 204 + nouveau_bo_ref(NULL, &priv->bo_gart); 205 + } 206 + 245 207 if (ret) 246 208 nv84_fence_destroy(drm); 247 209 return ret;
+20 -166
drivers/gpu/drm/nouveau/nvc0_fence.c
··· 34 34 35 35 #include "nv50_display.h" 36 36 37 - struct nvc0_fence_priv { 38 - struct nouveau_fence_priv base; 39 - struct nouveau_bo *bo; 40 - u32 *suspend; 41 - }; 42 - 43 - struct nvc0_fence_chan { 44 - struct nouveau_fence_chan base; 45 - struct nouveau_vma vma; 46 - struct nouveau_vma dispc_vma[4]; 47 - }; 48 - 49 - u64 50 - nvc0_fence_crtc(struct nouveau_channel *chan, int crtc) 51 - { 52 - struct nvc0_fence_chan *fctx = chan->fence; 53 - return fctx->dispc_vma[crtc].offset; 54 - } 55 - 56 37 static int 57 - nvc0_fence_emit(struct nouveau_fence *fence) 38 + nvc0_fence_emit32(struct nouveau_channel *chan, u64 virtual, u32 sequence) 58 39 { 59 - struct nouveau_channel *chan = fence->channel; 60 - struct nvc0_fence_chan *fctx = chan->fence; 61 - struct nouveau_fifo_chan *fifo = (void *)chan->object; 62 - u64 addr = fctx->vma.offset + fifo->chid * 16; 63 - int ret; 64 - 65 - ret = RING_SPACE(chan, 5); 40 + int ret = RING_SPACE(chan, 6); 66 41 if (ret == 0) { 67 - BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 68 - OUT_RING (chan, upper_32_bits(addr)); 69 - OUT_RING (chan, lower_32_bits(addr)); 70 - OUT_RING (chan, fence->sequence); 42 + BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 5); 43 + OUT_RING (chan, upper_32_bits(virtual)); 44 + OUT_RING (chan, lower_32_bits(virtual)); 45 + OUT_RING (chan, sequence); 71 46 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); 47 + OUT_RING (chan, 0x00000000); 72 48 FIRE_RING (chan); 73 49 } 74 - 75 50 return ret; 76 51 } 77 52 78 53 static int 79 - nvc0_fence_sync(struct nouveau_fence *fence, 80 - struct nouveau_channel *prev, struct nouveau_channel *chan) 54 + nvc0_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence) 81 55 { 82 - struct nvc0_fence_chan *fctx = chan->fence; 83 - struct nouveau_fifo_chan *fifo = (void *)prev->object; 84 - u64 addr = fctx->vma.offset + fifo->chid * 16; 85 - int ret; 86 - 87 - ret = RING_SPACE(chan, 5); 56 + int ret = RING_SPACE(chan, 5); 88 57 if (ret == 0) { 89 58 BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); 90 - OUT_RING (chan, upper_32_bits(addr)); 91 - OUT_RING (chan, lower_32_bits(addr)); 92 - OUT_RING (chan, fence->sequence); 59 + OUT_RING (chan, upper_32_bits(virtual)); 60 + OUT_RING (chan, lower_32_bits(virtual)); 61 + OUT_RING (chan, sequence); 93 62 OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_GEQUAL | 94 63 NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD); 95 64 FIRE_RING (chan); 96 65 } 97 - 98 66 return ret; 99 - } 100 - 101 - static u32 102 - nvc0_fence_read(struct nouveau_channel *chan) 103 - { 104 - struct nouveau_fifo_chan *fifo = (void *)chan->object; 105 - struct nvc0_fence_priv *priv = chan->drm->fence; 106 - return nouveau_bo_rd32(priv->bo, fifo->chid * 16/4); 107 - } 108 - 109 - static void 110 - nvc0_fence_context_del(struct nouveau_channel *chan) 111 - { 112 - struct drm_device *dev = chan->drm->dev; 113 - struct nvc0_fence_priv *priv = chan->drm->fence; 114 - struct nvc0_fence_chan *fctx = chan->fence; 115 - int i; 116 - 117 - for (i = 0; i < dev->mode_config.num_crtc; i++) { 118 - struct nouveau_bo *bo = nv50_display_crtc_sema(dev, i); 119 - nouveau_bo_vma_del(bo, &fctx->dispc_vma[i]); 120 - } 121 - 122 - nouveau_bo_vma_del(priv->bo, &fctx->vma); 123 - nouveau_fence_context_del(&fctx->base); 124 - chan->fence = NULL; 125 - kfree(fctx); 126 67 } 127 68 128 69 static int 129 70 nvc0_fence_context_new(struct nouveau_channel *chan) 130 71 { 131 - struct nouveau_fifo_chan *fifo = (void *)chan->object; 132 - struct nouveau_client *client = nouveau_client(fifo); 133 - struct nvc0_fence_priv *priv = chan->drm->fence; 134 - struct nvc0_fence_chan *fctx; 135 - int ret, i; 136 - 137 - fctx = chan->fence = kzalloc(sizeof(*fctx), GFP_KERNEL); 138 - if (!fctx) 139 - return -ENOMEM; 140 - 141 - nouveau_fence_context_new(&fctx->base); 142 - 143 - ret = nouveau_bo_vma_add(priv->bo, client->vm, &fctx->vma); 144 - if (ret) 145 - nvc0_fence_context_del(chan); 146 - 147 - /* map display semaphore buffers into channel's vm */ 148 - for (i = 0; !ret && i < chan->drm->dev->mode_config.num_crtc; i++) { 149 - struct nouveau_bo *bo = nv50_display_crtc_sema(chan->drm->dev, i); 150 - ret = nouveau_bo_vma_add(bo, client->vm, &fctx->dispc_vma[i]); 72 + int ret = nv84_fence_context_new(chan); 73 + if (ret == 0) { 74 + struct nv84_fence_chan *fctx = chan->fence; 75 + fctx->base.emit32 = nvc0_fence_emit32; 76 + fctx->base.sync32 = nvc0_fence_sync32; 151 77 } 152 - 153 - nouveau_bo_wr32(priv->bo, fifo->chid * 16/4, 0x00000000); 154 78 return ret; 155 - } 156 - 157 - static bool 158 - nvc0_fence_suspend(struct nouveau_drm *drm) 159 - { 160 - struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 161 - struct nvc0_fence_priv *priv = drm->fence; 162 - int i; 163 - 164 - priv->suspend = vmalloc((pfifo->max + 1) * sizeof(u32)); 165 - if (priv->suspend) { 166 - for (i = 0; i <= pfifo->max; i++) 167 - priv->suspend[i] = nouveau_bo_rd32(priv->bo, i); 168 - } 169 - 170 - return priv->suspend != NULL; 171 - } 172 - 173 - static void 174 - nvc0_fence_resume(struct nouveau_drm *drm) 175 - { 176 - struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 177 - struct nvc0_fence_priv *priv = drm->fence; 178 - int i; 179 - 180 - if (priv->suspend) { 181 - for (i = 0; i <= pfifo->max; i++) 182 - nouveau_bo_wr32(priv->bo, i, priv->suspend[i]); 183 - vfree(priv->suspend); 184 - priv->suspend = NULL; 185 - } 186 - } 187 - 188 - static void 189 - nvc0_fence_destroy(struct nouveau_drm *drm) 190 - { 191 - struct nvc0_fence_priv *priv = drm->fence; 192 - nouveau_bo_unmap(priv->bo); 193 - if (priv->bo) 194 - nouveau_bo_unpin(priv->bo); 195 - nouveau_bo_ref(NULL, &priv->bo); 196 - drm->fence = NULL; 197 - kfree(priv); 198 79 } 199 80 200 81 int 201 82 nvc0_fence_create(struct nouveau_drm *drm) 202 83 { 203 - struct nouveau_fifo *pfifo = nouveau_fifo(drm->device); 204 - struct nvc0_fence_priv *priv; 205 - int ret; 206 - 207 - priv = drm->fence = kzalloc(sizeof(*priv), GFP_KERNEL); 208 - if (!priv) 209 - return -ENOMEM; 210 - 211 - priv->base.dtor = nvc0_fence_destroy; 212 - priv->base.suspend = nvc0_fence_suspend; 213 - priv->base.resume = nvc0_fence_resume; 214 - priv->base.context_new = nvc0_fence_context_new; 215 - priv->base.context_del = nvc0_fence_context_del; 216 - priv->base.emit = nvc0_fence_emit; 217 - priv->base.sync = nvc0_fence_sync; 218 - priv->base.read = nvc0_fence_read; 219 - 220 - ret = nouveau_bo_new(drm->dev, 16 * (pfifo->max + 1), 0, 221 - TTM_PL_FLAG_VRAM, 0, 0, NULL, &priv->bo); 84 + int ret = nv84_fence_create(drm); 222 85 if (ret == 0) { 223 - ret = nouveau_bo_pin(priv->bo, TTM_PL_FLAG_VRAM); 224 - if (ret == 0) { 225 - ret = nouveau_bo_map(priv->bo); 226 - if (ret) 227 - nouveau_bo_unpin(priv->bo); 228 - } 229 - if (ret) 230 - nouveau_bo_ref(NULL, &priv->bo); 86 + struct nv84_fence_priv *priv = drm->fence; 87 + priv->base.context_new = nvc0_fence_context_new; 231 88 } 232 - 233 - if (ret) 234 - nvc0_fence_destroy(drm); 235 89 return ret; 236 90 }