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

display rework fixes lots of displayport issues.

* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6: (43 commits)
drm/nouveau/disp/dp: fix tmds passthrough on dp connector
drm/nouveau/dp: probe dpcd to determine connectedness
drm/nv50-: trigger update after all connectors disabled
drm/nv50-: prepare for attaching a SOR to multiple heads
drm/gf119-/disp: fix debug output on update failure
drm/nouveau/disp/dp: make use of postcursor when its available
drm/g94-/disp/dp: take max pullup value across all lanes
drm/nouveau/bios/dp: parse lane postcursor data
drm/nouveau/dp: fix support for dpms
drm/nouveau: register a drm_dp_aux channel for each dp connector
drm/g94-/disp: add method to power-off dp lanes
drm/nouveau/disp/dp: maintain link in response to hpd signal
drm/g94-/disp: bash and wait for something after changing lane power regs
drm/nouveau/disp/dp: split link config/power into two steps
drm/nv50/disp: train PIOR-attached DP from second supervisor
drm/nouveau/disp/dp: make use of existing output data for link training
drm/gf119/disp: start removing direct vbios parsing from supervisor
drm/nv50/disp: start removing direct vbios parsing from supervisor
drm/nouveau/disp/dp: maintain receiver caps in response to hpd signal
drm/nouveau/disp/dp: create subclass for dp outputs
...

+3369 -1509
+8
drivers/gpu/drm/nouveau/Makefile
··· 125 125 nouveau-y += core/subdev/gpio/base.o 126 126 nouveau-y += core/subdev/gpio/nv10.o 127 127 nouveau-y += core/subdev/gpio/nv50.o 128 + nouveau-y += core/subdev/gpio/nv92.o 128 129 nouveau-y += core/subdev/gpio/nvd0.o 129 130 nouveau-y += core/subdev/gpio/nve0.o 130 131 nouveau-y += core/subdev/i2c/base.o 131 132 nouveau-y += core/subdev/i2c/anx9805.o 132 133 nouveau-y += core/subdev/i2c/aux.o 133 134 nouveau-y += core/subdev/i2c/bit.o 135 + nouveau-y += core/subdev/i2c/pad.o 136 + nouveau-y += core/subdev/i2c/padnv04.o 137 + nouveau-y += core/subdev/i2c/padnv94.o 134 138 nouveau-y += core/subdev/i2c/nv04.o 135 139 nouveau-y += core/subdev/i2c/nv4e.o 136 140 nouveau-y += core/subdev/i2c/nv50.o 137 141 nouveau-y += core/subdev/i2c/nv94.o 138 142 nouveau-y += core/subdev/i2c/nvd0.o 143 + nouveau-y += core/subdev/i2c/nve0.o 139 144 nouveau-y += core/subdev/ibus/nvc0.o 140 145 nouveau-y += core/subdev/ibus/nve0.o 141 146 nouveau-y += core/subdev/ibus/gk20a.o ··· 222 217 nouveau-y += core/engine/device/nve0.o 223 218 nouveau-y += core/engine/device/gm100.o 224 219 nouveau-y += core/engine/disp/base.o 220 + nouveau-y += core/engine/disp/conn.o 221 + nouveau-y += core/engine/disp/outp.o 222 + nouveau-y += core/engine/disp/outpdp.o 225 223 nouveau-y += core/engine/disp/nv04.o 226 224 nouveau-y += core/engine/disp/nv50.o 227 225 nouveau-y += core/engine/disp/nv84.o
+58 -25
drivers/gpu/drm/nouveau/core/core/event.c
··· 28 28 { 29 29 struct nouveau_event *event = handler->event; 30 30 unsigned long flags; 31 - if (__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) { 32 - spin_lock_irqsave(&event->refs_lock, flags); 33 - if (!--event->index[handler->index].refs) { 31 + u32 m, t; 32 + 33 + if (!__test_and_clear_bit(NVKM_EVENT_ENABLE, &handler->flags)) 34 + return; 35 + 36 + spin_lock_irqsave(&event->refs_lock, flags); 37 + for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) { 38 + if (!--event->refs[handler->index * event->types_nr + t]) { 34 39 if (event->disable) 35 - event->disable(event, handler->index); 40 + event->disable(event, 1 << t, handler->index); 36 41 } 37 - spin_unlock_irqrestore(&event->refs_lock, flags); 42 + 38 43 } 44 + spin_unlock_irqrestore(&event->refs_lock, flags); 39 45 } 40 46 41 47 void ··· 49 43 { 50 44 struct nouveau_event *event = handler->event; 51 45 unsigned long flags; 52 - if (!__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) { 53 - spin_lock_irqsave(&event->refs_lock, flags); 54 - if (!event->index[handler->index].refs++) { 46 + u32 m, t; 47 + 48 + if (__test_and_set_bit(NVKM_EVENT_ENABLE, &handler->flags)) 49 + return; 50 + 51 + spin_lock_irqsave(&event->refs_lock, flags); 52 + for (m = handler->types; t = __ffs(m), m; m &= ~(1 << t)) { 53 + if (!event->refs[handler->index * event->types_nr + t]++) { 55 54 if (event->enable) 56 - event->enable(event, handler->index); 55 + event->enable(event, 1 << t, handler->index); 57 56 } 58 - spin_unlock_irqrestore(&event->refs_lock, flags); 57 + 59 58 } 59 + spin_unlock_irqrestore(&event->refs_lock, flags); 60 60 } 61 61 62 62 static void ··· 77 65 } 78 66 79 67 static int 80 - nouveau_event_init(struct nouveau_event *event, int index, 81 - int (*func)(void *, int), void *priv, 68 + nouveau_event_init(struct nouveau_event *event, u32 types, int index, 69 + int (*func)(void *, u32, int), void *priv, 82 70 struct nouveau_eventh *handler) 83 71 { 84 72 unsigned long flags; 85 73 74 + if (types & ~((1 << event->types_nr) - 1)) 75 + return -EINVAL; 86 76 if (index >= event->index_nr) 87 77 return -EINVAL; 88 78 89 79 handler->event = event; 90 80 handler->flags = 0; 81 + handler->types = types; 91 82 handler->index = index; 92 83 handler->func = func; 93 84 handler->priv = priv; 94 85 95 86 spin_lock_irqsave(&event->list_lock, flags); 96 - list_add_tail(&handler->head, &event->index[index].list); 87 + list_add_tail(&handler->head, &event->list[index]); 97 88 spin_unlock_irqrestore(&event->list_lock, flags); 98 89 return 0; 99 90 } 100 91 101 92 int 102 - nouveau_event_new(struct nouveau_event *event, int index, 103 - int (*func)(void *, int), void *priv, 93 + nouveau_event_new(struct nouveau_event *event, u32 types, int index, 94 + int (*func)(void *, u32, int), void *priv, 104 95 struct nouveau_eventh **phandler) 105 96 { 106 97 struct nouveau_eventh *handler; 107 98 int ret = -ENOMEM; 108 99 100 + if (event->check) { 101 + ret = event->check(event, types, index); 102 + if (ret) 103 + return ret; 104 + } 105 + 109 106 handler = *phandler = kmalloc(sizeof(*handler), GFP_KERNEL); 110 107 if (handler) { 111 - ret = nouveau_event_init(event, index, func, priv, handler); 108 + ret = nouveau_event_init(event, types, index, func, priv, handler); 112 109 if (ret) 113 110 kfree(handler); 114 111 } ··· 137 116 } 138 117 139 118 void 140 - nouveau_event_trigger(struct nouveau_event *event, int index) 119 + nouveau_event_trigger(struct nouveau_event *event, u32 types, int index) 141 120 { 142 121 struct nouveau_eventh *handler; 143 122 unsigned long flags; ··· 146 125 return; 147 126 148 127 spin_lock_irqsave(&event->list_lock, flags); 149 - list_for_each_entry(handler, &event->index[index].list, head) { 150 - if (test_bit(NVKM_EVENT_ENABLE, &handler->flags) && 151 - handler->func(handler->priv, index) == NVKM_EVENT_DROP) 152 - nouveau_event_put(handler); 128 + list_for_each_entry(handler, &event->list[index], head) { 129 + if (!test_bit(NVKM_EVENT_ENABLE, &handler->flags)) 130 + continue; 131 + if (!(handler->types & types)) 132 + continue; 133 + if (handler->func(handler->priv, handler->types & types, index) 134 + != NVKM_EVENT_DROP) 135 + continue; 136 + nouveau_event_put(handler); 153 137 } 154 138 spin_unlock_irqrestore(&event->list_lock, flags); 155 139 } ··· 170 144 } 171 145 172 146 int 173 - nouveau_event_create(int index_nr, struct nouveau_event **pevent) 147 + nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **pevent) 174 148 { 175 149 struct nouveau_event *event; 176 150 int i; 177 151 178 - event = *pevent = kzalloc(sizeof(*event) + index_nr * 179 - sizeof(event->index[0]), GFP_KERNEL); 152 + event = *pevent = kzalloc(sizeof(*event) + (index_nr * types_nr) * 153 + sizeof(event->refs[0]), GFP_KERNEL); 180 154 if (!event) 181 155 return -ENOMEM; 156 + 157 + event->list = kmalloc(sizeof(*event->list) * index_nr, GFP_KERNEL); 158 + if (!event->list) { 159 + kfree(event); 160 + return -ENOMEM; 161 + } 182 162 183 163 spin_lock_init(&event->list_lock); 184 164 spin_lock_init(&event->refs_lock); 185 165 for (i = 0; i < index_nr; i++) 186 - INIT_LIST_HEAD(&event->index[i].list); 166 + INIT_LIST_HEAD(&event->list[i]); 167 + event->types_nr = types_nr; 187 168 event->index_nr = index_nr; 188 169 return 0; 189 170 }
+2 -2
drivers/gpu/drm/nouveau/core/engine/device/gm100.c
··· 60 60 case 0x117: 61 61 device->cname = "GM107"; 62 62 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 63 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 64 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 63 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 64 + device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; 65 65 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 66 66 #if 0 67 67 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass;
+2 -2
drivers/gpu/drm/nouveau/core/engine/device/nv04.c
··· 47 47 case 0x04: 48 48 device->cname = "NV04"; 49 49 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 50 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 50 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 51 51 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 52 52 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv04_devinit_oclass; 53 53 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 65 65 case 0x05: 66 66 device->cname = "NV05"; 67 67 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 68 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 68 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 69 69 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 70 70 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv05_devinit_oclass; 71 71 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+16 -16
drivers/gpu/drm/nouveau/core/engine/device/nv10.c
··· 48 48 case 0x10: 49 49 device->cname = "NV10"; 50 50 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 51 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 52 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 51 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 52 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 53 53 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 54 54 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 55 55 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 65 65 case 0x15: 66 66 device->cname = "NV15"; 67 67 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 68 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 69 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 68 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 69 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 70 70 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 71 71 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 72 72 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 84 84 case 0x16: 85 85 device->cname = "NV16"; 86 86 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 87 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 88 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 87 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 88 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 89 89 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 90 90 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 91 91 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 103 103 case 0x1a: 104 104 device->cname = "nForce"; 105 105 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 106 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 107 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 106 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 107 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 108 108 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 109 109 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; 110 110 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 122 122 case 0x11: 123 123 device->cname = "NV11"; 124 124 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 125 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 126 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 125 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 126 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 127 127 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 128 128 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 129 129 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 141 141 case 0x17: 142 142 device->cname = "NV17"; 143 143 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 144 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 145 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 144 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 145 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 146 146 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 147 147 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 148 148 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 160 160 case 0x1f: 161 161 device->cname = "nForce2"; 162 162 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 163 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 164 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 163 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 164 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 165 165 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 166 166 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; 167 167 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 179 179 case 0x18: 180 180 device->cname = "NV18"; 181 181 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 182 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 183 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 182 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 183 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 184 184 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 185 185 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 186 186 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+8 -8
drivers/gpu/drm/nouveau/core/engine/device/nv20.c
··· 49 49 case 0x20: 50 50 device->cname = "NV20"; 51 51 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 52 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 53 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 52 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 53 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 54 54 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 55 55 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 56 56 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 68 68 case 0x25: 69 69 device->cname = "NV25"; 70 70 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 71 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 72 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 71 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 72 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 73 73 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 74 74 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 75 75 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 87 87 case 0x28: 88 88 device->cname = "NV28"; 89 89 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 90 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 91 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 90 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 91 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 92 92 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 93 93 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 94 94 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 106 106 case 0x2a: 107 107 device->cname = "NV2A"; 108 108 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 109 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 110 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 109 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 110 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 111 111 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 112 112 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 113 113 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+10 -10
drivers/gpu/drm/nouveau/core/engine/device/nv30.c
··· 49 49 case 0x30: 50 50 device->cname = "NV30"; 51 51 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 52 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 53 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 52 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 53 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 54 54 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 55 55 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 56 56 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 68 68 case 0x35: 69 69 device->cname = "NV35"; 70 70 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 71 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 72 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 71 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 72 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 73 73 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 74 74 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 75 75 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 87 87 case 0x31: 88 88 device->cname = "NV31"; 89 89 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 90 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 91 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 90 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 91 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 92 92 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 93 93 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 94 94 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 107 107 case 0x36: 108 108 device->cname = "NV36"; 109 109 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 110 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 111 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 110 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 111 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 112 112 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 113 113 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv20_devinit_oclass; 114 114 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass; ··· 127 127 case 0x34: 128 128 device->cname = "NV34"; 129 129 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 130 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 131 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 130 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 131 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 132 132 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv04_clock_oclass; 133 133 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv10_devinit_oclass; 134 134 device->oclass[NVDEV_SUBDEV_MC ] = nv04_mc_oclass;
+32 -32
drivers/gpu/drm/nouveau/core/engine/device/nv40.c
··· 53 53 case 0x40: 54 54 device->cname = "NV40"; 55 55 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 56 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 57 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 56 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 57 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 58 58 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 59 59 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 60 60 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 76 76 case 0x41: 77 77 device->cname = "NV41"; 78 78 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 79 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 80 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 79 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 80 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 81 81 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 82 82 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 83 83 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 99 99 case 0x42: 100 100 device->cname = "NV42"; 101 101 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 102 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 103 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 102 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 103 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 104 104 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 105 105 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 106 106 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 122 122 case 0x43: 123 123 device->cname = "NV43"; 124 124 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 125 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 126 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 125 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 126 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 127 127 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 128 128 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 129 129 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 145 145 case 0x45: 146 146 device->cname = "NV45"; 147 147 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 148 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 149 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 148 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 149 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 150 150 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 151 151 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 152 152 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 168 168 case 0x47: 169 169 device->cname = "G70"; 170 170 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 171 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 172 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 171 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 172 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 173 173 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 174 174 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 175 175 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 191 191 case 0x49: 192 192 device->cname = "G71"; 193 193 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 194 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 195 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 194 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 195 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 196 196 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 197 197 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 198 198 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 214 214 case 0x4b: 215 215 device->cname = "G73"; 216 216 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 217 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 218 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 217 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 218 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 219 219 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 220 220 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 221 221 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 237 237 case 0x44: 238 238 device->cname = "NV44"; 239 239 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 240 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 241 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 240 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 241 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 242 242 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 243 243 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 244 244 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 260 260 case 0x46: 261 261 device->cname = "G72"; 262 262 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 263 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 264 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 263 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 264 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 265 265 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 266 266 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 267 267 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 283 283 case 0x4a: 284 284 device->cname = "NV44A"; 285 285 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 286 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 287 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 286 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 287 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 288 288 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 289 289 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 290 290 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 306 306 case 0x4c: 307 307 device->cname = "C61"; 308 308 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 309 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 310 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 309 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 310 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 311 311 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 312 312 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 313 313 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 329 329 case 0x4e: 330 330 device->cname = "C51"; 331 331 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 332 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 333 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv4e_i2c_oclass; 332 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 333 + device->oclass[NVDEV_SUBDEV_I2C ] = nv4e_i2c_oclass; 334 334 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 335 335 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 336 336 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 352 352 case 0x63: 353 353 device->cname = "C73"; 354 354 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 355 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 356 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 355 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 356 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 357 357 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 358 358 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 359 359 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 375 375 case 0x67: 376 376 device->cname = "C67"; 377 377 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 378 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 379 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 378 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 379 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 380 380 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 381 381 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 382 382 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass; ··· 398 398 case 0x68: 399 399 device->cname = "C68"; 400 400 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 401 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv10_gpio_oclass; 402 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv04_i2c_oclass; 401 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv10_gpio_oclass; 402 + device->oclass[NVDEV_SUBDEV_I2C ] = nv04_i2c_oclass; 403 403 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nv40_clock_oclass; 404 404 device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass; 405 405 device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
+28 -28
drivers/gpu/drm/nouveau/core/engine/device/nv50.c
··· 60 60 case 0x50: 61 61 device->cname = "G80"; 62 62 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 63 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 64 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 63 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; 64 + device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; 65 65 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv50_clock_oclass; 66 66 device->oclass[NVDEV_SUBDEV_THERM ] = &nv50_therm_oclass; 67 67 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 85 85 case 0x84: 86 86 device->cname = "G84"; 87 87 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 88 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 89 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 88 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; 89 + device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; 90 90 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 91 91 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 92 92 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 113 113 case 0x86: 114 114 device->cname = "G86"; 115 115 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 116 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 117 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 116 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv50_gpio_oclass; 117 + device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; 118 118 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 119 119 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 120 120 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 141 141 case 0x92: 142 142 device->cname = "G92"; 143 143 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 144 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 145 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 144 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 145 + device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; 146 146 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 147 147 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 148 148 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 169 169 case 0x94: 170 170 device->cname = "G94"; 171 171 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 172 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 173 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 172 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 173 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 174 174 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 175 175 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 176 176 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 197 197 case 0x96: 198 198 device->cname = "G96"; 199 199 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 200 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 201 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 200 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 201 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 202 202 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 203 203 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 204 204 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 225 225 case 0x98: 226 226 device->cname = "G98"; 227 227 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 228 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 229 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 228 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 229 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 230 230 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 231 231 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 232 232 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 253 253 case 0xa0: 254 254 device->cname = "G200"; 255 255 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 256 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 257 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv50_i2c_oclass; 256 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 257 + device->oclass[NVDEV_SUBDEV_I2C ] = nv50_i2c_oclass; 258 258 device->oclass[NVDEV_SUBDEV_CLOCK ] = nv84_clock_oclass; 259 259 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 260 260 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 281 281 case 0xaa: 282 282 device->cname = "MCP77/MCP78"; 283 283 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 284 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 285 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 284 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 285 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 286 286 device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass; 287 287 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 288 288 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 309 309 case 0xac: 310 310 device->cname = "MCP79/MCP7A"; 311 311 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 312 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 313 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 312 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 313 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 314 314 device->oclass[NVDEV_SUBDEV_CLOCK ] = nvaa_clock_oclass; 315 315 device->oclass[NVDEV_SUBDEV_THERM ] = &nv84_therm_oclass; 316 316 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 337 337 case 0xa3: 338 338 device->cname = "GT215"; 339 339 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 340 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 341 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 340 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 341 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 342 342 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 343 343 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 344 344 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 367 367 case 0xa5: 368 368 device->cname = "GT216"; 369 369 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 370 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 371 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 370 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 371 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 372 372 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 373 373 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 374 374 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 396 396 case 0xa8: 397 397 device->cname = "GT218"; 398 398 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 399 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 400 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 399 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 400 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 401 401 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 402 402 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 403 403 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 425 425 case 0xaf: 426 426 device->cname = "MCP89"; 427 427 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 428 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 429 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 428 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 429 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 430 430 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nva3_clock_oclass; 431 431 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 432 432 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+18 -18
drivers/gpu/drm/nouveau/core/engine/device/nvc0.c
··· 60 60 case 0xc0: 61 61 device->cname = "GF100"; 62 62 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 63 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 64 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 63 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 64 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 65 65 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 66 66 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 67 67 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 92 92 case 0xc4: 93 93 device->cname = "GF104"; 94 94 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 95 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 96 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 95 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 96 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 97 97 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 98 98 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 99 99 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 124 124 case 0xc3: 125 125 device->cname = "GF106"; 126 126 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 127 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 128 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 127 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 128 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 129 129 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 130 130 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 131 131 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 155 155 case 0xce: 156 156 device->cname = "GF114"; 157 157 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 158 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 159 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 158 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 159 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 160 160 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 161 161 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 162 162 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 187 187 case 0xcf: 188 188 device->cname = "GF116"; 189 189 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 190 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 191 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 190 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 191 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 192 192 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 193 193 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 194 194 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 219 219 case 0xc1: 220 220 device->cname = "GF108"; 221 221 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 222 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 223 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 222 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 223 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 224 224 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 225 225 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 226 226 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 250 250 case 0xc8: 251 251 device->cname = "GF110"; 252 252 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 253 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nv50_gpio_oclass; 254 - device->oclass[NVDEV_SUBDEV_I2C ] = &nv94_i2c_oclass; 253 + device->oclass[NVDEV_SUBDEV_GPIO ] = nv92_gpio_oclass; 254 + device->oclass[NVDEV_SUBDEV_I2C ] = nv94_i2c_oclass; 255 255 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 256 256 device->oclass[NVDEV_SUBDEV_THERM ] = &nva3_therm_oclass; 257 257 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 282 282 case 0xd9: 283 283 device->cname = "GF119"; 284 284 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 285 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 286 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 285 + device->oclass[NVDEV_SUBDEV_GPIO ] = nvd0_gpio_oclass; 286 + device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; 287 287 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 288 288 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 289 289 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 313 313 case 0xd7: 314 314 device->cname = "GF117"; 315 315 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 316 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nvd0_gpio_oclass; 317 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 316 + device->oclass[NVDEV_SUBDEV_GPIO ] = nvd0_gpio_oclass; 317 + device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; 318 318 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nvc0_clock_oclass; 319 319 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 320 320 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+12 -12
drivers/gpu/drm/nouveau/core/engine/device/nve0.c
··· 60 60 case 0xe4: 61 61 device->cname = "GK104"; 62 62 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 63 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 64 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 63 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 64 + device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; 65 65 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 66 66 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 67 67 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 93 93 case 0xe7: 94 94 device->cname = "GK107"; 95 95 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 96 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 97 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 96 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 97 + device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; 98 98 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 99 99 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 100 100 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 126 126 case 0xe6: 127 127 device->cname = "GK106"; 128 128 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 129 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 130 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 129 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 130 + device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; 131 131 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 132 132 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 133 133 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 176 176 case 0xf0: 177 177 device->cname = "GK110"; 178 178 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 179 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 180 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 179 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 180 + device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; 181 181 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 182 182 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 183 183 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 209 209 case 0xf1: 210 210 device->cname = "GK110B"; 211 211 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 212 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 213 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 212 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 213 + device->oclass[NVDEV_SUBDEV_I2C ] = nvd0_i2c_oclass; 214 214 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 215 215 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 216 216 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass; ··· 242 242 case 0x108: 243 243 device->cname = "GK208"; 244 244 device->oclass[NVDEV_SUBDEV_VBIOS ] = &nouveau_bios_oclass; 245 - device->oclass[NVDEV_SUBDEV_GPIO ] = &nve0_gpio_oclass; 246 - device->oclass[NVDEV_SUBDEV_I2C ] = &nvd0_i2c_oclass; 245 + device->oclass[NVDEV_SUBDEV_GPIO ] = nve0_gpio_oclass; 246 + device->oclass[NVDEV_SUBDEV_I2C ] = nve0_i2c_oclass; 247 247 device->oclass[NVDEV_SUBDEV_CLOCK ] = &nve0_clock_oclass; 248 248 device->oclass[NVDEV_SUBDEV_THERM ] = &nvd0_therm_oclass; 249 249 device->oclass[NVDEV_SUBDEV_MXM ] = &nv50_mxm_oclass;
+121 -3
drivers/gpu/drm/nouveau/core/engine/disp/base.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <engine/disp.h> 25 + #include "priv.h" 26 + #include "outp.h" 27 + #include "conn.h" 28 + 29 + static int 30 + nouveau_disp_hpd_check(struct nouveau_event *event, u32 types, int index) 31 + { 32 + struct nouveau_disp *disp = event->priv; 33 + struct nvkm_output *outp; 34 + list_for_each_entry(outp, &disp->outp, head) { 35 + if (outp->conn->index == index) { 36 + if (outp->conn->hpd.event) 37 + return 0; 38 + break; 39 + } 40 + } 41 + return -ENOSYS; 42 + } 43 + 44 + int 45 + _nouveau_disp_fini(struct nouveau_object *object, bool suspend) 46 + { 47 + struct nouveau_disp *disp = (void *)object; 48 + struct nvkm_output *outp; 49 + int ret; 50 + 51 + list_for_each_entry(outp, &disp->outp, head) { 52 + ret = nv_ofuncs(outp)->fini(nv_object(outp), suspend); 53 + if (ret && suspend) 54 + goto fail_outp; 55 + } 56 + 57 + return nouveau_engine_fini(&disp->base, suspend); 58 + 59 + fail_outp: 60 + list_for_each_entry_continue_reverse(outp, &disp->outp, head) { 61 + nv_ofuncs(outp)->init(nv_object(outp)); 62 + } 63 + 64 + return ret; 65 + } 66 + 67 + int 68 + _nouveau_disp_init(struct nouveau_object *object) 69 + { 70 + struct nouveau_disp *disp = (void *)object; 71 + struct nvkm_output *outp; 72 + int ret; 73 + 74 + ret = nouveau_engine_init(&disp->base); 75 + if (ret) 76 + return ret; 77 + 78 + list_for_each_entry(outp, &disp->outp, head) { 79 + ret = nv_ofuncs(outp)->init(nv_object(outp)); 80 + if (ret) 81 + goto fail_outp; 82 + } 83 + 84 + return ret; 85 + 86 + fail_outp: 87 + list_for_each_entry_continue_reverse(outp, &disp->outp, head) { 88 + nv_ofuncs(outp)->fini(nv_object(outp), false); 89 + } 90 + 91 + return ret; 92 + } 26 93 27 94 void 28 95 _nouveau_disp_dtor(struct nouveau_object *object) 29 96 { 30 97 struct nouveau_disp *disp = (void *)object; 98 + struct nvkm_output *outp, *outt; 99 + 31 100 nouveau_event_destroy(&disp->vblank); 101 + 102 + list_for_each_entry_safe(outp, outt, &disp->outp, head) { 103 + nouveau_object_ref(NULL, (struct nouveau_object **)&outp); 104 + } 105 + 32 106 nouveau_engine_destroy(&disp->base); 33 107 } 34 108 ··· 113 39 const char *intname, const char *extname, 114 40 int length, void **pobject) 115 41 { 42 + struct nouveau_disp_impl *impl = (void *)oclass; 43 + struct nouveau_bios *bios = nouveau_bios(parent); 116 44 struct nouveau_disp *disp; 117 - int ret; 45 + struct nouveau_oclass **sclass; 46 + struct nouveau_object *object; 47 + struct dcb_output dcbE; 48 + u8 hpd = 0, ver, hdr; 49 + u32 data; 50 + int ret, i; 118 51 119 52 ret = nouveau_engine_create_(parent, engine, oclass, true, 120 53 intname, extname, length, pobject); ··· 129 48 if (ret) 130 49 return ret; 131 50 132 - return nouveau_event_create(heads, &disp->vblank); 51 + INIT_LIST_HEAD(&disp->outp); 52 + 53 + /* create output objects for each display path in the vbios */ 54 + i = -1; 55 + while ((data = dcb_outp_parse(bios, ++i, &ver, &hdr, &dcbE))) { 56 + if (dcbE.type == DCB_OUTPUT_UNUSED) 57 + continue; 58 + if (dcbE.type == DCB_OUTPUT_EOL) 59 + break; 60 + data = dcbE.location << 4 | dcbE.type; 61 + 62 + oclass = nvkm_output_oclass; 63 + sclass = impl->outp; 64 + while (sclass && sclass[0]) { 65 + if (sclass[0]->handle == data) { 66 + oclass = sclass[0]; 67 + break; 68 + } 69 + sclass++; 70 + } 71 + 72 + nouveau_object_ctor(*pobject, *pobject, oclass, 73 + &dcbE, i, &object); 74 + hpd = max(hpd, (u8)(dcbE.connector + 1)); 75 + } 76 + 77 + ret = nouveau_event_create(3, hpd, &disp->hpd); 78 + if (ret) 79 + return ret; 80 + 81 + disp->hpd->priv = disp; 82 + disp->hpd->check = nouveau_disp_hpd_check; 83 + 84 + ret = nouveau_event_create(1, heads, &disp->vblank); 85 + if (ret) 86 + return ret; 87 + 88 + return 0; 133 89 }
+172
drivers/gpu/drm/nouveau/core/engine/disp/conn.c
··· 1 + /* 2 + * Copyright 2014 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 "conn.h" 28 + #include "outp.h" 29 + 30 + static void 31 + nvkm_connector_hpd_work(struct work_struct *w) 32 + { 33 + struct nvkm_connector *conn = container_of(w, typeof(*conn), hpd.work); 34 + struct nouveau_disp *disp = nouveau_disp(conn); 35 + struct nouveau_gpio *gpio = nouveau_gpio(conn); 36 + u32 send = NVKM_HPD_UNPLUG; 37 + if (gpio->get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.event->index)) 38 + send = NVKM_HPD_PLUG; 39 + nouveau_event_trigger(disp->hpd, send, conn->index); 40 + nouveau_event_get(conn->hpd.event); 41 + } 42 + 43 + static int 44 + nvkm_connector_hpd(void *data, u32 type, int index) 45 + { 46 + struct nvkm_connector *conn = data; 47 + DBG("HPD: %d\n", type); 48 + schedule_work(&conn->hpd.work); 49 + return NVKM_EVENT_DROP; 50 + } 51 + 52 + int 53 + _nvkm_connector_fini(struct nouveau_object *object, bool suspend) 54 + { 55 + struct nvkm_connector *conn = (void *)object; 56 + if (conn->hpd.event) 57 + nouveau_event_put(conn->hpd.event); 58 + return nouveau_object_fini(&conn->base, suspend); 59 + } 60 + 61 + int 62 + _nvkm_connector_init(struct nouveau_object *object) 63 + { 64 + struct nvkm_connector *conn = (void *)object; 65 + int ret = nouveau_object_init(&conn->base); 66 + if (ret == 0) { 67 + if (conn->hpd.event) 68 + nouveau_event_get(conn->hpd.event); 69 + } 70 + return ret; 71 + } 72 + 73 + void 74 + _nvkm_connector_dtor(struct nouveau_object *object) 75 + { 76 + struct nvkm_connector *conn = (void *)object; 77 + nouveau_event_ref(NULL, &conn->hpd.event); 78 + nouveau_object_destroy(&conn->base); 79 + } 80 + 81 + int 82 + nvkm_connector_create_(struct nouveau_object *parent, 83 + struct nouveau_object *engine, 84 + struct nouveau_oclass *oclass, 85 + struct nvbios_connE *info, int index, 86 + int length, void **pobject) 87 + { 88 + static const u8 hpd[] = { 0x07, 0x08, 0x51, 0x52, 0x5e, 0x5f, 0x60 }; 89 + struct nouveau_gpio *gpio = nouveau_gpio(parent); 90 + struct nouveau_disp *disp = (void *)engine; 91 + struct nvkm_connector *conn; 92 + struct nvkm_output *outp; 93 + struct dcb_gpio_func func; 94 + int ret; 95 + 96 + list_for_each_entry(outp, &disp->outp, head) { 97 + if (outp->conn && outp->conn->index == index) { 98 + atomic_inc(&nv_object(outp->conn)->refcount); 99 + *pobject = outp->conn; 100 + return 1; 101 + } 102 + } 103 + 104 + ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject); 105 + conn = *pobject; 106 + if (ret) 107 + return ret; 108 + 109 + conn->info = *info; 110 + conn->index = index; 111 + 112 + DBG("type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x\n", 113 + info->type, info->location, info->hpd, info->dp, 114 + info->di, info->sr, info->lcdid); 115 + 116 + if ((info->hpd = ffs(info->hpd))) { 117 + if (--info->hpd >= ARRAY_SIZE(hpd)) { 118 + ERR("hpd %02x unknown\n", info->hpd); 119 + goto done; 120 + } 121 + info->hpd = hpd[info->hpd]; 122 + 123 + ret = gpio->find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); 124 + if (ret) { 125 + ERR("func %02x lookup failed, %d\n", info->hpd, ret); 126 + goto done; 127 + } 128 + 129 + ret = nouveau_event_new(gpio->events, NVKM_GPIO_TOGGLED, 130 + func.line, nvkm_connector_hpd, 131 + conn, &conn->hpd.event); 132 + if (ret) { 133 + ERR("func %02x failed, %d\n", info->hpd, ret); 134 + } else { 135 + DBG("func %02x (HPD)\n", info->hpd); 136 + } 137 + } 138 + 139 + done: 140 + INIT_WORK(&conn->hpd.work, nvkm_connector_hpd_work); 141 + return 0; 142 + } 143 + 144 + int 145 + _nvkm_connector_ctor(struct nouveau_object *parent, 146 + struct nouveau_object *engine, 147 + struct nouveau_oclass *oclass, void *info, u32 index, 148 + struct nouveau_object **pobject) 149 + { 150 + struct nvkm_connector *conn; 151 + int ret; 152 + 153 + ret = nvkm_connector_create(parent, engine, oclass, info, index, &conn); 154 + *pobject = nv_object(conn); 155 + if (ret) 156 + return ret; 157 + 158 + return 0; 159 + } 160 + 161 + struct nouveau_oclass * 162 + nvkm_connector_oclass = &(struct nvkm_connector_impl) { 163 + .base = { 164 + .handle = 0, 165 + .ofuncs = &(struct nouveau_ofuncs) { 166 + .ctor = _nvkm_connector_ctor, 167 + .dtor = _nvkm_connector_dtor, 168 + .init = _nvkm_connector_init, 169 + .fini = _nvkm_connector_fini, 170 + }, 171 + }, 172 + }.base;
+59
drivers/gpu/drm/nouveau/core/engine/disp/conn.h
··· 1 + #ifndef __NVKM_DISP_CONN_H__ 2 + #define __NVKM_DISP_CONN_H__ 3 + 4 + #include "priv.h" 5 + 6 + struct nvkm_connector { 7 + struct nouveau_object base; 8 + struct list_head head; 9 + 10 + struct nvbios_connE info; 11 + int index; 12 + 13 + struct { 14 + struct nouveau_eventh *event; 15 + struct work_struct work; 16 + } hpd; 17 + }; 18 + 19 + #define nvkm_connector_create(p,e,c,b,i,d) \ 20 + nvkm_connector_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) 21 + #define nvkm_connector_destroy(d) ({ \ 22 + struct nvkm_connector *disp = (d); \ 23 + _nvkm_connector_dtor(nv_object(disp)); \ 24 + }) 25 + #define nvkm_connector_init(d) ({ \ 26 + struct nvkm_connector *disp = (d); \ 27 + _nvkm_connector_init(nv_object(disp)); \ 28 + }) 29 + #define nvkm_connector_fini(d,s) ({ \ 30 + struct nvkm_connector *disp = (d); \ 31 + _nvkm_connector_fini(nv_object(disp), (s)); \ 32 + }) 33 + 34 + int nvkm_connector_create_(struct nouveau_object *, struct nouveau_object *, 35 + struct nouveau_oclass *, struct nvbios_connE *, 36 + int, int, void **); 37 + 38 + int _nvkm_connector_ctor(struct nouveau_object *, struct nouveau_object *, 39 + struct nouveau_oclass *, void *, u32, 40 + struct nouveau_object **); 41 + void _nvkm_connector_dtor(struct nouveau_object *); 42 + int _nvkm_connector_init(struct nouveau_object *); 43 + int _nvkm_connector_fini(struct nouveau_object *, bool); 44 + 45 + struct nvkm_connector_impl { 46 + struct nouveau_oclass base; 47 + }; 48 + 49 + #ifndef MSG 50 + #define MSG(l,f,a...) do { \ 51 + struct nvkm_connector *_conn = (void *)conn; \ 52 + nv_##l(nv_object(conn)->engine, "%02x:%02x%02x: "f, _conn->index, \ 53 + _conn->info.location, _conn->info.type, ##a); \ 54 + } while(0) 55 + #define DBG(f,a...) MSG(debug, f, ##a) 56 + #define ERR(f,a...) MSG(error, f, ##a) 57 + #endif 58 + 59 + #endif
+164 -144
drivers/gpu/drm/nouveau/core/engine/disp/dport.c
··· 30 30 31 31 #include <engine/disp.h> 32 32 33 - #include "dport.h" 33 + #include <core/class.h> 34 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) 35 + #include "dport.h" 36 + #include "outpdp.h" 39 37 40 38 /****************************************************************************** 41 39 * link training 42 40 *****************************************************************************/ 43 41 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[16]; 42 + struct nvkm_output_dp *outp; 52 43 int link_nr; 53 44 u32 link_bw; 54 45 u8 stat[6]; 55 46 u8 conf[4]; 47 + bool pc2; 48 + u8 pc2stat; 49 + u8 pc2conf[2]; 56 50 }; 57 51 58 52 static int 59 53 dp_set_link_config(struct dp_state *dp) 60 54 { 61 - struct nouveau_disp *disp = dp->disp; 55 + struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); 56 + struct nvkm_output_dp *outp = dp->outp; 57 + struct nouveau_disp *disp = nouveau_disp(outp); 62 58 struct nouveau_bios *bios = nouveau_bios(disp); 63 59 struct nvbios_init init = { 64 - .subdev = nv_subdev(dp->disp), 60 + .subdev = nv_subdev(disp), 65 61 .bios = bios, 66 62 .offset = 0x0000, 67 - .outp = dp->outp, 68 - .crtc = dp->head, 63 + .outp = &outp->base.info, 64 + .crtc = -1, 69 65 .execute = 1, 70 66 }; 71 67 u32 lnkcmp; ··· 71 75 DBG("%d lanes at %d KB/s\n", dp->link_nr, dp->link_bw); 72 76 73 77 /* set desired link configuration on the source */ 74 - if ((lnkcmp = dp->info.lnkcmp)) { 75 - if (dp->version < 0x30) { 78 + if ((lnkcmp = dp->outp->info.lnkcmp)) { 79 + if (outp->version < 0x30) { 76 80 while ((dp->link_bw / 10) < nv_ro16(bios, lnkcmp)) 77 81 lnkcmp += 4; 78 82 init.offset = nv_ro16(bios, lnkcmp + 2); ··· 85 89 nvbios_exec(&init); 86 90 } 87 91 88 - ret = dp->func->lnk_ctl(dp->disp, dp->outp, dp->head, 89 - dp->link_nr, dp->link_bw / 27000, 90 - dp->dpcd[DPCD_RC02] & 91 - DPCD_RC02_ENHANCED_FRAME_CAP); 92 + ret = impl->lnk_ctl(outp, dp->link_nr, dp->link_bw / 27000, 93 + outp->dpcd[DPCD_RC02] & 94 + DPCD_RC02_ENHANCED_FRAME_CAP); 92 95 if (ret) { 93 - ERR("lnk_ctl failed with %d\n", ret); 96 + if (ret < 0) 97 + ERR("lnk_ctl failed with %d\n", ret); 94 98 return ret; 95 99 } 100 + 101 + impl->lnk_pwr(outp, dp->link_nr); 96 102 97 103 /* set desired link configuration on the sink */ 98 104 sink[0] = dp->link_bw / 27000; 99 105 sink[1] = dp->link_nr; 100 - if (dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) 106 + if (outp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP) 101 107 sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; 102 108 103 - return nv_wraux(dp->aux, DPCD_LC00, sink, 2); 109 + return nv_wraux(outp->base.edid, DPCD_LC00_LINK_BW_SET, sink, 2); 104 110 } 105 111 106 112 static void 107 113 dp_set_training_pattern(struct dp_state *dp, u8 pattern) 108 114 { 115 + struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); 116 + struct nvkm_output_dp *outp = dp->outp; 109 117 u8 sink_tp; 110 118 111 119 DBG("training pattern %d\n", pattern); 112 - dp->func->pattern(dp->disp, dp->outp, dp->head, pattern); 120 + impl->pattern(outp, pattern); 113 121 114 - nv_rdaux(dp->aux, DPCD_LC02, &sink_tp, 1); 122 + nv_rdaux(outp->base.edid, DPCD_LC02, &sink_tp, 1); 115 123 sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; 116 124 sink_tp |= pattern; 117 - nv_wraux(dp->aux, DPCD_LC02, &sink_tp, 1); 125 + nv_wraux(outp->base.edid, DPCD_LC02, &sink_tp, 1); 118 126 } 119 127 120 128 static int 121 - dp_link_train_commit(struct dp_state *dp) 129 + dp_link_train_commit(struct dp_state *dp, bool pc) 122 130 { 123 - int i; 131 + struct nvkm_output_dp_impl *impl = (void *)nv_oclass(dp->outp); 132 + struct nvkm_output_dp *outp = dp->outp; 133 + int ret, i; 124 134 125 135 for (i = 0; i < dp->link_nr; i++) { 126 136 u8 lane = (dp->stat[4 + (i >> 1)] >> ((i & 1) * 4)) & 0xf; 137 + u8 lpc2 = (dp->pc2stat >> (i * 2)) & 0x3; 127 138 u8 lpre = (lane & 0x0c) >> 2; 128 139 u8 lvsw = (lane & 0x03) >> 0; 140 + u8 hivs = 3 - lpre; 141 + u8 hipe = 3; 142 + u8 hipc = 3; 143 + 144 + if (lpc2 >= hipc) 145 + lpc2 = hipc | DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED; 146 + if (lpre >= hipe) { 147 + lpre = hipe | DPCD_LC03_MAX_SWING_REACHED; /* yes. */ 148 + lvsw = hivs = 3 - (lpre & 3); 149 + } else 150 + if (lvsw >= hivs) { 151 + lvsw = hivs | DPCD_LC03_MAX_SWING_REACHED; 152 + } 129 153 130 154 dp->conf[i] = (lpre << 3) | lvsw; 131 - if (lvsw == 3) 132 - dp->conf[i] |= DPCD_LC03_MAX_SWING_REACHED; 133 - if (lpre == 3) 134 - dp->conf[i] |= DPCD_LC03_MAX_PRE_EMPHASIS_REACHED; 155 + dp->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4); 135 156 136 - DBG("config lane %d %02x\n", i, dp->conf[i]); 137 - dp->func->drv_ctl(dp->disp, dp->outp, dp->head, i, lvsw, lpre); 157 + DBG("config lane %d %02x %02x\n", i, dp->conf[i], lpc2); 158 + impl->drv_ctl(outp, i, lvsw & 3, lpre & 3, lpc2 & 3); 138 159 } 139 160 140 - return nv_wraux(dp->aux, DPCD_LC03(0), dp->conf, 4); 141 - } 142 - 143 - static int 144 - dp_link_train_update(struct dp_state *dp, u32 delay) 145 - { 146 - int ret; 147 - 148 - if (dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL]) 149 - mdelay(dp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4); 150 - else 151 - udelay(delay); 152 - 153 - ret = nv_rdaux(dp->aux, DPCD_LS02, dp->stat, 6); 161 + ret = nv_wraux(outp->base.edid, DPCD_LC03(0), dp->conf, 4); 154 162 if (ret) 155 163 return ret; 156 164 157 - DBG("status %6ph\n", dp->stat); 165 + if (pc) { 166 + ret = nv_wraux(outp->base.edid, DPCD_LC0F, dp->pc2conf, 2); 167 + if (ret) 168 + return ret; 169 + } 170 + 171 + return 0; 172 + } 173 + 174 + static int 175 + dp_link_train_update(struct dp_state *dp, bool pc, u32 delay) 176 + { 177 + struct nvkm_output_dp *outp = dp->outp; 178 + int ret; 179 + 180 + if (outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL]) 181 + mdelay(outp->dpcd[DPCD_RC0E_AUX_RD_INTERVAL] * 4); 182 + else 183 + udelay(delay); 184 + 185 + ret = nv_rdaux(outp->base.edid, DPCD_LS02, dp->stat, 6); 186 + if (ret) 187 + return ret; 188 + 189 + if (pc) { 190 + ret = nv_rdaux(outp->base.edid, DPCD_LS0C, &dp->pc2stat, 1); 191 + if (ret) 192 + dp->pc2stat = 0x00; 193 + DBG("status %6ph pc2 %02x\n", dp->stat, dp->pc2stat); 194 + } else { 195 + DBG("status %6ph\n", dp->stat); 196 + } 197 + 158 198 return 0; 159 199 } 160 200 ··· 204 172 dp_set_training_pattern(dp, 1); 205 173 206 174 do { 207 - if (dp_link_train_commit(dp) || 208 - dp_link_train_update(dp, 100)) 175 + if (dp_link_train_commit(dp, false) || 176 + dp_link_train_update(dp, false, 100)) 209 177 break; 210 178 211 179 cr_done = true; ··· 231 199 static int 232 200 dp_link_train_eq(struct dp_state *dp) 233 201 { 202 + struct nvkm_output_dp *outp = dp->outp; 234 203 bool eq_done = false, cr_done = true; 235 204 int tries = 0, i; 236 205 237 - if (dp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED) 206 + if (outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED) 238 207 dp_set_training_pattern(dp, 3); 239 208 else 240 209 dp_set_training_pattern(dp, 2); 241 210 242 211 do { 243 - if (dp_link_train_update(dp, 400)) 212 + if (dp_link_train_update(dp, dp->pc2, 400)) 244 213 break; 245 214 246 215 eq_done = !!(dp->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); ··· 254 221 eq_done = false; 255 222 } 256 223 257 - if (dp_link_train_commit(dp)) 224 + if (dp_link_train_commit(dp, dp->pc2)) 258 225 break; 259 226 } while (!eq_done && cr_done && ++tries <= 5); 260 227 ··· 264 231 static void 265 232 dp_link_train_init(struct dp_state *dp, bool spread) 266 233 { 234 + struct nvkm_output_dp *outp = dp->outp; 235 + struct nouveau_disp *disp = nouveau_disp(outp); 236 + struct nouveau_bios *bios = nouveau_bios(disp); 267 237 struct nvbios_init init = { 268 - .subdev = nv_subdev(dp->disp), 269 - .bios = nouveau_bios(dp->disp), 270 - .outp = dp->outp, 271 - .crtc = dp->head, 238 + .subdev = nv_subdev(disp), 239 + .bios = bios, 240 + .outp = &outp->base.info, 241 + .crtc = -1, 272 242 .execute = 1, 273 243 }; 274 244 275 245 /* set desired spread */ 276 246 if (spread) 277 - init.offset = dp->info.script[2]; 247 + init.offset = outp->info.script[2]; 278 248 else 279 - init.offset = dp->info.script[3]; 249 + init.offset = outp->info.script[3]; 280 250 nvbios_exec(&init); 281 251 282 252 /* pre-train script */ 283 - init.offset = dp->info.script[0]; 253 + init.offset = outp->info.script[0]; 284 254 nvbios_exec(&init); 285 255 } 286 256 287 257 static void 288 258 dp_link_train_fini(struct dp_state *dp) 289 259 { 260 + struct nvkm_output_dp *outp = dp->outp; 261 + struct nouveau_disp *disp = nouveau_disp(outp); 262 + struct nouveau_bios *bios = nouveau_bios(disp); 290 263 struct nvbios_init init = { 291 - .subdev = nv_subdev(dp->disp), 292 - .bios = nouveau_bios(dp->disp), 293 - .outp = dp->outp, 294 - .crtc = dp->head, 264 + .subdev = nv_subdev(disp), 265 + .bios = bios, 266 + .outp = &outp->base.info, 267 + .crtc = -1, 295 268 .execute = 1, 296 269 }; 297 270 298 271 /* post-train script */ 299 - init.offset = dp->info.script[1], 272 + init.offset = outp->info.script[1], 300 273 nvbios_exec(&init); 301 274 } 302 275 303 - int 304 - nouveau_dp_train(struct nouveau_disp *disp, const struct nouveau_dp_func *func, 305 - struct dcb_output *outp, int head, u32 datarate) 276 + static const struct dp_rates { 277 + u32 rate; 278 + u8 bw; 279 + u8 nr; 280 + } nouveau_dp_rates[] = { 281 + { 2160000, 0x14, 4 }, 282 + { 1080000, 0x0a, 4 }, 283 + { 1080000, 0x14, 2 }, 284 + { 648000, 0x06, 4 }, 285 + { 540000, 0x0a, 2 }, 286 + { 540000, 0x14, 1 }, 287 + { 324000, 0x06, 2 }, 288 + { 270000, 0x0a, 1 }, 289 + { 162000, 0x06, 1 }, 290 + {} 291 + }; 292 + 293 + void 294 + nouveau_dp_train(struct work_struct *w) 306 295 { 307 - struct nouveau_bios *bios = nouveau_bios(disp); 308 - struct nouveau_i2c *i2c = nouveau_i2c(disp); 296 + struct nvkm_output_dp *outp = container_of(w, typeof(*outp), lt.work); 297 + struct nouveau_disp *disp = nouveau_disp(outp); 298 + const struct dp_rates *cfg = nouveau_dp_rates; 309 299 struct dp_state _dp = { 310 - .disp = disp, 311 - .func = func, 312 300 .outp = outp, 313 - .head = head, 314 301 }, *dp = &_dp; 315 - const u32 bw_list[] = { 540000, 270000, 162000, 0 }; 316 - const u32 *link_bw = bw_list; 317 - u8 hdr, cnt, len; 318 - u32 data; 302 + u32 datarate = 0; 319 303 int ret; 320 304 321 - /* find the bios displayport data relevant to this output */ 322 - data = nvbios_dpout_match(bios, outp->hasht, outp->hashm, &dp->version, 323 - &hdr, &cnt, &len, &dp->info); 324 - if (!data) { 325 - ERR("bios data not found\n"); 326 - return -EINVAL; 327 - } 328 - 329 - /* acquire the aux channel and fetch some info about the display */ 330 - if (outp->location) 331 - dp->aux = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); 332 - else 333 - dp->aux = i2c->find(i2c, NV_I2C_TYPE_DCBI2C(outp->i2c_index)); 334 - if (!dp->aux) { 335 - ERR("no aux channel?!\n"); 336 - return -ENODEV; 337 - } 338 - 339 - ret = nv_rdaux(dp->aux, 0x00000, dp->dpcd, sizeof(dp->dpcd)); 340 - if (ret) { 341 - /* it's possible the display has been unplugged before we 342 - * get here. we still need to execute the full set of 343 - * vbios scripts, and program the OR at a high enough 344 - * frequency to satisfy the target mode. failure to do 345 - * so results at best in an UPDATE hanging, and at worst 346 - * with PDISP running away to join the circus. 347 - */ 348 - dp->dpcd[1] = link_bw[0] / 27000; 349 - dp->dpcd[2] = 4; 350 - dp->dpcd[3] = 0x00; 351 - ERR("failed to read DPCD\n"); 352 - } 353 - 354 305 /* bring capabilities within encoder limits */ 355 - if (nv_oclass(disp)->handle < NV_ENGINE(DISP, 0x90)) 356 - dp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED; 357 - if ((dp->dpcd[2] & 0x1f) > dp->outp->dpconf.link_nr) { 358 - dp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT; 359 - dp->dpcd[2] |= dp->outp->dpconf.link_nr; 306 + if (nv_mclass(disp) < NVD0_DISP_CLASS) 307 + outp->dpcd[2] &= ~DPCD_RC02_TPS3_SUPPORTED; 308 + if ((outp->dpcd[2] & 0x1f) > outp->base.info.dpconf.link_nr) { 309 + outp->dpcd[2] &= ~DPCD_RC02_MAX_LANE_COUNT; 310 + outp->dpcd[2] |= outp->base.info.dpconf.link_nr; 360 311 } 361 - if (dp->dpcd[1] > dp->outp->dpconf.link_bw) 362 - dp->dpcd[1] = dp->outp->dpconf.link_bw; 312 + if (outp->dpcd[1] > outp->base.info.dpconf.link_bw) 313 + outp->dpcd[1] = outp->base.info.dpconf.link_bw; 314 + dp->pc2 = outp->dpcd[2] & DPCD_RC02_TPS3_SUPPORTED; 363 315 364 - /* adjust required bandwidth for 8B/10B coding overhead */ 365 - datarate = (datarate / 8) * 10; 316 + /* restrict link config to the lowest required rate, if requested */ 317 + if (datarate) { 318 + datarate = (datarate / 8) * 10; /* 8B/10B coding overhead */ 319 + while (cfg[1].rate >= datarate) 320 + cfg++; 321 + } 322 + cfg--; 323 + 324 + /* disable link interrupt handling during link training */ 325 + nouveau_event_put(outp->irq); 366 326 367 327 /* enable down-spreading and execute pre-train script from vbios */ 368 - dp_link_train_init(dp, dp->dpcd[3] & 0x01); 328 + dp_link_train_init(dp, outp->dpcd[3] & 0x01); 369 329 370 - /* start off at highest link rate supported by encoder and display */ 371 - while (*link_bw > (dp->dpcd[1] * 27000)) 372 - link_bw++; 373 - 374 - while ((ret = -EIO) && link_bw[0]) { 375 - /* find minimum required lane count at this link rate */ 376 - dp->link_nr = dp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT; 377 - while ((dp->link_nr >> 1) * link_bw[0] > datarate) 378 - dp->link_nr >>= 1; 379 - 380 - /* drop link rate to minimum with this lane count */ 381 - while ((link_bw[1] * dp->link_nr) > datarate) 382 - link_bw++; 383 - dp->link_bw = link_bw[0]; 330 + while (ret = -EIO, (++cfg)->rate) { 331 + /* select next configuration supported by encoder and sink */ 332 + while (cfg->nr > (outp->dpcd[2] & DPCD_RC02_MAX_LANE_COUNT) || 333 + cfg->bw > (outp->dpcd[DPCD_RC01_MAX_LINK_RATE])) 334 + cfg++; 335 + dp->link_bw = cfg->bw * 27000; 336 + dp->link_nr = cfg->nr; 384 337 385 338 /* program selected link configuration */ 386 339 ret = dp_set_link_config(dp); ··· 383 364 */ 384 365 break; 385 366 } 386 - 387 - /* retry at lower rate */ 388 - link_bw++; 389 367 } 390 368 391 - /* finish link training */ 369 + /* finish link training and execute post-train script from vbios */ 392 370 dp_set_training_pattern(dp, 0); 393 371 if (ret < 0) 394 372 ERR("link training failed\n"); 395 373 396 - /* execute post-train script from vbios */ 397 374 dp_link_train_fini(dp); 398 - return (ret < 0) ? false : true; 375 + 376 + /* signal completion and enable link interrupt handling */ 377 + DBG("training complete\n"); 378 + atomic_set(&outp->lt.done, 1); 379 + wake_up(&outp->lt.wait); 380 + nouveau_event_get(outp->irq); 399 381 }
+17 -20
drivers/gpu/drm/nouveau/core/engine/disp/dport.h
··· 13 13 #define DPCD_RC0E_AUX_RD_INTERVAL 0x0000e 14 14 15 15 /* DPCD Link Configuration */ 16 - #define DPCD_LC00 0x00100 17 - #define DPCD_LC00_LINK_BW_SET 0xff 16 + #define DPCD_LC00_LINK_BW_SET 0x00100 18 17 #define DPCD_LC01 0x00101 19 18 #define DPCD_LC01_ENHANCED_FRAME_EN 0x80 20 19 #define DPCD_LC01_LANE_COUNT_SET 0x1f ··· 24 25 #define DPCD_LC03_PRE_EMPHASIS_SET 0x18 25 26 #define DPCD_LC03_MAX_SWING_REACHED 0x04 26 27 #define DPCD_LC03_VOLTAGE_SWING_SET 0x03 28 + #define DPCD_LC0F 0x0010f 29 + #define DPCD_LC0F_LANE1_MAX_POST_CURSOR2_REACHED 0x40 30 + #define DPCD_LC0F_LANE1_POST_CURSOR2_SET 0x30 31 + #define DPCD_LC0F_LANE0_MAX_POST_CURSOR2_REACHED 0x04 32 + #define DPCD_LC0F_LANE0_POST_CURSOR2_SET 0x03 33 + #define DPCD_LC10 0x00110 34 + #define DPCD_LC10_LANE3_MAX_POST_CURSOR2_REACHED 0x40 35 + #define DPCD_LC10_LANE3_POST_CURSOR2_SET 0x30 36 + #define DPCD_LC10_LANE2_MAX_POST_CURSOR2_REACHED 0x04 37 + #define DPCD_LC10_LANE2_POST_CURSOR2_SET 0x03 27 38 28 39 /* DPCD Link/Sink Status */ 29 40 #define DPCD_LS02 0x00202 ··· 64 55 #define DPCD_LS07_LANE3_VOLTAGE_SWING 0x30 65 56 #define DPCD_LS07_LANE2_PRE_EMPHASIS 0x0c 66 57 #define DPCD_LS07_LANE2_VOLTAGE_SWING 0x03 58 + #define DPCD_LS0C 0x0020c 59 + #define DPCD_LS0C_LANE3_POST_CURSOR2 0xc0 60 + #define DPCD_LS0C_LANE2_POST_CURSOR2 0x30 61 + #define DPCD_LS0C_LANE1_POST_CURSOR2 0x0c 62 + #define DPCD_LS0C_LANE0_POST_CURSOR2 0x03 67 63 68 - struct nouveau_disp; 69 - struct dcb_output; 70 - 71 - struct nouveau_dp_func { 72 - int (*pattern)(struct nouveau_disp *, struct dcb_output *, 73 - int head, int pattern); 74 - int (*lnk_ctl)(struct nouveau_disp *, struct dcb_output *, int head, 75 - int link_nr, int link_bw, bool enh_frame); 76 - int (*drv_ctl)(struct nouveau_disp *, struct dcb_output *, int head, 77 - int lane, int swing, int preem); 78 - }; 79 - 80 - extern const struct nouveau_dp_func nv94_sor_dp_func; 81 - extern const struct nouveau_dp_func nvd0_sor_dp_func; 82 - extern const struct nouveau_dp_func nv50_pior_dp_func; 83 - 84 - int nouveau_dp_train(struct nouveau_disp *, const struct nouveau_dp_func *, 85 - struct dcb_output *, int, u32); 64 + void nouveau_dp_train(struct work_struct *); 86 65 87 66 #endif
+1 -1
drivers/gpu/drm/nouveau/core/engine/disp/gm107.c
··· 81 81 priv->sor.power = nv50_sor_power; 82 82 priv->sor.hda_eld = nvd0_hda_eld; 83 83 priv->sor.hdmi = nvd0_hdmi_ctrl; 84 - priv->sor.dp = &nvd0_sor_dp_func; 85 84 return 0; 86 85 } 87 86 ··· 93 94 .init = _nouveau_disp_init, 94 95 .fini = _nouveau_disp_fini, 95 96 }, 97 + .base.outp = nvd0_disp_outp_sclass, 96 98 .mthd.core = &nve0_disp_mast_mthd_chan, 97 99 .mthd.base = &nvd0_disp_sync_mthd_chan, 98 100 .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+4 -4
drivers/gpu/drm/nouveau/core/engine/disp/nv04.c
··· 86 86 ******************************************************************************/ 87 87 88 88 static void 89 - nv04_disp_vblank_enable(struct nouveau_event *event, int head) 89 + nv04_disp_vblank_enable(struct nouveau_event *event, int type, int head) 90 90 { 91 91 nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000001); 92 92 } 93 93 94 94 static void 95 - nv04_disp_vblank_disable(struct nouveau_event *event, int head) 95 + nv04_disp_vblank_disable(struct nouveau_event *event, int type, int head) 96 96 { 97 97 nv_wr32(event->priv, 0x600140 + (head * 0x2000) , 0x00000000); 98 98 } ··· 106 106 u32 pvideo; 107 107 108 108 if (crtc0 & 0x00000001) { 109 - nouveau_event_trigger(priv->base.vblank, 0); 109 + nouveau_event_trigger(priv->base.vblank, 1, 0); 110 110 nv_wr32(priv, 0x600100, 0x00000001); 111 111 } 112 112 113 113 if (crtc1 & 0x00000001) { 114 - nouveau_event_trigger(priv->base.vblank, 1); 114 + nouveau_event_trigger(priv->base.vblank, 1, 1); 115 115 nv_wr32(priv, 0x602100, 0x00000001); 116 116 } 117 117
+166 -116
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
··· 829 829 } 830 830 831 831 static void 832 - nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) 832 + nv50_disp_base_vblank_enable(struct nouveau_event *event, int type, int head) 833 833 { 834 834 nv_mask(event->priv, 0x61002c, (4 << head), (4 << head)); 835 835 } 836 836 837 837 static void 838 - nv50_disp_base_vblank_disable(struct nouveau_event *event, int head) 838 + nv50_disp_base_vblank_disable(struct nouveau_event *event, int type, int head) 839 839 { 840 840 nv_mask(event->priv, 0x61002c, (4 << head), 0); 841 841 } ··· 1114 1114 nv_wr32(priv, 0x610080 + (chid * 0x08), 0x90000000); 1115 1115 } 1116 1116 1117 - static u16 1118 - exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, 1119 - struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 1117 + static struct nvkm_output * 1118 + exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, 1119 + u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 1120 1120 struct nvbios_outp *info) 1121 1121 { 1122 1122 struct nouveau_bios *bios = nouveau_bios(priv); 1123 - u16 mask, type, data; 1123 + struct nvkm_output *outp; 1124 + u16 mask, type; 1124 1125 1125 - if (outp < 4) { 1126 + if (or < 4) { 1126 1127 type = DCB_OUTPUT_ANALOG; 1127 1128 mask = 0; 1128 1129 } else 1129 - if (outp < 8) { 1130 + if (or < 8) { 1130 1131 switch (ctrl & 0x00000f00) { 1131 1132 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; 1132 1133 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; ··· 1137 1136 case 0x00000900: type = DCB_OUTPUT_DP; mask = 2; break; 1138 1137 default: 1139 1138 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); 1140 - return 0x0000; 1139 + return NULL; 1141 1140 } 1142 - outp -= 4; 1141 + or -= 4; 1143 1142 } else { 1144 - outp = outp - 8; 1143 + or = or - 8; 1145 1144 type = 0x0010; 1146 1145 mask = 0; 1147 1146 switch (ctrl & 0x00000f00) { 1148 - case 0x00000000: type |= priv->pior.type[outp]; break; 1147 + case 0x00000000: type |= priv->pior.type[or]; break; 1149 1148 default: 1150 1149 nv_error(priv, "unknown PIOR mc 0x%08x\n", ctrl); 1151 - return 0x0000; 1150 + return NULL; 1152 1151 } 1153 1152 } 1154 1153 1155 1154 mask = 0x00c0 & (mask << 6); 1156 - mask |= 0x0001 << outp; 1155 + mask |= 0x0001 << or; 1157 1156 mask |= 0x0100 << head; 1158 1157 1159 - data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); 1160 - if (!data) 1161 - return 0x0000; 1158 + list_for_each_entry(outp, &priv->base.outp, head) { 1159 + if ((outp->info.hasht & 0xff) == type && 1160 + (outp->info.hashm & mask) == mask) { 1161 + *data = nvbios_outp_match(bios, outp->info.hasht, 1162 + outp->info.hashm, 1163 + ver, hdr, cnt, len, info); 1164 + if (!*data) 1165 + return NULL; 1166 + return outp; 1167 + } 1168 + } 1162 1169 1163 - /* off-chip encoders require matching the exact encoder type */ 1164 - if (dcb->location != 0) 1165 - type |= dcb->extdev << 8; 1166 - 1167 - return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); 1170 + return NULL; 1168 1171 } 1169 1172 1170 - static bool 1173 + static struct nvkm_output * 1171 1174 exec_script(struct nv50_disp_priv *priv, int head, int id) 1172 1175 { 1173 1176 struct nouveau_bios *bios = nouveau_bios(priv); 1177 + struct nvkm_output *outp; 1174 1178 struct nvbios_outp info; 1175 - struct dcb_output dcb; 1176 1179 u8 ver, hdr, cnt, len; 1177 - u16 data; 1178 - u32 ctrl = 0x00000000; 1180 + u32 data, ctrl = 0; 1179 1181 u32 reg; 1180 1182 int i; 1181 1183 ··· 1208 1204 } 1209 1205 1210 1206 if (!(ctrl & (1 << head))) 1211 - return false; 1207 + return NULL; 1212 1208 i--; 1213 1209 1214 - data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); 1215 - if (data) { 1210 + outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info); 1211 + if (outp) { 1216 1212 struct nvbios_init init = { 1217 1213 .subdev = nv_subdev(priv), 1218 1214 .bios = bios, 1219 1215 .offset = info.script[id], 1220 - .outp = &dcb, 1216 + .outp = &outp->info, 1221 1217 .crtc = head, 1222 1218 .execute = 1, 1223 1219 }; 1224 1220 1225 - return nvbios_exec(&init) == 0; 1221 + nvbios_exec(&init); 1226 1222 } 1227 1223 1228 - return false; 1224 + return outp; 1229 1225 } 1230 1226 1231 - static u32 1232 - exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, 1233 - struct dcb_output *outp) 1227 + static struct nvkm_output * 1228 + exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) 1234 1229 { 1235 1230 struct nouveau_bios *bios = nouveau_bios(priv); 1231 + struct nvkm_output *outp; 1236 1232 struct nvbios_outp info1; 1237 1233 struct nvbios_ocfg info2; 1238 1234 u8 ver, hdr, cnt, len; 1239 - u32 ctrl = 0x00000000; 1240 - u32 data, conf = ~0; 1235 + u32 data, ctrl = 0; 1241 1236 u32 reg; 1242 1237 int i; 1243 1238 ··· 1266 1263 } 1267 1264 1268 1265 if (!(ctrl & (1 << head))) 1269 - return conf; 1266 + return NULL; 1270 1267 i--; 1271 1268 1272 - data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); 1269 + outp = exec_lookup(priv, head, i, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); 1273 1270 if (!data) 1274 - return conf; 1271 + return NULL; 1275 1272 1276 - if (outp->location == 0) { 1277 - switch (outp->type) { 1273 + if (outp->info.location == 0) { 1274 + switch (outp->info.type) { 1278 1275 case DCB_OUTPUT_TMDS: 1279 - conf = (ctrl & 0x00000f00) >> 8; 1276 + *conf = (ctrl & 0x00000f00) >> 8; 1280 1277 if (pclk >= 165000) 1281 - conf |= 0x0100; 1278 + *conf |= 0x0100; 1282 1279 break; 1283 1280 case DCB_OUTPUT_LVDS: 1284 - conf = priv->sor.lvdsconf; 1281 + *conf = priv->sor.lvdsconf; 1285 1282 break; 1286 1283 case DCB_OUTPUT_DP: 1287 - conf = (ctrl & 0x00000f00) >> 8; 1284 + *conf = (ctrl & 0x00000f00) >> 8; 1288 1285 break; 1289 1286 case DCB_OUTPUT_ANALOG: 1290 1287 default: 1291 - conf = 0x00ff; 1288 + *conf = 0x00ff; 1292 1289 break; 1293 1290 } 1294 1291 } else { 1295 - conf = (ctrl & 0x00000f00) >> 8; 1292 + *conf = (ctrl & 0x00000f00) >> 8; 1296 1293 pclk = pclk / 2; 1297 1294 } 1298 1295 1299 - data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 1296 + data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2); 1300 1297 if (data && id < 0xff) { 1301 1298 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 1302 1299 if (data) { ··· 1304 1301 .subdev = nv_subdev(priv), 1305 1302 .bios = bios, 1306 1303 .offset = data, 1307 - .outp = outp, 1304 + .outp = &outp->info, 1308 1305 .crtc = head, 1309 1306 .execute = 1, 1310 1307 }; ··· 1313 1310 } 1314 1311 } 1315 1312 1316 - return conf; 1313 + return outp; 1317 1314 } 1318 1315 1319 1316 static void ··· 1325 1322 static void 1326 1323 nv50_disp_intr_unk20_0(struct nv50_disp_priv *priv, int head) 1327 1324 { 1328 - exec_script(priv, head, 2); 1325 + struct nvkm_output *outp = exec_script(priv, head, 2); 1326 + 1327 + /* the binary driver does this outside of the supervisor handling 1328 + * (after the third supervisor from a detach). we (currently?) 1329 + * allow both detach/attach to happen in the same set of 1330 + * supervisor interrupts, so it would make sense to execute this 1331 + * (full power down?) script after all the detach phases of the 1332 + * supervisor handling. like with training if needed from the 1333 + * second supervisor, nvidia doesn't do this, so who knows if it's 1334 + * entirely safe, but it does appear to work.. 1335 + * 1336 + * without this script being run, on some configurations i've 1337 + * seen, switching from DP to TMDS on a DP connector may result 1338 + * in a blank screen (SOR_PWR off/on can restore it) 1339 + */ 1340 + if (outp && outp->info.type == DCB_OUTPUT_DP) { 1341 + struct nvkm_output_dp *outpdp = (void *)outp; 1342 + struct nvbios_init init = { 1343 + .subdev = nv_subdev(priv), 1344 + .bios = nouveau_bios(priv), 1345 + .outp = &outp->info, 1346 + .crtc = head, 1347 + .offset = outpdp->info.script[4], 1348 + .execute = 1, 1349 + }; 1350 + 1351 + nvbios_exec(&init); 1352 + atomic_set(&outpdp->lt.done, 0); 1353 + } 1329 1354 } 1330 1355 1331 1356 static void ··· 1475 1444 static void 1476 1445 nv50_disp_intr_unk20_2(struct nv50_disp_priv *priv, int head) 1477 1446 { 1478 - struct dcb_output outp; 1447 + struct nvkm_output *outp; 1479 1448 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; 1480 1449 u32 hval, hreg = 0x614200 + (head * 0x800); 1481 1450 u32 oval, oreg; 1482 - u32 mask; 1483 - u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); 1484 - if (conf != ~0) { 1485 - if (outp.location == 0 && outp.type == DCB_OUTPUT_DP) { 1486 - u32 soff = (ffs(outp.or) - 1) * 0x08; 1487 - u32 ctrl = nv_rd32(priv, 0x610794 + soff); 1488 - u32 datarate; 1451 + u32 mask, conf; 1489 1452 1490 - switch ((ctrl & 0x000f0000) >> 16) { 1491 - case 6: datarate = pclk * 30 / 8; break; 1492 - case 5: datarate = pclk * 24 / 8; break; 1493 - case 2: 1494 - default: 1495 - datarate = pclk * 18 / 8; 1496 - break; 1497 - } 1453 + outp = exec_clkcmp(priv, head, 0xff, pclk, &conf); 1454 + if (!outp) 1455 + return; 1498 1456 1499 - nouveau_dp_train(&priv->base, priv->sor.dp, 1500 - &outp, head, datarate); 1501 - } 1457 + /* we allow both encoder attach and detach operations to occur 1458 + * within a single supervisor (ie. modeset) sequence. the 1459 + * encoder detach scripts quite often switch off power to the 1460 + * lanes, which requires the link to be re-trained. 1461 + * 1462 + * this is not generally an issue as the sink "must" (heh) 1463 + * signal an irq when it's lost sync so the driver can 1464 + * re-train. 1465 + * 1466 + * however, on some boards, if one does not configure at least 1467 + * the gpu side of the link *before* attaching, then various 1468 + * things can go horribly wrong (PDISP disappearing from mmio, 1469 + * third supervisor never happens, etc). 1470 + * 1471 + * the solution is simply to retrain here, if necessary. last 1472 + * i checked, the binary driver userspace does not appear to 1473 + * trigger this situation (it forces an UPDATE between steps). 1474 + */ 1475 + if (outp->info.type == DCB_OUTPUT_DP) { 1476 + u32 soff = (ffs(outp->info.or) - 1) * 0x08; 1477 + u32 ctrl, datarate; 1502 1478 1503 - exec_clkcmp(priv, head, 0, pclk, &outp); 1504 - 1505 - if (!outp.location && outp.type == DCB_OUTPUT_ANALOG) { 1506 - oreg = 0x614280 + (ffs(outp.or) - 1) * 0x800; 1507 - oval = 0x00000000; 1508 - hval = 0x00000000; 1509 - mask = 0xffffffff; 1510 - } else 1511 - if (!outp.location) { 1512 - if (outp.type == DCB_OUTPUT_DP) 1513 - nv50_disp_intr_unk20_2_dp(priv, &outp, pclk); 1514 - oreg = 0x614300 + (ffs(outp.or) - 1) * 0x800; 1515 - oval = (conf & 0x0100) ? 0x00000101 : 0x00000000; 1516 - hval = 0x00000000; 1517 - mask = 0x00000707; 1479 + if (outp->info.location == 0) { 1480 + ctrl = nv_rd32(priv, 0x610794 + soff); 1481 + soff = 1; 1518 1482 } else { 1519 - oreg = 0x614380 + (ffs(outp.or) - 1) * 0x800; 1520 - oval = 0x00000001; 1521 - hval = 0x00000001; 1522 - mask = 0x00000707; 1483 + ctrl = nv_rd32(priv, 0x610b80 + soff); 1484 + soff = 2; 1523 1485 } 1524 1486 1525 - nv_mask(priv, hreg, 0x0000000f, hval); 1526 - nv_mask(priv, oreg, mask, oval); 1487 + switch ((ctrl & 0x000f0000) >> 16) { 1488 + case 6: datarate = pclk * 30 / 8; break; 1489 + case 5: datarate = pclk * 24 / 8; break; 1490 + case 2: 1491 + default: 1492 + datarate = pclk * 18 / 8; 1493 + break; 1494 + } 1495 + 1496 + if (nvkm_output_dp_train(outp, datarate / soff, true)) 1497 + ERR("link not trained before attach\n"); 1527 1498 } 1499 + 1500 + exec_clkcmp(priv, head, 0, pclk, &conf); 1501 + 1502 + if (!outp->info.location && outp->info.type == DCB_OUTPUT_ANALOG) { 1503 + oreg = 0x614280 + (ffs(outp->info.or) - 1) * 0x800; 1504 + oval = 0x00000000; 1505 + hval = 0x00000000; 1506 + mask = 0xffffffff; 1507 + } else 1508 + if (!outp->info.location) { 1509 + if (outp->info.type == DCB_OUTPUT_DP) 1510 + nv50_disp_intr_unk20_2_dp(priv, &outp->info, pclk); 1511 + oreg = 0x614300 + (ffs(outp->info.or) - 1) * 0x800; 1512 + oval = (conf & 0x0100) ? 0x00000101 : 0x00000000; 1513 + hval = 0x00000000; 1514 + mask = 0x00000707; 1515 + } else { 1516 + oreg = 0x614380 + (ffs(outp->info.or) - 1) * 0x800; 1517 + oval = 0x00000001; 1518 + hval = 0x00000001; 1519 + mask = 0x00000707; 1520 + } 1521 + 1522 + nv_mask(priv, hreg, 0x0000000f, hval); 1523 + nv_mask(priv, oreg, mask, oval); 1528 1524 } 1529 1525 1530 1526 /* If programming a TMDS output on a SOR that can also be configured for ··· 1579 1521 static void 1580 1522 nv50_disp_intr_unk40_0(struct nv50_disp_priv *priv, int head) 1581 1523 { 1582 - struct dcb_output outp; 1524 + struct nvkm_output *outp; 1583 1525 u32 pclk = nv_rd32(priv, 0x610ad0 + (head * 0x540)) & 0x3fffff; 1584 - if (exec_clkcmp(priv, head, 1, pclk, &outp) != ~0) { 1585 - if (outp.location == 0 && outp.type == DCB_OUTPUT_TMDS) 1586 - nv50_disp_intr_unk40_0_tmds(priv, &outp); 1587 - else 1588 - if (outp.location == 1 && outp.type == DCB_OUTPUT_DP) { 1589 - u32 soff = (ffs(outp.or) - 1) * 0x08; 1590 - u32 ctrl = nv_rd32(priv, 0x610b84 + soff); 1591 - u32 datarate; 1526 + u32 conf; 1592 1527 1593 - switch ((ctrl & 0x000f0000) >> 16) { 1594 - case 6: datarate = pclk * 30 / 8; break; 1595 - case 5: datarate = pclk * 24 / 8; break; 1596 - case 2: 1597 - default: 1598 - datarate = pclk * 18 / 8; 1599 - break; 1600 - } 1528 + outp = exec_clkcmp(priv, head, 1, pclk, &conf); 1529 + if (!outp) 1530 + return; 1601 1531 1602 - nouveau_dp_train(&priv->base, priv->pior.dp, 1603 - &outp, head, datarate); 1604 - } 1605 - } 1532 + if (outp->info.location == 0 && outp->info.type == DCB_OUTPUT_TMDS) 1533 + nv50_disp_intr_unk40_0_tmds(priv, &outp->info); 1606 1534 } 1607 1535 1608 1536 void ··· 1654 1610 } 1655 1611 1656 1612 if (intr1 & 0x00000004) { 1657 - nouveau_event_trigger(priv->base.vblank, 0); 1613 + nouveau_event_trigger(priv->base.vblank, 1, 0); 1658 1614 nv_wr32(priv, 0x610024, 0x00000004); 1659 1615 intr1 &= ~0x00000004; 1660 1616 } 1661 1617 1662 1618 if (intr1 & 0x00000008) { 1663 - nouveau_event_trigger(priv->base.vblank, 1); 1619 + nouveau_event_trigger(priv->base.vblank, 1, 1); 1664 1620 nv_wr32(priv, 0x610024, 0x00000008); 1665 1621 intr1 &= ~0x00000008; 1666 1622 } ··· 1700 1656 priv->dac.sense = nv50_dac_sense; 1701 1657 priv->sor.power = nv50_sor_power; 1702 1658 priv->pior.power = nv50_pior_power; 1703 - priv->pior.dp = &nv50_pior_dp_func; 1704 1659 return 0; 1705 1660 } 1661 + 1662 + struct nouveau_oclass * 1663 + nv50_disp_outp_sclass[] = { 1664 + &nv50_pior_dp_impl.base.base, 1665 + NULL 1666 + }; 1706 1667 1707 1668 struct nouveau_oclass * 1708 1669 nv50_disp_oclass = &(struct nv50_disp_impl) { ··· 1718 1669 .init = _nouveau_disp_init, 1719 1670 .fini = _nouveau_disp_fini, 1720 1671 }, 1672 + .base.outp = nv50_disp_outp_sclass, 1721 1673 .mthd.core = &nv50_disp_mast_mthd_chan, 1722 1674 .mthd.base = &nv50_disp_sync_mthd_chan, 1723 1675 .mthd.ovly = &nv50_disp_ovly_mthd_chan,
+12 -2
drivers/gpu/drm/nouveau/core/engine/disp/nv50.h
··· 11 11 12 12 #include "dport.h" 13 13 #include "priv.h" 14 + #include "outp.h" 15 + #include "outpdp.h" 14 16 15 17 struct nv50_disp_impl { 16 18 struct nouveau_disp_impl base; ··· 45 43 int (*hda_eld)(struct nv50_disp_priv *, int sor, u8 *, u32); 46 44 int (*hdmi)(struct nv50_disp_priv *, int head, int sor, u32); 47 45 u32 lvdsconf; 48 - const struct nouveau_dp_func *dp; 49 46 } sor; 50 47 struct { 51 48 int nr; 52 49 int (*power)(struct nv50_disp_priv *, int ext, u32 data); 53 50 u8 type[3]; 54 - const struct nouveau_dp_func *dp; 55 51 } pior; 56 52 }; 57 53 ··· 198 198 199 199 extern const struct nv50_disp_mthd_chan nve0_disp_mast_mthd_chan; 200 200 extern const struct nv50_disp_mthd_chan nve0_disp_ovly_mthd_chan; 201 + 202 + extern struct nvkm_output_dp_impl nv50_pior_dp_impl; 203 + extern struct nouveau_oclass *nv50_disp_outp_sclass[]; 204 + 205 + extern struct nvkm_output_dp_impl nv94_sor_dp_impl; 206 + int nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *, int); 207 + extern struct nouveau_oclass *nv94_disp_outp_sclass[]; 208 + 209 + extern struct nvkm_output_dp_impl nvd0_sor_dp_impl; 210 + extern struct nouveau_oclass *nvd0_disp_outp_sclass[]; 201 211 202 212 #endif
+1 -1
drivers/gpu/drm/nouveau/core/engine/disp/nv84.c
··· 264 264 priv->sor.power = nv50_sor_power; 265 265 priv->sor.hdmi = nv84_hdmi_ctrl; 266 266 priv->pior.power = nv50_pior_power; 267 - priv->pior.dp = &nv50_pior_dp_func; 268 267 return 0; 269 268 } 270 269 ··· 276 277 .init = _nouveau_disp_init, 277 278 .fini = _nouveau_disp_fini, 278 279 }, 280 + .base.outp = nv50_disp_outp_sclass, 279 281 .mthd.core = &nv84_disp_mast_mthd_chan, 280 282 .mthd.base = &nv84_disp_sync_mthd_chan, 281 283 .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+9 -2
drivers/gpu/drm/nouveau/core/engine/disp/nv94.c
··· 77 77 { SOR_MTHD(NV50_DISP_SOR_PWR) , nv50_sor_mthd }, 78 78 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 79 79 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 80 + { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 80 81 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 81 82 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 82 83 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, ··· 123 122 priv->dac.sense = nv50_dac_sense; 124 123 priv->sor.power = nv50_sor_power; 125 124 priv->sor.hdmi = nv84_hdmi_ctrl; 126 - priv->sor.dp = &nv94_sor_dp_func; 127 125 priv->pior.power = nv50_pior_power; 128 - priv->pior.dp = &nv50_pior_dp_func; 129 126 return 0; 130 127 } 128 + 129 + struct nouveau_oclass * 130 + nv94_disp_outp_sclass[] = { 131 + &nv50_pior_dp_impl.base.base, 132 + &nv94_sor_dp_impl.base.base, 133 + NULL 134 + }; 131 135 132 136 struct nouveau_oclass * 133 137 nv94_disp_oclass = &(struct nv50_disp_impl) { ··· 143 137 .init = _nouveau_disp_init, 144 138 .fini = _nouveau_disp_fini, 145 139 }, 140 + .base.outp = nv94_disp_outp_sclass, 146 141 .mthd.core = &nv94_disp_mast_mthd_chan, 147 142 .mthd.base = &nv84_disp_sync_mthd_chan, 148 143 .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+1 -1
drivers/gpu/drm/nouveau/core/engine/disp/nva0.c
··· 126 126 priv->sor.power = nv50_sor_power; 127 127 priv->sor.hdmi = nv84_hdmi_ctrl; 128 128 priv->pior.power = nv50_pior_power; 129 - priv->pior.dp = &nv50_pior_dp_func; 130 129 return 0; 131 130 } 132 131 ··· 138 139 .init = _nouveau_disp_init, 139 140 .fini = _nouveau_disp_fini, 140 141 }, 142 + .base.outp = nv50_disp_outp_sclass, 141 143 .mthd.core = &nv84_disp_mast_mthd_chan, 142 144 .mthd.base = &nv84_disp_sync_mthd_chan, 143 145 .mthd.ovly = &nva0_disp_ovly_mthd_chan,
+2 -2
drivers/gpu/drm/nouveau/core/engine/disp/nva3.c
··· 50 50 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, 51 51 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 52 52 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 53 + { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 53 54 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 54 55 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 55 56 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, ··· 97 96 priv->sor.power = nv50_sor_power; 98 97 priv->sor.hda_eld = nva3_hda_eld; 99 98 priv->sor.hdmi = nva3_hdmi_ctrl; 100 - priv->sor.dp = &nv94_sor_dp_func; 101 99 priv->pior.power = nv50_pior_power; 102 - priv->pior.dp = &nv50_pior_dp_func; 103 100 return 0; 104 101 } 105 102 ··· 110 111 .init = _nouveau_disp_init, 111 112 .fini = _nouveau_disp_fini, 112 113 }, 114 + .base.outp = nv94_disp_outp_sclass, 113 115 .mthd.core = &nv94_disp_mast_mthd_chan, 114 116 .mthd.base = &nv84_disp_sync_mthd_chan, 115 117 .mthd.ovly = &nv84_disp_ovly_mthd_chan,
+119 -87
drivers/gpu/drm/nouveau/core/engine/disp/nvd0.c
··· 748 748 } 749 749 750 750 static void 751 - nvd0_disp_base_vblank_enable(struct nouveau_event *event, int head) 751 + nvd0_disp_base_vblank_enable(struct nouveau_event *event, int type, int head) 752 752 { 753 753 nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000001); 754 754 } 755 755 756 756 static void 757 - nvd0_disp_base_vblank_disable(struct nouveau_event *event, int head) 757 + nvd0_disp_base_vblank_disable(struct nouveau_event *event, int type, int head) 758 758 { 759 759 nv_mask(event->priv, 0x6100c0 + (head * 0x800), 0x00000001, 0x00000000); 760 760 } ··· 887 887 { SOR_MTHD(NVA3_DISP_SOR_HDA_ELD) , nv50_sor_mthd }, 888 888 { SOR_MTHD(NV84_DISP_SOR_HDMI_PWR) , nv50_sor_mthd }, 889 889 { SOR_MTHD(NV50_DISP_SOR_LVDS_SCRIPT) , nv50_sor_mthd }, 890 + { SOR_MTHD(NV94_DISP_SOR_DP_PWR) , nv50_sor_mthd }, 890 891 { DAC_MTHD(NV50_DISP_DAC_PWR) , nv50_dac_mthd }, 891 892 { DAC_MTHD(NV50_DISP_DAC_LOAD) , nv50_dac_mthd }, 892 893 { PIOR_MTHD(NV50_DISP_PIOR_PWR) , nv50_pior_mthd }, ··· 916 915 * Display engine implementation 917 916 ******************************************************************************/ 918 917 919 - static u16 920 - exec_lookup(struct nv50_disp_priv *priv, int head, int outp, u32 ctrl, 921 - struct dcb_output *dcb, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 918 + static struct nvkm_output * 919 + exec_lookup(struct nv50_disp_priv *priv, int head, int or, u32 ctrl, 920 + u32 *data, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 922 921 struct nvbios_outp *info) 923 922 { 924 923 struct nouveau_bios *bios = nouveau_bios(priv); 925 - u16 mask, type, data; 924 + struct nvkm_output *outp; 925 + u16 mask, type; 926 926 927 - if (outp < 4) { 927 + if (or < 4) { 928 928 type = DCB_OUTPUT_ANALOG; 929 929 mask = 0; 930 930 } else { 931 - outp -= 4; 931 + or -= 4; 932 932 switch (ctrl & 0x00000f00) { 933 933 case 0x00000000: type = DCB_OUTPUT_LVDS; mask = 1; break; 934 934 case 0x00000100: type = DCB_OUTPUT_TMDS; mask = 1; break; ··· 941 939 nv_error(priv, "unknown SOR mc 0x%08x\n", ctrl); 942 940 return 0x0000; 943 941 } 944 - dcb->sorconf.link = mask; 945 942 } 946 943 947 944 mask = 0x00c0 & (mask << 6); 948 - mask |= 0x0001 << outp; 945 + mask |= 0x0001 << or; 949 946 mask |= 0x0100 << head; 950 947 951 - data = dcb_outp_match(bios, type, mask, ver, hdr, dcb); 952 - if (!data) 953 - return 0x0000; 948 + list_for_each_entry(outp, &priv->base.outp, head) { 949 + if ((outp->info.hasht & 0xff) == type && 950 + (outp->info.hashm & mask) == mask) { 951 + *data = nvbios_outp_match(bios, outp->info.hasht, 952 + outp->info.hashm, 953 + ver, hdr, cnt, len, info); 954 + if (!*data) 955 + return NULL; 956 + return outp; 957 + } 958 + } 954 959 955 - return nvbios_outp_match(bios, type, mask, ver, hdr, cnt, len, info); 960 + return NULL; 956 961 } 957 962 958 - static bool 963 + static struct nvkm_output * 959 964 exec_script(struct nv50_disp_priv *priv, int head, int id) 960 965 { 961 966 struct nouveau_bios *bios = nouveau_bios(priv); 967 + struct nvkm_output *outp; 962 968 struct nvbios_outp info; 963 - struct dcb_output dcb; 964 969 u8 ver, hdr, cnt, len; 965 - u32 ctrl = 0x00000000; 966 - u16 data; 967 - int outp; 970 + u32 data, ctrl = 0; 971 + int or; 968 972 969 - for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { 970 - ctrl = nv_rd32(priv, 0x640180 + (outp * 0x20)); 973 + for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { 974 + ctrl = nv_rd32(priv, 0x640180 + (or * 0x20)); 971 975 if (ctrl & (1 << head)) 972 976 break; 973 977 } 974 978 975 - if (outp == 8) 976 - return false; 979 + if (or == 8) 980 + return NULL; 977 981 978 - data = exec_lookup(priv, head, outp, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); 979 - if (data) { 982 + outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info); 983 + if (outp) { 980 984 struct nvbios_init init = { 981 985 .subdev = nv_subdev(priv), 982 986 .bios = bios, 983 987 .offset = info.script[id], 984 - .outp = &dcb, 988 + .outp = &outp->info, 985 989 .crtc = head, 986 990 .execute = 1, 987 991 }; 988 992 989 - return nvbios_exec(&init) == 0; 993 + nvbios_exec(&init); 990 994 } 991 995 992 - return false; 996 + return outp; 993 997 } 994 998 995 - static u32 996 - exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, 997 - u32 pclk, struct dcb_output *dcb) 999 + static struct nvkm_output * 1000 + exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, u32 *conf) 998 1001 { 999 1002 struct nouveau_bios *bios = nouveau_bios(priv); 1003 + struct nvkm_output *outp; 1000 1004 struct nvbios_outp info1; 1001 1005 struct nvbios_ocfg info2; 1002 1006 u8 ver, hdr, cnt, len; 1003 - u32 ctrl = 0x00000000; 1004 - u32 data, conf = ~0; 1005 - int outp; 1007 + u32 data, ctrl = 0; 1008 + int or; 1006 1009 1007 - for (outp = 0; !(ctrl & (1 << head)) && outp < 8; outp++) { 1008 - ctrl = nv_rd32(priv, 0x660180 + (outp * 0x20)); 1010 + for (or = 0; !(ctrl & (1 << head)) && or < 8; or++) { 1011 + ctrl = nv_rd32(priv, 0x660180 + (or * 0x20)); 1009 1012 if (ctrl & (1 << head)) 1010 1013 break; 1011 1014 } 1012 1015 1013 - if (outp == 8) 1014 - return conf; 1016 + if (or == 8) 1017 + return NULL; 1015 1018 1016 - data = exec_lookup(priv, head, outp, ctrl, dcb, &ver, &hdr, &cnt, &len, &info1); 1017 - if (data == 0x0000) 1018 - return conf; 1019 + outp = exec_lookup(priv, head, or, ctrl, &data, &ver, &hdr, &cnt, &len, &info1); 1020 + if (!outp) 1021 + return NULL; 1019 1022 1020 - switch (dcb->type) { 1023 + switch (outp->info.type) { 1021 1024 case DCB_OUTPUT_TMDS: 1022 - conf = (ctrl & 0x00000f00) >> 8; 1025 + *conf = (ctrl & 0x00000f00) >> 8; 1023 1026 if (pclk >= 165000) 1024 - conf |= 0x0100; 1027 + *conf |= 0x0100; 1025 1028 break; 1026 1029 case DCB_OUTPUT_LVDS: 1027 - conf = priv->sor.lvdsconf; 1030 + *conf = priv->sor.lvdsconf; 1028 1031 break; 1029 1032 case DCB_OUTPUT_DP: 1030 - conf = (ctrl & 0x00000f00) >> 8; 1033 + *conf = (ctrl & 0x00000f00) >> 8; 1031 1034 break; 1032 1035 case DCB_OUTPUT_ANALOG: 1033 1036 default: 1034 - conf = 0x00ff; 1037 + *conf = 0x00ff; 1035 1038 break; 1036 1039 } 1037 1040 1038 - data = nvbios_ocfg_match(bios, data, conf, &ver, &hdr, &cnt, &len, &info2); 1041 + data = nvbios_ocfg_match(bios, data, *conf, &ver, &hdr, &cnt, &len, &info2); 1039 1042 if (data && id < 0xff) { 1040 1043 data = nvbios_oclk_match(bios, info2.clkcmp[id], pclk); 1041 1044 if (data) { ··· 1048 1041 .subdev = nv_subdev(priv), 1049 1042 .bios = bios, 1050 1043 .offset = data, 1051 - .outp = dcb, 1044 + .outp = &outp->info, 1052 1045 .crtc = head, 1053 1046 .execute = 1, 1054 1047 }; ··· 1057 1050 } 1058 1051 } 1059 1052 1060 - return conf; 1053 + return outp; 1061 1054 } 1062 1055 1063 1056 static void ··· 1069 1062 static void 1070 1063 nvd0_disp_intr_unk2_0(struct nv50_disp_priv *priv, int head) 1071 1064 { 1072 - exec_script(priv, head, 2); 1065 + struct nvkm_output *outp = exec_script(priv, head, 2); 1066 + 1067 + /* see note in nv50_disp_intr_unk20_0() */ 1068 + if (outp && outp->info.type == DCB_OUTPUT_DP) { 1069 + struct nvkm_output_dp *outpdp = (void *)outp; 1070 + struct nvbios_init init = { 1071 + .subdev = nv_subdev(priv), 1072 + .bios = nouveau_bios(priv), 1073 + .outp = &outp->info, 1074 + .crtc = head, 1075 + .offset = outpdp->info.script[4], 1076 + .execute = 1, 1077 + }; 1078 + 1079 + nvbios_exec(&init); 1080 + atomic_set(&outpdp->lt.done, 0); 1081 + } 1073 1082 } 1074 1083 1075 1084 static void ··· 1147 1124 static void 1148 1125 nvd0_disp_intr_unk2_2(struct nv50_disp_priv *priv, int head) 1149 1126 { 1150 - struct dcb_output outp; 1127 + struct nvkm_output *outp; 1151 1128 u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; 1152 - u32 conf = exec_clkcmp(priv, head, 0xff, pclk, &outp); 1153 - if (conf != ~0) { 1154 - u32 addr, data; 1129 + u32 conf, addr, data; 1155 1130 1156 - if (outp.type == DCB_OUTPUT_DP) { 1157 - u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); 1158 - switch ((sync & 0x000003c0) >> 6) { 1159 - case 6: pclk = pclk * 30 / 8; break; 1160 - case 5: pclk = pclk * 24 / 8; break; 1161 - case 2: 1162 - default: 1163 - pclk = pclk * 18 / 8; 1164 - break; 1165 - } 1131 + outp = exec_clkcmp(priv, head, 0xff, pclk, &conf); 1132 + if (!outp) 1133 + return; 1166 1134 1167 - nouveau_dp_train(&priv->base, priv->sor.dp, 1168 - &outp, head, pclk); 1135 + /* see note in nv50_disp_intr_unk20_2() */ 1136 + if (outp->info.type == DCB_OUTPUT_DP) { 1137 + u32 sync = nv_rd32(priv, 0x660404 + (head * 0x300)); 1138 + switch ((sync & 0x000003c0) >> 6) { 1139 + case 6: pclk = pclk * 30 / 8; break; 1140 + case 5: pclk = pclk * 24 / 8; break; 1141 + case 2: 1142 + default: 1143 + pclk = pclk * 18 / 8; 1144 + break; 1169 1145 } 1170 1146 1171 - exec_clkcmp(priv, head, 0, pclk, &outp); 1172 - 1173 - if (outp.type == DCB_OUTPUT_ANALOG) { 1174 - addr = 0x612280 + (ffs(outp.or) - 1) * 0x800; 1175 - data = 0x00000000; 1176 - } else { 1177 - if (outp.type == DCB_OUTPUT_DP) 1178 - nvd0_disp_intr_unk2_2_tu(priv, head, &outp); 1179 - addr = 0x612300 + (ffs(outp.or) - 1) * 0x800; 1180 - data = (conf & 0x0100) ? 0x00000101 : 0x00000000; 1181 - } 1182 - 1183 - nv_mask(priv, addr, 0x00000707, data); 1147 + if (nvkm_output_dp_train(outp, pclk, true)) 1148 + ERR("link not trained before attach\n"); 1184 1149 } 1150 + 1151 + exec_clkcmp(priv, head, 0, pclk, &conf); 1152 + 1153 + if (outp->info.type == DCB_OUTPUT_ANALOG) { 1154 + addr = 0x612280 + (ffs(outp->info.or) - 1) * 0x800; 1155 + data = 0x00000000; 1156 + } else { 1157 + if (outp->info.type == DCB_OUTPUT_DP) 1158 + nvd0_disp_intr_unk2_2_tu(priv, head, &outp->info); 1159 + addr = 0x612300 + (ffs(outp->info.or) - 1) * 0x800; 1160 + data = (conf & 0x0100) ? 0x00000101 : 0x00000000; 1161 + } 1162 + 1163 + nv_mask(priv, addr, 0x00000707, data); 1185 1164 } 1186 1165 1187 1166 static void 1188 1167 nvd0_disp_intr_unk4_0(struct nv50_disp_priv *priv, int head) 1189 1168 { 1190 - struct dcb_output outp; 1191 1169 u32 pclk = nv_rd32(priv, 0x660450 + (head * 0x300)) / 1000; 1192 - exec_clkcmp(priv, head, 1, pclk, &outp); 1170 + u32 conf; 1171 + 1172 + exec_clkcmp(priv, head, 1, pclk, &conf); 1193 1173 } 1194 1174 1195 1175 void ··· 1266 1240 chid, (mthd & 0x0000ffc), data, mthd, unkn); 1267 1241 1268 1242 if (chid == 0) { 1269 - switch (mthd) { 1243 + switch (mthd & 0xffc) { 1270 1244 case 0x0080: 1271 1245 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 0, 1272 1246 impl->mthd.core); ··· 1276 1250 } 1277 1251 } else 1278 1252 if (chid <= 4) { 1279 - switch (mthd) { 1253 + switch (mthd & 0xffc) { 1280 1254 case 0x0080: 1281 1255 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 1, 1282 1256 impl->mthd.base); ··· 1286 1260 } 1287 1261 } else 1288 1262 if (chid <= 8) { 1289 - switch (mthd) { 1263 + switch (mthd & 0xffc) { 1290 1264 case 0x0080: 1291 1265 nv50_disp_mthd_chan(priv, NV_DBG_ERROR, chid - 5, 1292 1266 impl->mthd.ovly); ··· 1343 1317 if (mask & intr) { 1344 1318 u32 stat = nv_rd32(priv, 0x6100bc + (i * 0x800)); 1345 1319 if (stat & 0x00000001) 1346 - nouveau_event_trigger(priv->base.vblank, i); 1320 + nouveau_event_trigger(priv->base.vblank, 1, i); 1347 1321 nv_mask(priv, 0x6100bc + (i * 0x800), 0, 0); 1348 1322 nv_rd32(priv, 0x6100c0 + (i * 0x800)); 1349 1323 } ··· 1378 1352 priv->sor.power = nv50_sor_power; 1379 1353 priv->sor.hda_eld = nvd0_hda_eld; 1380 1354 priv->sor.hdmi = nvd0_hdmi_ctrl; 1381 - priv->sor.dp = &nvd0_sor_dp_func; 1382 1355 return 0; 1383 1356 } 1357 + 1358 + struct nouveau_oclass * 1359 + nvd0_disp_outp_sclass[] = { 1360 + &nvd0_sor_dp_impl.base.base, 1361 + NULL 1362 + }; 1384 1363 1385 1364 struct nouveau_oclass * 1386 1365 nvd0_disp_oclass = &(struct nv50_disp_impl) { ··· 1396 1365 .init = _nouveau_disp_init, 1397 1366 .fini = _nouveau_disp_fini, 1398 1367 }, 1368 + .base.outp = nvd0_disp_outp_sclass, 1399 1369 .mthd.core = &nvd0_disp_mast_mthd_chan, 1400 1370 .mthd.base = &nvd0_disp_sync_mthd_chan, 1401 1371 .mthd.ovly = &nvd0_disp_ovly_mthd_chan,
+1 -1
drivers/gpu/drm/nouveau/core/engine/disp/nve0.c
··· 246 246 priv->sor.power = nv50_sor_power; 247 247 priv->sor.hda_eld = nvd0_hda_eld; 248 248 priv->sor.hdmi = nvd0_hdmi_ctrl; 249 - priv->sor.dp = &nvd0_sor_dp_func; 250 249 return 0; 251 250 } 252 251 ··· 258 259 .init = _nouveau_disp_init, 259 260 .fini = _nouveau_disp_fini, 260 261 }, 262 + .base.outp = nvd0_disp_outp_sclass, 261 263 .mthd.core = &nve0_disp_mast_mthd_chan, 262 264 .mthd.base = &nvd0_disp_sync_mthd_chan, 263 265 .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+1 -1
drivers/gpu/drm/nouveau/core/engine/disp/nvf0.c
··· 81 81 priv->sor.power = nv50_sor_power; 82 82 priv->sor.hda_eld = nvd0_hda_eld; 83 83 priv->sor.hdmi = nvd0_hdmi_ctrl; 84 - priv->sor.dp = &nvd0_sor_dp_func; 85 84 return 0; 86 85 } 87 86 ··· 93 94 .init = _nouveau_disp_init, 94 95 .fini = _nouveau_disp_fini, 95 96 }, 97 + .base.outp = nvd0_disp_outp_sclass, 96 98 .mthd.core = &nve0_disp_mast_mthd_chan, 97 99 .mthd.base = &nvd0_disp_sync_mthd_chan, 98 100 .mthd.ovly = &nve0_disp_ovly_mthd_chan,
+137
drivers/gpu/drm/nouveau/core/engine/disp/outp.c
··· 1 + /* 2 + * Copyright 2014 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/bios.h> 27 + #include <subdev/bios/conn.h> 28 + 29 + #include "outp.h" 30 + 31 + int 32 + _nvkm_output_fini(struct nouveau_object *object, bool suspend) 33 + { 34 + struct nvkm_output *outp = (void *)object; 35 + nv_ofuncs(outp->conn)->fini(nv_object(outp->conn), suspend); 36 + return nouveau_object_fini(&outp->base, suspend); 37 + } 38 + 39 + int 40 + _nvkm_output_init(struct nouveau_object *object) 41 + { 42 + struct nvkm_output *outp = (void *)object; 43 + int ret = nouveau_object_init(&outp->base); 44 + if (ret == 0) 45 + nv_ofuncs(outp->conn)->init(nv_object(outp->conn)); 46 + return 0; 47 + } 48 + 49 + void 50 + _nvkm_output_dtor(struct nouveau_object *object) 51 + { 52 + struct nvkm_output *outp = (void *)object; 53 + list_del(&outp->head); 54 + nouveau_object_ref(NULL, (void *)&outp->conn); 55 + nouveau_object_destroy(&outp->base); 56 + } 57 + 58 + int 59 + nvkm_output_create_(struct nouveau_object *parent, 60 + struct nouveau_object *engine, 61 + struct nouveau_oclass *oclass, 62 + struct dcb_output *dcbE, int index, 63 + int length, void **pobject) 64 + { 65 + struct nouveau_bios *bios = nouveau_bios(engine); 66 + struct nouveau_i2c *i2c = nouveau_i2c(parent); 67 + struct nouveau_disp *disp = (void *)engine; 68 + struct nvbios_connE connE; 69 + struct nvkm_output *outp; 70 + u8 ver, hdr; 71 + u32 data; 72 + int ret; 73 + 74 + ret = nouveau_object_create_(parent, engine, oclass, 0, length, pobject); 75 + outp = *pobject; 76 + if (ret) 77 + return ret; 78 + 79 + outp->info = *dcbE; 80 + outp->index = index; 81 + 82 + DBG("type %02x loc %d or %d link %d con %x edid %x bus %d head %x\n", 83 + dcbE->type, dcbE->location, dcbE->or, dcbE->type >= 2 ? 84 + dcbE->sorconf.link : 0, dcbE->connector, dcbE->i2c_index, 85 + dcbE->bus, dcbE->heads); 86 + 87 + outp->port = i2c->find(i2c, outp->info.i2c_index); 88 + outp->edid = outp->port; 89 + 90 + data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE); 91 + if (!data) { 92 + DBG("vbios connector data not found\n"); 93 + memset(&connE, 0x00, sizeof(connE)); 94 + connE.type = DCB_CONNECTOR_NONE; 95 + } 96 + 97 + ret = nouveau_object_ctor(parent, engine, nvkm_connector_oclass, 98 + &connE, outp->info.connector, 99 + (struct nouveau_object **)&outp->conn); 100 + if (ret < 0) { 101 + ERR("error %d creating connector, disabling\n", ret); 102 + return ret; 103 + } 104 + 105 + list_add_tail(&outp->head, &disp->outp); 106 + return 0; 107 + } 108 + 109 + int 110 + _nvkm_output_ctor(struct nouveau_object *parent, 111 + struct nouveau_object *engine, 112 + struct nouveau_oclass *oclass, void *dcbE, u32 index, 113 + struct nouveau_object **pobject) 114 + { 115 + struct nvkm_output *outp; 116 + int ret; 117 + 118 + ret = nvkm_output_create(parent, engine, oclass, dcbE, index, &outp); 119 + *pobject = nv_object(outp); 120 + if (ret) 121 + return ret; 122 + 123 + return 0; 124 + } 125 + 126 + struct nouveau_oclass * 127 + nvkm_output_oclass = &(struct nvkm_output_impl) { 128 + .base = { 129 + .handle = 0, 130 + .ofuncs = &(struct nouveau_ofuncs) { 131 + .ctor = _nvkm_output_ctor, 132 + .dtor = _nvkm_output_dtor, 133 + .init = _nvkm_output_init, 134 + .fini = _nvkm_output_fini, 135 + }, 136 + }, 137 + }.base;
+59
drivers/gpu/drm/nouveau/core/engine/disp/outp.h
··· 1 + #ifndef __NVKM_DISP_OUTP_H__ 2 + #define __NVKM_DISP_OUTP_H__ 3 + 4 + #include "priv.h" 5 + 6 + struct nvkm_output { 7 + struct nouveau_object base; 8 + struct list_head head; 9 + 10 + struct dcb_output info; 11 + int index; 12 + 13 + struct nouveau_i2c_port *port; 14 + struct nouveau_i2c_port *edid; 15 + 16 + struct nvkm_connector *conn; 17 + }; 18 + 19 + #define nvkm_output_create(p,e,c,b,i,d) \ 20 + nvkm_output_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) 21 + #define nvkm_output_destroy(d) ({ \ 22 + struct nvkm_output *_outp = (d); \ 23 + _nvkm_output_dtor(nv_object(_outp)); \ 24 + }) 25 + #define nvkm_output_init(d) ({ \ 26 + struct nvkm_output *_outp = (d); \ 27 + _nvkm_output_init(nv_object(_outp)); \ 28 + }) 29 + #define nvkm_output_fini(d,s) ({ \ 30 + struct nvkm_output *_outp = (d); \ 31 + _nvkm_output_fini(nv_object(_outp), (s)); \ 32 + }) 33 + 34 + int nvkm_output_create_(struct nouveau_object *, struct nouveau_object *, 35 + struct nouveau_oclass *, struct dcb_output *, 36 + int, int, void **); 37 + 38 + int _nvkm_output_ctor(struct nouveau_object *, struct nouveau_object *, 39 + struct nouveau_oclass *, void *, u32, 40 + struct nouveau_object **); 41 + void _nvkm_output_dtor(struct nouveau_object *); 42 + int _nvkm_output_init(struct nouveau_object *); 43 + int _nvkm_output_fini(struct nouveau_object *, bool); 44 + 45 + struct nvkm_output_impl { 46 + struct nouveau_oclass base; 47 + }; 48 + 49 + #ifndef MSG 50 + #define MSG(l,f,a...) do { \ 51 + struct nvkm_output *_outp = (void *)outp; \ 52 + nv_##l(nv_object(outp)->engine, "%02x:%04x:%04x: "f, _outp->index, \ 53 + _outp->info.hasht, _outp->info.hashm, ##a); \ 54 + } while(0) 55 + #define DBG(f,a...) MSG(debug, f, ##a) 56 + #define ERR(f,a...) MSG(error, f, ##a) 57 + #endif 58 + 59 + #endif
+276
drivers/gpu/drm/nouveau/core/engine/disp/outpdp.c
··· 1 + /* 2 + * Copyright 2014 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 + 27 + #include "outpdp.h" 28 + #include "conn.h" 29 + #include "dport.h" 30 + 31 + int 32 + nvkm_output_dp_train(struct nvkm_output *base, u32 datarate, bool wait) 33 + { 34 + struct nvkm_output_dp *outp = (void *)base; 35 + bool retrain = true; 36 + u8 link[2], stat[3]; 37 + u32 rate; 38 + int ret, i; 39 + 40 + /* check that the link is trained at a high enough rate */ 41 + ret = nv_rdaux(outp->base.edid, DPCD_LC00_LINK_BW_SET, link, 2); 42 + if (ret) { 43 + DBG("failed to read link config, assuming no sink\n"); 44 + goto done; 45 + } 46 + 47 + rate = link[0] * 27000 * (link[1] & DPCD_LC01_LANE_COUNT_SET); 48 + if (rate < ((datarate / 8) * 10)) { 49 + DBG("link not trained at sufficient rate\n"); 50 + goto done; 51 + } 52 + 53 + /* check that link is still trained */ 54 + ret = nv_rdaux(outp->base.edid, DPCD_LS02, stat, 3); 55 + if (ret) { 56 + DBG("failed to read link status, assuming no sink\n"); 57 + goto done; 58 + } 59 + 60 + if (stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE) { 61 + for (i = 0; i < (link[1] & DPCD_LC01_LANE_COUNT_SET); i++) { 62 + u8 lane = (stat[i >> 1] >> ((i & 1) * 4)) & 0x0f; 63 + if (!(lane & DPCD_LS02_LANE0_CR_DONE) || 64 + !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || 65 + !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) { 66 + DBG("lane %d not equalised\n", lane); 67 + goto done; 68 + } 69 + } 70 + retrain = false; 71 + } else { 72 + DBG("no inter-lane alignment\n"); 73 + } 74 + 75 + done: 76 + if (retrain || !atomic_read(&outp->lt.done)) { 77 + /* no sink, but still need to configure source */ 78 + if (outp->dpcd[DPCD_RC00_DPCD_REV] == 0x00) { 79 + outp->dpcd[DPCD_RC01_MAX_LINK_RATE] = 80 + outp->base.info.dpconf.link_bw; 81 + outp->dpcd[DPCD_RC02] = 82 + outp->base.info.dpconf.link_nr; 83 + } 84 + atomic_set(&outp->lt.done, 0); 85 + schedule_work(&outp->lt.work); 86 + } else { 87 + nouveau_event_get(outp->irq); 88 + } 89 + 90 + if (wait) { 91 + if (!wait_event_timeout(outp->lt.wait, 92 + atomic_read(&outp->lt.done), 93 + msecs_to_jiffies(2000))) 94 + ret = -ETIMEDOUT; 95 + } 96 + 97 + return ret; 98 + } 99 + 100 + static void 101 + nvkm_output_dp_enable(struct nvkm_output_dp *outp, bool present) 102 + { 103 + struct nouveau_i2c_port *port = outp->base.edid; 104 + if (present) { 105 + if (!outp->present) { 106 + nouveau_i2c(port)->acquire_pad(port, 0); 107 + DBG("aux power -> always\n"); 108 + outp->present = true; 109 + } 110 + nvkm_output_dp_train(&outp->base, 0, true); 111 + } else { 112 + if (outp->present) { 113 + nouveau_i2c(port)->release_pad(port); 114 + DBG("aux power -> demand\n"); 115 + outp->present = false; 116 + } 117 + atomic_set(&outp->lt.done, 0); 118 + } 119 + } 120 + 121 + static void 122 + nvkm_output_dp_detect(struct nvkm_output_dp *outp) 123 + { 124 + struct nouveau_i2c_port *port = outp->base.edid; 125 + int ret = nouveau_i2c(port)->acquire_pad(port, 0); 126 + if (ret == 0) { 127 + ret = nv_rdaux(outp->base.edid, DPCD_RC00_DPCD_REV, 128 + outp->dpcd, sizeof(outp->dpcd)); 129 + nvkm_output_dp_enable(outp, ret == 0); 130 + nouveau_i2c(port)->release_pad(port); 131 + } 132 + } 133 + 134 + static void 135 + nvkm_output_dp_service_work(struct work_struct *work) 136 + { 137 + struct nvkm_output_dp *outp = container_of(work, typeof(*outp), work); 138 + struct nouveau_disp *disp = nouveau_disp(outp); 139 + int type = atomic_xchg(&outp->pending, 0); 140 + u32 send = 0; 141 + 142 + if (type & (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG)) { 143 + nvkm_output_dp_detect(outp); 144 + if (type & NVKM_I2C_UNPLUG) 145 + send |= NVKM_HPD_UNPLUG; 146 + if (type & NVKM_I2C_PLUG) 147 + send |= NVKM_HPD_PLUG; 148 + nouveau_event_get(outp->base.conn->hpd.event); 149 + } 150 + 151 + if (type & NVKM_I2C_IRQ) { 152 + nvkm_output_dp_train(&outp->base, 0, true); 153 + send |= NVKM_HPD_IRQ; 154 + } 155 + 156 + nouveau_event_trigger(disp->hpd, send, outp->base.info.connector); 157 + } 158 + 159 + static int 160 + nvkm_output_dp_service(void *data, u32 type, int index) 161 + { 162 + struct nvkm_output_dp *outp = data; 163 + DBG("HPD: %d\n", type); 164 + atomic_or(type, &outp->pending); 165 + schedule_work(&outp->work); 166 + return NVKM_EVENT_DROP; 167 + } 168 + 169 + int 170 + _nvkm_output_dp_fini(struct nouveau_object *object, bool suspend) 171 + { 172 + struct nvkm_output_dp *outp = (void *)object; 173 + nouveau_event_put(outp->irq); 174 + nvkm_output_dp_enable(outp, false); 175 + return nvkm_output_fini(&outp->base, suspend); 176 + } 177 + 178 + int 179 + _nvkm_output_dp_init(struct nouveau_object *object) 180 + { 181 + struct nvkm_output_dp *outp = (void *)object; 182 + nvkm_output_dp_detect(outp); 183 + return nvkm_output_init(&outp->base); 184 + } 185 + 186 + void 187 + _nvkm_output_dp_dtor(struct nouveau_object *object) 188 + { 189 + struct nvkm_output_dp *outp = (void *)object; 190 + nouveau_event_ref(NULL, &outp->irq); 191 + nvkm_output_destroy(&outp->base); 192 + } 193 + 194 + int 195 + nvkm_output_dp_create_(struct nouveau_object *parent, 196 + struct nouveau_object *engine, 197 + struct nouveau_oclass *oclass, 198 + struct dcb_output *info, int index, 199 + int length, void **pobject) 200 + { 201 + struct nouveau_bios *bios = nouveau_bios(parent); 202 + struct nouveau_i2c *i2c = nouveau_i2c(parent); 203 + struct nvkm_output_dp *outp; 204 + u8 hdr, cnt, len; 205 + u32 data; 206 + int ret; 207 + 208 + ret = nvkm_output_create_(parent, engine, oclass, info, index, 209 + length, pobject); 210 + outp = *pobject; 211 + if (ret) 212 + return ret; 213 + 214 + nouveau_event_ref(NULL, &outp->base.conn->hpd.event); 215 + 216 + /* access to the aux channel is not optional... */ 217 + if (!outp->base.edid) { 218 + ERR("aux channel not found\n"); 219 + return -ENODEV; 220 + } 221 + 222 + /* nor is the bios data for this output... */ 223 + data = nvbios_dpout_match(bios, outp->base.info.hasht, 224 + outp->base.info.hashm, &outp->version, 225 + &hdr, &cnt, &len, &outp->info); 226 + if (!data) { 227 + ERR("no bios dp data\n"); 228 + return -ENODEV; 229 + } 230 + 231 + DBG("bios dp %02x %02x %02x %02x\n", outp->version, hdr, cnt, len); 232 + 233 + /* link training */ 234 + INIT_WORK(&outp->lt.work, nouveau_dp_train); 235 + init_waitqueue_head(&outp->lt.wait); 236 + atomic_set(&outp->lt.done, 0); 237 + 238 + /* link maintenance */ 239 + ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_IRQ, outp->base.edid->index, 240 + nvkm_output_dp_service, outp, &outp->irq); 241 + if (ret) { 242 + ERR("error monitoring aux irq event: %d\n", ret); 243 + return ret; 244 + } 245 + 246 + INIT_WORK(&outp->work, nvkm_output_dp_service_work); 247 + 248 + /* hotplug detect, replaces gpio-based mechanism with aux events */ 249 + ret = nouveau_event_new(i2c->ntfy, NVKM_I2C_PLUG | NVKM_I2C_UNPLUG, 250 + outp->base.edid->index, 251 + nvkm_output_dp_service, outp, 252 + &outp->base.conn->hpd.event); 253 + if (ret) { 254 + ERR("error monitoring aux hpd events: %d\n", ret); 255 + return ret; 256 + } 257 + 258 + return 0; 259 + } 260 + 261 + int 262 + _nvkm_output_dp_ctor(struct nouveau_object *parent, 263 + struct nouveau_object *engine, 264 + struct nouveau_oclass *oclass, void *info, u32 index, 265 + struct nouveau_object **pobject) 266 + { 267 + struct nvkm_output_dp *outp; 268 + int ret; 269 + 270 + ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp); 271 + *pobject = nv_object(outp); 272 + if (ret) 273 + return ret; 274 + 275 + return 0; 276 + }
+65
drivers/gpu/drm/nouveau/core/engine/disp/outpdp.h
··· 1 + #ifndef __NVKM_DISP_OUTP_DP_H__ 2 + #define __NVKM_DISP_OUTP_DP_H__ 3 + 4 + #include <subdev/bios.h> 5 + #include <subdev/bios/dp.h> 6 + 7 + #include "outp.h" 8 + 9 + struct nvkm_output_dp { 10 + struct nvkm_output base; 11 + 12 + struct nvbios_dpout info; 13 + u8 version; 14 + 15 + struct nouveau_eventh *irq; 16 + struct nouveau_eventh *hpd; 17 + struct work_struct work; 18 + atomic_t pending; 19 + bool present; 20 + u8 dpcd[16]; 21 + 22 + struct { 23 + struct work_struct work; 24 + wait_queue_head_t wait; 25 + atomic_t done; 26 + } lt; 27 + }; 28 + 29 + #define nvkm_output_dp_create(p,e,c,b,i,d) \ 30 + nvkm_output_dp_create_((p), (e), (c), (b), (i), sizeof(**d), (void **)d) 31 + #define nvkm_output_dp_destroy(d) ({ \ 32 + struct nvkm_output_dp *_outp = (d); \ 33 + _nvkm_output_dp_dtor(nv_object(_outp)); \ 34 + }) 35 + #define nvkm_output_dp_init(d) ({ \ 36 + struct nvkm_output_dp *_outp = (d); \ 37 + _nvkm_output_dp_init(nv_object(_outp)); \ 38 + }) 39 + #define nvkm_output_dp_fini(d,s) ({ \ 40 + struct nvkm_output_dp *_outp = (d); \ 41 + _nvkm_output_dp_fini(nv_object(_outp), (s)); \ 42 + }) 43 + 44 + int nvkm_output_dp_create_(struct nouveau_object *, struct nouveau_object *, 45 + struct nouveau_oclass *, struct dcb_output *, 46 + int, int, void **); 47 + 48 + int _nvkm_output_dp_ctor(struct nouveau_object *, struct nouveau_object *, 49 + struct nouveau_oclass *, void *, u32, 50 + struct nouveau_object **); 51 + void _nvkm_output_dp_dtor(struct nouveau_object *); 52 + int _nvkm_output_dp_init(struct nouveau_object *); 53 + int _nvkm_output_dp_fini(struct nouveau_object *, bool); 54 + 55 + struct nvkm_output_dp_impl { 56 + struct nvkm_output_impl base; 57 + int (*pattern)(struct nvkm_output_dp *, int); 58 + int (*lnk_pwr)(struct nvkm_output_dp *, int nr); 59 + int (*lnk_ctl)(struct nvkm_output_dp *, int nr, int bw, bool ef); 60 + int (*drv_ctl)(struct nvkm_output_dp *, int ln, int vs, int pe, int pc); 61 + }; 62 + 63 + int nvkm_output_dp_train(struct nvkm_output *, u32 rate, bool wait); 64 + 65 + #endif
+83 -43
drivers/gpu/drm/nouveau/core/engine/disp/piornv50.c
··· 33 33 #include "nv50.h" 34 34 35 35 /****************************************************************************** 36 + * TMDS 37 + *****************************************************************************/ 38 + 39 + static int 40 + nv50_pior_tmds_ctor(struct nouveau_object *parent, 41 + struct nouveau_object *engine, 42 + struct nouveau_oclass *oclass, void *info, u32 index, 43 + struct nouveau_object **pobject) 44 + { 45 + struct nouveau_i2c *i2c = nouveau_i2c(parent); 46 + struct nvkm_output *outp; 47 + int ret; 48 + 49 + ret = nvkm_output_create(parent, engine, oclass, info, index, &outp); 50 + *pobject = nv_object(outp); 51 + if (ret) 52 + return ret; 53 + 54 + outp->edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTDDC(outp->info.extdev)); 55 + return 0; 56 + } 57 + 58 + struct nvkm_output_impl 59 + nv50_pior_tmds_impl = { 60 + .base.handle = DCB_OUTPUT_TMDS | 0x0100, 61 + .base.ofuncs = &(struct nouveau_ofuncs) { 62 + .ctor = nv50_pior_tmds_ctor, 63 + .dtor = _nvkm_output_dtor, 64 + .init = _nvkm_output_init, 65 + .fini = _nvkm_output_fini, 66 + }, 67 + }; 68 + 69 + /****************************************************************************** 36 70 * DisplayPort 37 71 *****************************************************************************/ 38 - static struct nouveau_i2c_port * 39 - nv50_pior_dp_find(struct nouveau_disp *disp, struct dcb_output *outp) 72 + 73 + static int 74 + nv50_pior_dp_pattern(struct nvkm_output_dp *outp, int pattern) 40 75 { 41 - struct nouveau_i2c *i2c = nouveau_i2c(disp); 42 - return i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX(outp->extdev)); 76 + struct nouveau_i2c_port *port = outp->base.edid; 77 + if (port && port->func->pattern) 78 + return port->func->pattern(port, pattern); 79 + return port ? 0 : -ENODEV; 43 80 } 44 81 45 82 static int 46 - nv50_pior_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, 47 - int head, int pattern) 83 + nv50_pior_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) 48 84 { 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; 85 + return 0; 61 86 } 62 87 63 88 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) 89 + nv50_pior_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) 66 90 { 67 - struct nouveau_i2c_port *port; 68 - int ret = -EINVAL; 69 - 70 - port = nv50_pior_dp_find(disp, outp); 91 + struct nouveau_i2c_port *port = outp->base.edid; 71 92 if (port && port->func->lnk_ctl) 72 - ret = port->func->lnk_ctl(port, lane_nr, link_bw, enh); 73 - 74 - return ret; 93 + return port->func->lnk_ctl(port, nr, bw, ef); 94 + return port ? 0 : -ENODEV; 75 95 } 76 96 77 97 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) 98 + nv50_pior_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) 80 99 { 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; 100 + struct nouveau_i2c_port *port = outp->base.edid; 101 + if (port && port->func->drv_ctl) 102 + return port->func->drv_ctl(port, ln, vs, pe); 103 + return port ? 0 : -ENODEV; 93 104 } 94 105 95 - const struct nouveau_dp_func 96 - nv50_pior_dp_func = { 106 + static int 107 + nv50_pior_dp_ctor(struct nouveau_object *parent, 108 + struct nouveau_object *engine, 109 + struct nouveau_oclass *oclass, void *info, u32 index, 110 + struct nouveau_object **pobject) 111 + { 112 + struct nouveau_i2c *i2c = nouveau_i2c(parent); 113 + struct nvkm_output_dp *outp; 114 + int ret; 115 + 116 + ret = nvkm_output_dp_create(parent, engine, oclass, info, index, &outp); 117 + *pobject = nv_object(outp); 118 + if (ret) 119 + return ret; 120 + 121 + outp->base.edid = i2c->find_type(i2c, NV_I2C_TYPE_EXTAUX( 122 + outp->base.info.extdev)); 123 + return 0; 124 + } 125 + 126 + struct nvkm_output_dp_impl 127 + nv50_pior_dp_impl = { 128 + .base.base.handle = DCB_OUTPUT_DP | 0x0010, 129 + .base.base.ofuncs = &(struct nouveau_ofuncs) { 130 + .ctor = nv50_pior_dp_ctor, 131 + .dtor = _nvkm_output_dp_dtor, 132 + .init = _nvkm_output_dp_init, 133 + .fini = _nvkm_output_dp_fini, 134 + }, 97 135 .pattern = nv50_pior_dp_pattern, 136 + .lnk_pwr = nv50_pior_dp_lnk_pwr, 98 137 .lnk_ctl = nv50_pior_dp_lnk_ctl, 99 138 .drv_ctl = nv50_pior_dp_drv_ctl, 100 139 }; ··· 141 102 /****************************************************************************** 142 103 * General PIOR handling 143 104 *****************************************************************************/ 105 + 144 106 int 145 107 nv50_pior_power(struct nv50_disp_priv *priv, int or, u32 data) 146 108 {
+32
drivers/gpu/drm/nouveau/core/engine/disp/priv.h
··· 1 1 #ifndef __NVKM_DISP_PRIV_H__ 2 2 #define __NVKM_DISP_PRIV_H__ 3 3 4 + #include <subdev/bios.h> 5 + #include <subdev/bios/dcb.h> 6 + #include <subdev/bios/conn.h> 7 + 4 8 #include <engine/disp.h> 5 9 6 10 struct nouveau_disp_impl { 7 11 struct nouveau_oclass base; 12 + struct nouveau_oclass **outp; 13 + struct nouveau_oclass **conn; 8 14 }; 15 + 16 + #define nouveau_disp_create(p,e,c,h,i,x,d) \ 17 + nouveau_disp_create_((p), (e), (c), (h), (i), (x), \ 18 + sizeof(**d), (void **)d) 19 + #define nouveau_disp_destroy(d) ({ \ 20 + struct nouveau_disp *disp = (d); \ 21 + _nouveau_disp_dtor(nv_object(disp)); \ 22 + }) 23 + #define nouveau_disp_init(d) ({ \ 24 + struct nouveau_disp *disp = (d); \ 25 + _nouveau_disp_init(nv_object(disp)); \ 26 + }) 27 + #define nouveau_disp_fini(d,s) ({ \ 28 + struct nouveau_disp *disp = (d); \ 29 + _nouveau_disp_fini(nv_object(disp), (s)); \ 30 + }) 31 + 32 + int nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *, 33 + struct nouveau_oclass *, int heads, 34 + const char *, const char *, int, void **); 35 + void _nouveau_disp_dtor(struct nouveau_object *); 36 + int _nouveau_disp_init(struct nouveau_object *); 37 + int _nouveau_disp_fini(struct nouveau_object *, bool); 38 + 39 + extern struct nouveau_oclass *nvkm_output_oclass; 40 + extern struct nouveau_oclass *nvkm_connector_oclass; 9 41 10 42 #endif
+28
drivers/gpu/drm/nouveau/core/engine/disp/sornv50.c
··· 47 47 nv50_sor_mthd(struct nouveau_object *object, u32 mthd, void *args, u32 size) 48 48 { 49 49 struct nv50_disp_priv *priv = (void *)object->engine; 50 + const u8 type = (mthd & NV50_DISP_SOR_MTHD_TYPE) >> 12; 50 51 const u8 head = (mthd & NV50_DISP_SOR_MTHD_HEAD) >> 3; 52 + const u8 link = (mthd & NV50_DISP_SOR_MTHD_LINK) >> 2; 51 53 const u8 or = (mthd & NV50_DISP_SOR_MTHD_OR); 54 + const u16 mask = (0x0100 << head) | (0x0040 << link) | (0x0001 << or); 55 + struct nvkm_output *outp = NULL, *temp; 52 56 u32 data; 53 57 int ret = -EINVAL; 54 58 ··· 60 56 return -EINVAL; 61 57 data = *(u32 *)args; 62 58 59 + list_for_each_entry(temp, &priv->base.outp, head) { 60 + if ((temp->info.hasht & 0xff) == type && 61 + (temp->info.hashm & mask) == mask) { 62 + outp = temp; 63 + break; 64 + } 65 + } 63 66 64 67 switch (mthd & ~0x3f) { 65 68 case NV50_DISP_SOR_PWR: ··· 81 70 case NV50_DISP_SOR_LVDS_SCRIPT: 82 71 priv->sor.lvdsconf = data & NV50_DISP_SOR_LVDS_SCRIPT_ID; 83 72 ret = 0; 73 + break; 74 + case NV94_DISP_SOR_DP_PWR: 75 + if (outp) { 76 + struct nvkm_output_dp *outpdp = (void *)outp; 77 + switch (data) { 78 + case NV94_DISP_SOR_DP_PWR_STATE_OFF: 79 + ((struct nvkm_output_dp_impl *)nv_oclass(outp)) 80 + ->lnk_pwr(outpdp, 0); 81 + atomic_set(&outpdp->lt.done, 0); 82 + break; 83 + case NV94_DISP_SOR_DP_PWR_STATE_ON: 84 + nvkm_output_dp_train(&outpdp->base, 0, true); 85 + break; 86 + default: 87 + return -EINVAL; 88 + } 89 + } 84 90 break; 85 91 default: 86 92 BUG_ON(1);
+60 -39
drivers/gpu/drm/nouveau/core/engine/disp/sornv94.c
··· 29 29 #include <subdev/bios/dcb.h> 30 30 #include <subdev/bios/dp.h> 31 31 #include <subdev/bios/init.h> 32 + #include <subdev/timer.h> 32 33 33 34 #include "nv50.h" 35 + #include "outpdp.h" 34 36 35 37 static inline u32 36 - nv94_sor_soff(struct dcb_output *outp) 38 + nv94_sor_soff(struct nvkm_output_dp *outp) 37 39 { 38 - return (ffs(outp->or) - 1) * 0x800; 40 + return (ffs(outp->base.info.or) - 1) * 0x800; 39 41 } 40 42 41 43 static inline u32 42 - nv94_sor_loff(struct dcb_output *outp) 44 + nv94_sor_loff(struct nvkm_output_dp *outp) 43 45 { 44 - return nv94_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; 46 + return nv94_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80; 45 47 } 46 48 47 49 static inline u32 ··· 57 55 } 58 56 59 57 static int 60 - nv94_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, 61 - int head, int pattern) 58 + nv94_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) 62 59 { 63 - struct nv50_disp_priv *priv = (void *)disp; 60 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 64 61 const u32 loff = nv94_sor_loff(outp); 65 62 nv_mask(priv, 0x61c10c + loff, 0x0f000000, pattern << 24); 66 63 return 0; 67 64 } 68 65 69 - static int 70 - nv94_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 71 - int head, int link_nr, int link_bw, bool enh_frame) 66 + int 67 + nv94_sor_dp_lnk_pwr(struct nvkm_output_dp *outp, int nr) 72 68 { 73 - struct nv50_disp_priv *priv = (void *)disp; 69 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 74 70 const u32 soff = nv94_sor_soff(outp); 75 71 const u32 loff = nv94_sor_loff(outp); 76 - u32 dpctrl = 0x00000000; 77 - u32 clksor = 0x00000000; 78 - u32 lane = 0; 79 - int i; 72 + u32 mask = 0, i; 80 73 81 - dpctrl |= ((1 << link_nr) - 1) << 16; 82 - if (enh_frame) 83 - dpctrl |= 0x00004000; 84 - if (link_bw > 0x06) 85 - clksor |= 0x00040000; 74 + for (i = 0; i < nr; i++) 75 + mask |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3); 86 76 87 - for (i = 0; i < link_nr; i++) 88 - lane |= 1 << (nv94_sor_dp_lane_map(priv, i) >> 3); 89 - 90 - nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor); 91 - nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); 92 - nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane); 77 + nv_mask(priv, 0x61c130 + loff, 0x0000000f, mask); 78 + nv_mask(priv, 0x61c034 + soff, 0x80000000, 0x80000000); 79 + nv_wait(priv, 0x61c034 + soff, 0x80000000, 0x00000000); 93 80 return 0; 94 81 } 95 82 96 83 static int 97 - nv94_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 98 - int head, int lane, int swing, int preem) 84 + nv94_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) 99 85 { 100 - struct nouveau_bios *bios = nouveau_bios(disp); 101 - struct nv50_disp_priv *priv = (void *)disp; 102 - const u32 shift = nv94_sor_dp_lane_map(priv, lane); 86 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 87 + const u32 soff = nv94_sor_soff(outp); 88 + const u32 loff = nv94_sor_loff(outp); 89 + u32 dpctrl = 0x00000000; 90 + u32 clksor = 0x00000000; 91 + 92 + dpctrl |= ((1 << nr) - 1) << 16; 93 + if (ef) 94 + dpctrl |= 0x00004000; 95 + if (bw > 0x06) 96 + clksor |= 0x00040000; 97 + 98 + nv_mask(priv, 0x614300 + soff, 0x000c0000, clksor); 99 + nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); 100 + return 0; 101 + } 102 + 103 + static int 104 + nv94_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) 105 + { 106 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 107 + struct nouveau_bios *bios = nouveau_bios(priv); 108 + const u32 shift = nv94_sor_dp_lane_map(priv, ln); 103 109 const u32 loff = nv94_sor_loff(outp); 104 110 u32 addr, data[3]; 105 111 u8 ver, hdr, cnt, len; 106 112 struct nvbios_dpout info; 107 113 struct nvbios_dpcfg ocfg; 108 114 109 - addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, 115 + addr = nvbios_dpout_match(bios, outp->base.info.hasht, 116 + outp->base.info.hashm, 110 117 &ver, &hdr, &cnt, &len, &info); 111 118 if (!addr) 112 119 return -ENODEV; 113 120 114 - addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, 121 + addr = nvbios_dpcfg_match(bios, addr, 0, vs, pe, 115 122 &ver, &hdr, &cnt, &len, &ocfg); 116 123 if (!addr) 117 124 return -EINVAL; 118 125 119 126 data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); 120 127 data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); 121 - data[2] = nv_rd32(priv, 0x61c130 + loff) & ~(0x0000ff00); 122 - nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.drv << shift)); 123 - nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pre << shift)); 124 - nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.unk << 8)); 128 + data[2] = nv_rd32(priv, 0x61c130 + loff); 129 + if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) 130 + data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); 131 + nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); 132 + nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); 133 + nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8)); 125 134 return 0; 126 135 } 127 136 128 - const struct nouveau_dp_func 129 - nv94_sor_dp_func = { 137 + struct nvkm_output_dp_impl 138 + nv94_sor_dp_impl = { 139 + .base.base.handle = DCB_OUTPUT_DP, 140 + .base.base.ofuncs = &(struct nouveau_ofuncs) { 141 + .ctor = _nvkm_output_dp_ctor, 142 + .dtor = _nvkm_output_dp_dtor, 143 + .init = _nvkm_output_dp_init, 144 + .fini = _nvkm_output_dp_fini, 145 + }, 130 146 .pattern = nv94_sor_dp_pattern, 147 + .lnk_pwr = nv94_sor_dp_lnk_pwr, 131 148 .lnk_ctl = nv94_sor_dp_lnk_ctl, 132 149 .drv_ctl = nv94_sor_dp_drv_ctl, 133 150 };
+38 -34
drivers/gpu/drm/nouveau/core/engine/disp/sornvd0.c
··· 29 29 #include <subdev/bios/dcb.h> 30 30 #include <subdev/bios/dp.h> 31 31 #include <subdev/bios/init.h> 32 + #include <subdev/timer.h> 32 33 33 34 #include "nv50.h" 34 35 35 36 static inline u32 36 - nvd0_sor_soff(struct dcb_output *outp) 37 + nvd0_sor_soff(struct nvkm_output_dp *outp) 37 38 { 38 - return (ffs(outp->or) - 1) * 0x800; 39 + return (ffs(outp->base.info.or) - 1) * 0x800; 39 40 } 40 41 41 42 static inline u32 42 - nvd0_sor_loff(struct dcb_output *outp) 43 + nvd0_sor_loff(struct nvkm_output_dp *outp) 43 44 { 44 - return nvd0_sor_soff(outp) + !(outp->sorconf.link & 1) * 0x80; 45 + return nvd0_sor_soff(outp) + !(outp->base.info.sorconf.link & 1) * 0x80; 45 46 } 46 47 47 48 static inline u32 ··· 53 52 } 54 53 55 54 static int 56 - nvd0_sor_dp_pattern(struct nouveau_disp *disp, struct dcb_output *outp, 57 - int head, int pattern) 55 + nvd0_sor_dp_pattern(struct nvkm_output_dp *outp, int pattern) 58 56 { 59 - struct nv50_disp_priv *priv = (void *)disp; 57 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 60 58 const u32 loff = nvd0_sor_loff(outp); 61 59 nv_mask(priv, 0x61c110 + loff, 0x0f0f0f0f, 0x01010101 * pattern); 62 60 return 0; 63 61 } 64 62 65 63 static int 66 - nvd0_sor_dp_lnk_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 67 - int head, int link_nr, int link_bw, bool enh_frame) 64 + nvd0_sor_dp_lnk_ctl(struct nvkm_output_dp *outp, int nr, int bw, bool ef) 68 65 { 69 - struct nv50_disp_priv *priv = (void *)disp; 66 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 70 67 const u32 soff = nvd0_sor_soff(outp); 71 68 const u32 loff = nvd0_sor_loff(outp); 72 69 u32 dpctrl = 0x00000000; 73 70 u32 clksor = 0x00000000; 74 - u32 lane = 0; 75 - int i; 76 71 77 - clksor |= link_bw << 18; 78 - dpctrl |= ((1 << link_nr) - 1) << 16; 79 - if (enh_frame) 72 + clksor |= bw << 18; 73 + dpctrl |= ((1 << nr) - 1) << 16; 74 + if (ef) 80 75 dpctrl |= 0x00004000; 81 - 82 - for (i = 0; i < link_nr; i++) 83 - lane |= 1 << (nvd0_sor_dp_lane_map(priv, i) >> 3); 84 76 85 77 nv_mask(priv, 0x612300 + soff, 0x007c0000, clksor); 86 78 nv_mask(priv, 0x61c10c + loff, 0x001f4000, dpctrl); 87 - nv_mask(priv, 0x61c130 + loff, 0x0000000f, lane); 88 79 return 0; 89 80 } 90 81 91 82 static int 92 - nvd0_sor_dp_drv_ctl(struct nouveau_disp *disp, struct dcb_output *outp, 93 - int head, int lane, int swing, int preem) 83 + nvd0_sor_dp_drv_ctl(struct nvkm_output_dp *outp, int ln, int vs, int pe, int pc) 94 84 { 95 - struct nouveau_bios *bios = nouveau_bios(disp); 96 - struct nv50_disp_priv *priv = (void *)disp; 97 - const u32 shift = nvd0_sor_dp_lane_map(priv, lane); 85 + struct nv50_disp_priv *priv = (void *)nouveau_disp(outp); 86 + struct nouveau_bios *bios = nouveau_bios(priv); 87 + const u32 shift = nvd0_sor_dp_lane_map(priv, ln); 98 88 const u32 loff = nvd0_sor_loff(outp); 99 - u32 addr, data[3]; 89 + u32 addr, data[4]; 100 90 u8 ver, hdr, cnt, len; 101 91 struct nvbios_dpout info; 102 92 struct nvbios_dpcfg ocfg; 103 93 104 - addr = nvbios_dpout_match(bios, outp->hasht, outp->hashm, 94 + addr = nvbios_dpout_match(bios, outp->base.info.hasht, 95 + outp->base.info.hashm, 105 96 &ver, &hdr, &cnt, &len, &info); 106 97 if (!addr) 107 98 return -ENODEV; 108 99 109 - addr = nvbios_dpcfg_match(bios, addr, 0, swing, preem, 100 + addr = nvbios_dpcfg_match(bios, addr, pc, vs, pe, 110 101 &ver, &hdr, &cnt, &len, &ocfg); 111 102 if (!addr) 112 103 return -EINVAL; 113 104 114 105 data[0] = nv_rd32(priv, 0x61c118 + loff) & ~(0x000000ff << shift); 115 106 data[1] = nv_rd32(priv, 0x61c120 + loff) & ~(0x000000ff << shift); 116 - data[2] = nv_rd32(priv, 0x61c130 + loff) & ~(0x0000ff00); 117 - nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.drv << shift)); 118 - nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pre << shift)); 119 - nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.unk << 8)); 120 - nv_mask(priv, 0x61c13c + loff, 0x00000000, 0x00000000); 107 + data[2] = nv_rd32(priv, 0x61c130 + loff); 108 + if ((data[2] & 0x0000ff00) < (ocfg.tx_pu << 8) || ln == 0) 109 + data[2] = (data[2] & ~0x0000ff00) | (ocfg.tx_pu << 8); 110 + nv_wr32(priv, 0x61c118 + loff, data[0] | (ocfg.dc << shift)); 111 + nv_wr32(priv, 0x61c120 + loff, data[1] | (ocfg.pe << shift)); 112 + nv_wr32(priv, 0x61c130 + loff, data[2] | (ocfg.tx_pu << 8)); 113 + data[3] = nv_rd32(priv, 0x61c13c + loff) & ~(0x000000ff << shift); 114 + nv_wr32(priv, 0x61c13c + loff, data[3] | (ocfg.pc << shift)); 121 115 return 0; 122 116 } 123 117 124 - const struct nouveau_dp_func 125 - nvd0_sor_dp_func = { 118 + struct nvkm_output_dp_impl 119 + nvd0_sor_dp_impl = { 120 + .base.base.handle = DCB_OUTPUT_DP, 121 + .base.base.ofuncs = &(struct nouveau_ofuncs) { 122 + .ctor = _nvkm_output_dp_ctor, 123 + .dtor = _nvkm_output_dp_dtor, 124 + .init = _nvkm_output_dp_init, 125 + .fini = _nvkm_output_dp_fini, 126 + }, 126 127 .pattern = nvd0_sor_dp_pattern, 128 + .lnk_pwr = nv94_sor_dp_lnk_pwr, 127 129 .lnk_ctl = nvd0_sor_dp_lnk_ctl, 128 130 .drv_ctl = nvd0_sor_dp_drv_ctl, 129 131 };
+3 -3
drivers/gpu/drm/nouveau/core/engine/fifo/base.c
··· 91 91 if (!chan->user) 92 92 return -EFAULT; 93 93 94 - nouveau_event_trigger(priv->cevent, 0); 94 + nouveau_event_trigger(priv->cevent, 1, 0); 95 95 96 96 chan->size = size; 97 97 return 0; ··· 194 194 if (!priv->channel) 195 195 return -ENOMEM; 196 196 197 - ret = nouveau_event_create(1, &priv->cevent); 197 + ret = nouveau_event_create(1, 1, &priv->cevent); 198 198 if (ret) 199 199 return ret; 200 200 201 - ret = nouveau_event_create(1, &priv->uevent); 201 + ret = nouveau_event_create(1, 1, &priv->uevent); 202 202 if (ret) 203 203 return ret; 204 204
+1 -1
drivers/gpu/drm/nouveau/core/engine/fifo/nv04.c
··· 539 539 } 540 540 541 541 if (status & 0x40000000) { 542 - nouveau_event_trigger(priv->base.uevent, 0); 542 + nouveau_event_trigger(priv->base.uevent, 1, 0); 543 543 nv_wr32(priv, 0x002100, 0x40000000); 544 544 status &= ~0x40000000; 545 545 }
+2 -2
drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c
··· 389 389 ******************************************************************************/ 390 390 391 391 static void 392 - nv84_fifo_uevent_enable(struct nouveau_event *event, int index) 392 + nv84_fifo_uevent_enable(struct nouveau_event *event, int type, int index) 393 393 { 394 394 struct nv84_fifo_priv *priv = event->priv; 395 395 nv_mask(priv, 0x002140, 0x40000000, 0x40000000); 396 396 } 397 397 398 398 static void 399 - nv84_fifo_uevent_disable(struct nouveau_event *event, int index) 399 + nv84_fifo_uevent_disable(struct nouveau_event *event, int type, int index) 400 400 { 401 401 struct nv84_fifo_priv *priv = event->priv; 402 402 nv_mask(priv, 0x002140, 0x40000000, 0x00000000);
+3 -3
drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c
··· 730 730 for (unkn = 0; unkn < 8; unkn++) { 731 731 u32 ints = (intr >> (unkn * 0x04)) & inte; 732 732 if (ints & 0x1) { 733 - nouveau_event_trigger(priv->base.uevent, 0); 733 + nouveau_event_trigger(priv->base.uevent, 1, 0); 734 734 ints &= ~1; 735 735 } 736 736 if (ints) { ··· 827 827 } 828 828 829 829 static void 830 - nvc0_fifo_uevent_enable(struct nouveau_event *event, int index) 830 + nvc0_fifo_uevent_enable(struct nouveau_event *event, int type, int index) 831 831 { 832 832 struct nvc0_fifo_priv *priv = event->priv; 833 833 nv_mask(priv, 0x002140, 0x80000000, 0x80000000); 834 834 } 835 835 836 836 static void 837 - nvc0_fifo_uevent_disable(struct nouveau_event *event, int index) 837 + nvc0_fifo_uevent_disable(struct nouveau_event *event, int type, int index) 838 838 { 839 839 struct nvc0_fifo_priv *priv = event->priv; 840 840 nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
+3 -3
drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c
··· 859 859 static void 860 860 nve0_fifo_intr_engine(struct nve0_fifo_priv *priv) 861 861 { 862 - nouveau_event_trigger(priv->base.uevent, 0); 862 + nouveau_event_trigger(priv->base.uevent, 1, 0); 863 863 } 864 864 865 865 static void ··· 952 952 } 953 953 954 954 static void 955 - nve0_fifo_uevent_enable(struct nouveau_event *event, int index) 955 + nve0_fifo_uevent_enable(struct nouveau_event *event, int type, int index) 956 956 { 957 957 struct nve0_fifo_priv *priv = event->priv; 958 958 nv_mask(priv, 0x002140, 0x80000000, 0x80000000); 959 959 } 960 960 961 961 static void 962 - nve0_fifo_uevent_disable(struct nouveau_event *event, int index) 962 + nve0_fifo_uevent_disable(struct nouveau_event *event, int type, int index) 963 963 { 964 964 struct nve0_fifo_priv *priv = event->priv; 965 965 nv_mask(priv, 0x002140, 0x80000000, 0x00000000);
+2 -2
drivers/gpu/drm/nouveau/core/engine/software/nv50.c
··· 124 124 ******************************************************************************/ 125 125 126 126 static int 127 - nv50_software_vblsem_release(void *data, int head) 127 + nv50_software_vblsem_release(void *data, u32 type, int head) 128 128 { 129 129 struct nv50_software_chan *chan = data; 130 130 struct nv50_software_priv *priv = (void *)nv_object(chan)->engine; ··· 183 183 return -ENOMEM; 184 184 185 185 for (i = 0; i < chan->vblank.nr_event; i++) { 186 - ret = nouveau_event_new(pdisp->vblank, i, pclass->vblank, 186 + ret = nouveau_event_new(pdisp->vblank, 1, i, pclass->vblank, 187 187 chan, &chan->vblank.event[i]); 188 188 if (ret) 189 189 return ret;
+1 -1
drivers/gpu/drm/nouveau/core/engine/software/nv50.h
··· 19 19 20 20 struct nv50_software_cclass { 21 21 struct nouveau_oclass base; 22 - int (*vblank)(void *, int); 22 + int (*vblank)(void *, u32, int); 23 23 }; 24 24 25 25 struct nv50_software_chan {
+1 -1
drivers/gpu/drm/nouveau/core/engine/software/nvc0.c
··· 104 104 ******************************************************************************/ 105 105 106 106 static int 107 - nvc0_software_vblsem_release(void *data, int head) 107 + nvc0_software_vblsem_release(void *data, u32 type, int head) 108 108 { 109 109 struct nv50_software_chan *chan = data; 110 110 struct nv50_software_priv *priv = (void *)nv_object(chan)->engine;
+4
drivers/gpu/drm/nouveau/core/include/core/class.h
··· 295 295 #define NV84_DISP_SOR_HDMI_PWR_REKEY 0x0000007f 296 296 #define NV50_DISP_SOR_LVDS_SCRIPT 0x00013000 297 297 #define NV50_DISP_SOR_LVDS_SCRIPT_ID 0x0000ffff 298 + #define NV94_DISP_SOR_DP_PWR 0x00016000 299 + #define NV94_DISP_SOR_DP_PWR_STATE 0x00000001 300 + #define NV94_DISP_SOR_DP_PWR_STATE_OFF 0x00000000 301 + #define NV94_DISP_SOR_DP_PWR_STATE_ON 0x00000001 298 302 299 303 #define NV50_DISP_DAC_MTHD 0x00020000 300 304 #define NV50_DISP_DAC_MTHD_TYPE 0x0000f000
+15 -14
drivers/gpu/drm/nouveau/core/include/core/event.h
··· 12 12 struct nouveau_event *event; 13 13 struct list_head head; 14 14 unsigned long flags; 15 + u32 types; 15 16 int index; 16 - int (*func)(void *, int); 17 + int (*func)(void *, u32, int); 17 18 void *priv; 18 19 }; 19 20 20 21 struct nouveau_event { 21 - spinlock_t list_lock; 22 - spinlock_t refs_lock; 23 - 24 22 void *priv; 25 - void (*enable)(struct nouveau_event *, int index); 26 - void (*disable)(struct nouveau_event *, int index); 23 + int (*check)(struct nouveau_event *, u32 type, int index); 24 + void (*enable)(struct nouveau_event *, int type, int index); 25 + void (*disable)(struct nouveau_event *, int type, int index); 27 26 27 + int types_nr; 28 28 int index_nr; 29 - struct { 30 - struct list_head list; 31 - int refs; 32 - } index[]; 29 + 30 + spinlock_t list_lock; 31 + struct list_head *list; 32 + spinlock_t refs_lock; 33 + int refs[]; 33 34 }; 34 35 35 - int nouveau_event_create(int index_nr, struct nouveau_event **); 36 + int nouveau_event_create(int types_nr, int index_nr, struct nouveau_event **); 36 37 void nouveau_event_destroy(struct nouveau_event **); 37 - void nouveau_event_trigger(struct nouveau_event *, int index); 38 + void nouveau_event_trigger(struct nouveau_event *, u32 types, int index); 38 39 39 - int nouveau_event_new(struct nouveau_event *, int index, 40 - int (*func)(void *, int), void *, 40 + int nouveau_event_new(struct nouveau_event *, u32 types, int index, 41 + int (*func)(void *, u32, int), void *, 41 42 struct nouveau_eventh **); 42 43 void nouveau_event_ref(struct nouveau_eventh *, struct nouveau_eventh **); 43 44 void nouveau_event_get(struct nouveau_eventh *);
+11 -19
drivers/gpu/drm/nouveau/core/include/engine/disp.h
··· 6 6 #include <core/device.h> 7 7 #include <core/event.h> 8 8 9 + enum nvkm_hpd_event { 10 + NVKM_HPD_PLUG = 1, 11 + NVKM_HPD_UNPLUG = 2, 12 + NVKM_HPD_IRQ = 4, 13 + NVKM_HPD = (NVKM_HPD_PLUG | NVKM_HPD_UNPLUG | NVKM_HPD_IRQ) 14 + }; 15 + 9 16 struct nouveau_disp { 10 17 struct nouveau_engine base; 18 + 19 + struct list_head outp; 20 + struct nouveau_event *hpd; 21 + 11 22 struct nouveau_event *vblank; 12 23 }; 13 24 ··· 27 16 { 28 17 return (void *)nv_device(obj)->subdev[NVDEV_ENGINE_DISP]; 29 18 } 30 - 31 - #define nouveau_disp_create(p,e,c,h,i,x,d) \ 32 - nouveau_disp_create_((p), (e), (c), (h), (i), (x), \ 33 - sizeof(**d), (void **)d) 34 - #define nouveau_disp_destroy(d) ({ \ 35 - struct nouveau_disp *disp = (d); \ 36 - _nouveau_disp_dtor(nv_object(disp)); \ 37 - }) 38 - #define nouveau_disp_init(d) \ 39 - nouveau_engine_init(&(d)->base) 40 - #define nouveau_disp_fini(d,s) \ 41 - nouveau_engine_fini(&(d)->base, (s)) 42 - 43 - int nouveau_disp_create_(struct nouveau_object *, struct nouveau_object *, 44 - struct nouveau_oclass *, int heads, 45 - const char *, const char *, int, void **); 46 - void _nouveau_disp_dtor(struct nouveau_object *); 47 - #define _nouveau_disp_init _nouveau_engine_init 48 - #define _nouveau_disp_fini _nouveau_engine_fini 49 19 50 20 extern struct nouveau_oclass *nv04_disp_oclass; 51 21 extern struct nouveau_oclass *nv50_disp_oclass;
+20 -2
drivers/gpu/drm/nouveau/core/include/subdev/bios/conn.h
··· 22 22 DCB_CONNECTOR_NONE = 0xff 23 23 }; 24 24 25 - u16 dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); 26 - u16 dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len); 25 + struct nvbios_connT { 26 + }; 27 + 28 + u32 nvbios_connTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len); 29 + u32 nvbios_connTp(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 30 + struct nvbios_connT *info); 31 + 32 + struct nvbios_connE { 33 + u8 type; 34 + u8 location; 35 + u8 hpd; 36 + u8 dp; 37 + u8 di; 38 + u8 sr; 39 + u8 lcdid; 40 + }; 41 + 42 + u32 nvbios_connEe(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *hdr); 43 + u32 nvbios_connEp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *hdr, 44 + struct nvbios_connE *info); 27 45 28 46 #endif
+5 -4
drivers/gpu/drm/nouveau/core/include/subdev/bios/dp.h
··· 17 17 struct nvbios_dpout *); 18 18 19 19 struct nvbios_dpcfg { 20 - u8 drv; 21 - u8 pre; 22 - u8 unk; 20 + u8 pc; 21 + u8 dc; 22 + u8 pe; 23 + u8 tx_pu; 23 24 }; 24 25 25 26 u16 ··· 28 27 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 29 28 struct nvbios_dpcfg *); 30 29 u16 31 - nvbios_dpcfg_match(struct nouveau_bios *, u16 outp, u8 un, u8 vs, u8 pe, 30 + nvbios_dpcfg_match(struct nouveau_bios *, u16 outp, u8 pc, u8 vs, u8 pe, 32 31 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 33 32 struct nvbios_dpcfg *); 34 33
+11 -23
drivers/gpu/drm/nouveau/core/include/subdev/gpio.h
··· 8 8 #include <subdev/bios.h> 9 9 #include <subdev/bios/gpio.h> 10 10 11 + enum nvkm_gpio_event { 12 + NVKM_GPIO_HI = 1, 13 + NVKM_GPIO_LO = 2, 14 + NVKM_GPIO_TOGGLED = (NVKM_GPIO_HI | NVKM_GPIO_LO), 15 + }; 16 + 11 17 struct nouveau_gpio { 12 18 struct nouveau_subdev base; 13 19 14 20 struct nouveau_event *events; 15 21 16 - /* hardware interfaces */ 17 22 void (*reset)(struct nouveau_gpio *, u8 func); 18 - int (*drive)(struct nouveau_gpio *, int line, int dir, int out); 19 - int (*sense)(struct nouveau_gpio *, int line); 20 - 21 - /* software interfaces */ 22 23 int (*find)(struct nouveau_gpio *, int idx, u8 tag, u8 line, 23 24 struct dcb_gpio_func *); 24 25 int (*set)(struct nouveau_gpio *, int idx, u8 tag, u8 line, int state); ··· 32 31 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_GPIO]; 33 32 } 34 33 35 - #define nouveau_gpio_create(p,e,o,l,d) \ 36 - nouveau_gpio_create_((p), (e), (o), (l), sizeof(**d), (void **)d) 37 - #define nouveau_gpio_destroy(p) ({ \ 38 - struct nouveau_gpio *gpio = (p); \ 39 - _nouveau_gpio_dtor(nv_object(gpio)); \ 40 - }) 41 - #define nouveau_gpio_fini(p,s) \ 42 - nouveau_subdev_fini(&(p)->base, (s)) 43 - 44 - int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, 45 - struct nouveau_oclass *, int, int, void **); 46 - void _nouveau_gpio_dtor(struct nouveau_object *); 47 - int nouveau_gpio_init(struct nouveau_gpio *); 48 - 49 - extern struct nouveau_oclass nv10_gpio_oclass; 50 - extern struct nouveau_oclass nv50_gpio_oclass; 51 - extern struct nouveau_oclass nvd0_gpio_oclass; 52 - extern struct nouveau_oclass nve0_gpio_oclass; 34 + extern struct nouveau_oclass *nv10_gpio_oclass; 35 + extern struct nouveau_oclass *nv50_gpio_oclass; 36 + extern struct nouveau_oclass *nv92_gpio_oclass; 37 + extern struct nouveau_oclass *nvd0_gpio_oclass; 38 + extern struct nouveau_oclass *nve0_gpio_oclass; 53 39 54 40 #endif
+27 -56
drivers/gpu/drm/nouveau/core/include/subdev/i2c.h
··· 14 14 #define NV_I2C_TYPE_EXTDDC(e) (0x0005 | (e) << 8) 15 15 #define NV_I2C_TYPE_EXTAUX(e) (0x0006 | (e) << 8) 16 16 17 + enum nvkm_i2c_event { 18 + NVKM_I2C_PLUG = 1, 19 + NVKM_I2C_UNPLUG = 2, 20 + NVKM_I2C_IRQ = 4, 21 + NVKM_I2C_DONE = 8, 22 + NVKM_I2C_ANY = (NVKM_I2C_PLUG | 23 + NVKM_I2C_UNPLUG | 24 + NVKM_I2C_IRQ | 25 + NVKM_I2C_DONE), 26 + }; 27 + 17 28 struct nouveau_i2c_port { 18 29 struct nouveau_object base; 19 30 struct i2c_adapter adapter; 31 + struct mutex mutex; 20 32 21 33 struct list_head head; 22 34 u8 index; 35 + int aux; 23 36 24 37 const struct nouveau_i2c_func *func; 25 38 }; 26 39 27 40 struct nouveau_i2c_func { 28 - void (*acquire)(struct nouveau_i2c_port *); 29 - void (*release)(struct nouveau_i2c_port *); 30 - 31 41 void (*drive_scl)(struct nouveau_i2c_port *, int); 32 42 void (*drive_sda)(struct nouveau_i2c_port *, int); 33 43 int (*sense_scl)(struct nouveau_i2c_port *); 34 44 int (*sense_sda)(struct nouveau_i2c_port *); 35 45 36 - int (*aux)(struct nouveau_i2c_port *, u8, u32, u8 *, u8); 46 + int (*aux)(struct nouveau_i2c_port *, bool, u8, u32, u8 *, u8); 37 47 int (*pattern)(struct nouveau_i2c_port *, int pattern); 38 48 int (*lnk_ctl)(struct nouveau_i2c_port *, int nr, int bw, bool enh); 39 49 int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); 40 50 }; 41 - 42 - #define nouveau_i2c_port_create(p,e,o,i,a,f,d) \ 43 - nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f), \ 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 *, 57 - const struct nouveau_i2c_func *, 58 - int, void **); 59 - void _nouveau_i2c_port_dtor(struct nouveau_object *); 60 - #define _nouveau_i2c_port_init nouveau_object_init 61 - #define _nouveau_i2c_port_fini nouveau_object_fini 62 51 63 52 struct nouveau_i2c_board_info { 64 53 struct i2c_board_info dev; ··· 56 67 57 68 struct nouveau_i2c { 58 69 struct nouveau_subdev base; 70 + struct nouveau_event *ntfy; 59 71 60 72 struct nouveau_i2c_port *(*find)(struct nouveau_i2c *, u8 index); 61 73 struct nouveau_i2c_port *(*find_type)(struct nouveau_i2c *, u16 type); 74 + int (*acquire_pad)(struct nouveau_i2c_port *, unsigned long timeout); 75 + void (*release_pad)(struct nouveau_i2c_port *); 76 + int (*acquire)(struct nouveau_i2c_port *, unsigned long timeout); 77 + void (*release)(struct nouveau_i2c_port *); 62 78 int (*identify)(struct nouveau_i2c *, int index, 63 79 const char *what, struct nouveau_i2c_board_info *, 64 80 bool (*match)(struct nouveau_i2c_port *, 65 81 struct i2c_board_info *, void *), void *); 82 + 83 + wait_queue_head_t wait; 66 84 struct list_head ports; 67 85 }; 68 86 ··· 79 83 return (void *)nv_device(obj)->subdev[NVDEV_SUBDEV_I2C]; 80 84 } 81 85 82 - #define nouveau_i2c_create(p,e,o,s,d) \ 83 - nouveau_i2c_create_((p), (e), (o), (s), sizeof(**d), (void **)d) 84 - #define nouveau_i2c_destroy(p) ({ \ 85 - struct nouveau_i2c *i2c = (p); \ 86 - _nouveau_i2c_dtor(nv_object(i2c)); \ 87 - }) 88 - #define nouveau_i2c_init(p) ({ \ 89 - struct nouveau_i2c *i2c = (p); \ 90 - _nouveau_i2c_init(nv_object(i2c)); \ 91 - }) 92 - #define nouveau_i2c_fini(p,s) ({ \ 93 - struct nouveau_i2c *i2c = (p); \ 94 - _nouveau_i2c_fini(nv_object(i2c), (s)); \ 95 - }) 96 - 97 - int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, 98 - struct nouveau_oclass *, struct nouveau_oclass *, 99 - int, void **); 100 - void _nouveau_i2c_dtor(struct nouveau_object *); 101 - int _nouveau_i2c_init(struct nouveau_object *); 102 - int _nouveau_i2c_fini(struct nouveau_object *, bool); 103 - 104 - extern struct nouveau_oclass nv04_i2c_oclass; 105 - extern struct nouveau_oclass nv4e_i2c_oclass; 106 - extern struct nouveau_oclass nv50_i2c_oclass; 107 - extern struct nouveau_oclass nv94_i2c_oclass; 108 - extern struct nouveau_oclass nvd0_i2c_oclass; 109 - extern struct nouveau_oclass nouveau_anx9805_sclass[]; 110 - 111 - extern const struct i2c_algorithm nouveau_i2c_bit_algo; 112 - extern const struct i2c_algorithm nouveau_i2c_aux_algo; 86 + extern struct nouveau_oclass *nv04_i2c_oclass; 87 + extern struct nouveau_oclass *nv4e_i2c_oclass; 88 + extern struct nouveau_oclass *nv50_i2c_oclass; 89 + extern struct nouveau_oclass *nv94_i2c_oclass; 90 + extern struct nouveau_oclass *nvd0_i2c_oclass; 91 + extern struct nouveau_oclass *nve0_i2c_oclass; 113 92 114 93 static inline int 115 94 nv_rdi2cr(struct nouveau_i2c_port *port, u8 addr, u8 reg)
+53 -9
drivers/gpu/drm/nouveau/core/subdev/bios/conn.c
··· 28 28 #include <subdev/bios/dcb.h> 29 29 #include <subdev/bios/conn.h> 30 30 31 - u16 32 - dcb_conntab(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 31 + u32 32 + nvbios_connTe(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len) 33 33 { 34 - u16 dcb = dcb_table(bios, ver, hdr, cnt, len); 34 + u32 dcb = dcb_table(bios, ver, hdr, cnt, len); 35 35 if (dcb && *ver >= 0x30 && *hdr >= 0x16) { 36 - u16 data = nv_ro16(bios, dcb + 0x14); 36 + u32 data = nv_ro16(bios, dcb + 0x14); 37 37 if (data) { 38 38 *ver = nv_ro08(bios, data + 0); 39 39 *hdr = nv_ro08(bios, data + 1); ··· 42 42 return data; 43 43 } 44 44 } 45 - return 0x0000; 45 + return 0x00000000; 46 46 } 47 47 48 - u16 49 - dcb_conn(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) 48 + u32 49 + nvbios_connTp(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 50 + struct nvbios_connT *info) 51 + { 52 + u32 data = nvbios_connTe(bios, ver, hdr, cnt, len); 53 + memset(info, 0x00, sizeof(*info)); 54 + switch (!!data * *ver) { 55 + case 0x30: 56 + case 0x40: 57 + return data; 58 + default: 59 + break; 60 + } 61 + return 0x00000000; 62 + } 63 + 64 + u32 65 + nvbios_connEe(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len) 50 66 { 51 67 u8 hdr, cnt; 52 - u16 data = dcb_conntab(bios, ver, &hdr, &cnt, len); 68 + u32 data = nvbios_connTe(bios, ver, &hdr, &cnt, len); 53 69 if (data && idx < cnt) 54 70 return data + hdr + (idx * *len); 55 - return 0x0000; 71 + return 0x00000000; 72 + } 73 + 74 + u32 75 + nvbios_connEp(struct nouveau_bios *bios, u8 idx, u8 *ver, u8 *len, 76 + struct nvbios_connE *info) 77 + { 78 + u32 data = nvbios_connEe(bios, idx, ver, len); 79 + memset(info, 0x00, sizeof(*info)); 80 + switch (!!data * *ver) { 81 + case 0x30: 82 + case 0x40: 83 + info->type = nv_ro08(bios, data + 0x00); 84 + info->location = nv_ro08(bios, data + 0x01) & 0x0f; 85 + info->hpd = (nv_ro08(bios, data + 0x01) & 0x30) >> 4; 86 + info->dp = (nv_ro08(bios, data + 0x01) & 0xc0) >> 6; 87 + if (*len < 4) 88 + return data; 89 + info->hpd |= (nv_ro08(bios, data + 0x02) & 0x03) << 2; 90 + info->dp |= nv_ro08(bios, data + 0x02) & 0x0c; 91 + info->di = (nv_ro08(bios, data + 0x02) & 0xf0) >> 4; 92 + info->hpd |= (nv_ro08(bios, data + 0x03) & 0x07) << 4; 93 + info->sr = (nv_ro08(bios, data + 0x03) & 0x08) >> 3; 94 + info->lcdid = (nv_ro08(bios, data + 0x03) & 0x70) >> 4; 95 + return data; 96 + default: 97 + break; 98 + } 99 + return 0x00000000; 56 100 }
+12 -11
drivers/gpu/drm/nouveau/core/subdev/bios/dp.c
··· 162 162 struct nvbios_dpcfg *info) 163 163 { 164 164 u16 data = nvbios_dpcfg_entry(bios, outp, idx, ver, hdr, cnt, len); 165 + memset(info, 0x00, sizeof(*info)); 165 166 if (data) { 166 167 switch (*ver) { 167 168 case 0x21: 168 - info->drv = nv_ro08(bios, data + 0x02); 169 - info->pre = nv_ro08(bios, data + 0x03); 170 - info->unk = nv_ro08(bios, data + 0x04); 169 + info->dc = nv_ro08(bios, data + 0x02); 170 + info->pe = nv_ro08(bios, data + 0x03); 171 + info->tx_pu = nv_ro08(bios, data + 0x04); 171 172 break; 172 173 case 0x30: 173 174 case 0x40: 174 - info->drv = nv_ro08(bios, data + 0x01); 175 - info->pre = nv_ro08(bios, data + 0x02); 176 - info->unk = nv_ro08(bios, data + 0x03); 175 + info->pc = nv_ro08(bios, data + 0x00); 176 + info->dc = nv_ro08(bios, data + 0x01); 177 + info->pe = nv_ro08(bios, data + 0x02); 178 + info->tx_pu = nv_ro08(bios, data + 0x03); 177 179 break; 178 180 default: 179 181 data = 0x0000; ··· 186 184 } 187 185 188 186 u16 189 - nvbios_dpcfg_match(struct nouveau_bios *bios, u16 outp, u8 un, u8 vs, u8 pe, 187 + nvbios_dpcfg_match(struct nouveau_bios *bios, u16 outp, u8 pc, u8 vs, u8 pe, 190 188 u8 *ver, u8 *hdr, u8 *cnt, u8 *len, 191 189 struct nvbios_dpcfg *info) 192 190 { ··· 195 193 196 194 if (*ver >= 0x30) { 197 195 const u8 vsoff[] = { 0, 4, 7, 9 }; 198 - idx = (un * 10) + vsoff[vs] + pe; 196 + idx = (pc * 10) + vsoff[vs] + pe; 199 197 } else { 200 - while ((data = nvbios_dpcfg_entry(bios, outp, idx, 198 + while ((data = nvbios_dpcfg_entry(bios, outp, ++idx, 201 199 ver, hdr, cnt, len))) { 202 200 if (nv_ro08(bios, data + 0x00) == vs && 203 201 nv_ro08(bios, data + 0x01) == pe) 204 202 break; 205 - idx++; 206 203 } 207 204 } 208 205 209 - return nvbios_dpcfg_parse(bios, outp, pe, ver, hdr, cnt, len, info); 206 + return nvbios_dpcfg_parse(bios, outp, idx, ver, hdr, cnt, len, info); 210 207 }
+5 -4
drivers/gpu/drm/nouveau/core/subdev/bios/init.c
··· 98 98 init_conn(struct nvbios_init *init) 99 99 { 100 100 struct nouveau_bios *bios = init->bios; 101 - u8 ver, len; 102 - u16 conn; 101 + struct nvbios_connE connE; 102 + u8 ver, hdr; 103 + u32 conn; 103 104 104 105 if (init_exec(init)) { 105 106 if (init->outp) { 106 107 conn = init->outp->connector; 107 - conn = dcb_conn(bios, conn, &ver, &len); 108 + conn = nvbios_connEp(bios, conn, &ver, &hdr, &connE); 108 109 if (conn) 109 - return nv_ro08(bios, conn); 110 + return connE.type; 110 111 } 111 112 112 113 error("script needs connector type\n");
+111 -33
drivers/gpu/drm/nouveau/core/subdev/gpio/base.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <subdev/gpio.h> 26 25 #include <subdev/bios.h> 27 26 #include <subdev/bios/gpio.h> 27 + 28 + #include "priv.h" 28 29 29 30 static int 30 31 nouveau_gpio_drive(struct nouveau_gpio *gpio, 31 32 int idx, int line, int dir, int out) 32 33 { 33 - return gpio->drive ? gpio->drive(gpio, line, dir, out) : -ENODEV; 34 + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; 35 + return impl->drive ? impl->drive(gpio, line, dir, out) : -ENODEV; 34 36 } 35 37 36 38 static int 37 39 nouveau_gpio_sense(struct nouveau_gpio *gpio, int idx, int line) 38 40 { 39 - return gpio->sense ? gpio->sense(gpio, line) : -ENODEV; 41 + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; 42 + return impl->sense ? impl->sense(gpio, line) : -ENODEV; 40 43 } 41 44 42 45 static int ··· 105 102 return ret; 106 103 } 107 104 108 - void 109 - _nouveau_gpio_dtor(struct nouveau_object *object) 105 + static void 106 + nouveau_gpio_intr_disable(struct nouveau_event *event, int type, int index) 110 107 { 111 - struct nouveau_gpio *gpio = (void *)object; 112 - nouveau_event_destroy(&gpio->events); 113 - nouveau_subdev_destroy(&gpio->base); 108 + struct nouveau_gpio *gpio = nouveau_gpio(event->priv); 109 + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; 110 + impl->intr_mask(gpio, type, 1 << index, 0); 111 + } 112 + 113 + static void 114 + nouveau_gpio_intr_enable(struct nouveau_event *event, int type, int index) 115 + { 116 + struct nouveau_gpio *gpio = nouveau_gpio(event->priv); 117 + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; 118 + impl->intr_mask(gpio, type, 1 << index, 1 << index); 119 + } 120 + 121 + static void 122 + nouveau_gpio_intr(struct nouveau_subdev *subdev) 123 + { 124 + struct nouveau_gpio *gpio = nouveau_gpio(subdev); 125 + const struct nouveau_gpio_impl *impl = (void *)nv_object(gpio)->oclass; 126 + u32 hi, lo, e, i; 127 + 128 + impl->intr_stat(gpio, &hi, &lo); 129 + 130 + for (i = 0; e = 0, (hi | lo) && i < impl->lines; i++) { 131 + if (hi & (1 << i)) 132 + e |= NVKM_GPIO_HI; 133 + if (lo & (1 << i)) 134 + e |= NVKM_GPIO_LO; 135 + nouveau_event_trigger(gpio->events, e, i); 136 + } 114 137 } 115 138 116 139 int 117 - nouveau_gpio_create_(struct nouveau_object *parent, 118 - struct nouveau_object *engine, 119 - struct nouveau_oclass *oclass, int lines, 120 - int length, void **pobject) 140 + _nouveau_gpio_fini(struct nouveau_object *object, bool suspend) 121 141 { 122 - struct nouveau_gpio *gpio; 123 - int ret; 142 + const struct nouveau_gpio_impl *impl = (void *)object->oclass; 143 + struct nouveau_gpio *gpio = nouveau_gpio(object); 144 + u32 mask = (1 << impl->lines) - 1; 124 145 125 - ret = nouveau_subdev_create_(parent, engine, oclass, 0, "GPIO", "gpio", 126 - length, pobject); 127 - gpio = *pobject; 128 - if (ret) 129 - return ret; 146 + impl->intr_mask(gpio, NVKM_GPIO_TOGGLED, mask, 0); 147 + impl->intr_stat(gpio, &mask, &mask); 130 148 131 - ret = nouveau_event_create(lines, &gpio->events); 132 - if (ret) 133 - return ret; 134 - 135 - gpio->find = nouveau_gpio_find; 136 - gpio->set = nouveau_gpio_set; 137 - gpio->get = nouveau_gpio_get; 138 - return 0; 149 + return nouveau_subdev_fini(&gpio->base, suspend); 139 150 } 140 151 141 152 static struct dmi_system_id gpio_reset_ids[] = { ··· 164 147 }; 165 148 166 149 int 167 - nouveau_gpio_init(struct nouveau_gpio *gpio) 150 + _nouveau_gpio_init(struct nouveau_object *object) 168 151 { 169 - int ret = nouveau_subdev_init(&gpio->base); 170 - if (ret == 0 && gpio->reset) { 171 - if (dmi_check_system(gpio_reset_ids)) 172 - gpio->reset(gpio, DCB_GPIO_UNUSED); 173 - } 152 + struct nouveau_gpio *gpio = nouveau_gpio(object); 153 + int ret; 154 + 155 + ret = nouveau_subdev_init(&gpio->base); 156 + if (ret) 157 + return ret; 158 + 159 + if (gpio->reset && dmi_check_system(gpio_reset_ids)) 160 + gpio->reset(gpio, DCB_GPIO_UNUSED); 161 + 174 162 return ret; 163 + } 164 + 165 + void 166 + _nouveau_gpio_dtor(struct nouveau_object *object) 167 + { 168 + struct nouveau_gpio *gpio = (void *)object; 169 + nouveau_event_destroy(&gpio->events); 170 + nouveau_subdev_destroy(&gpio->base); 171 + } 172 + 173 + int 174 + nouveau_gpio_create_(struct nouveau_object *parent, 175 + struct nouveau_object *engine, 176 + struct nouveau_oclass *oclass, 177 + int length, void **pobject) 178 + { 179 + const struct nouveau_gpio_impl *impl = (void *)oclass; 180 + struct nouveau_gpio *gpio; 181 + int ret; 182 + 183 + ret = nouveau_subdev_create_(parent, engine, oclass, 0, "GPIO", "gpio", 184 + length, pobject); 185 + gpio = *pobject; 186 + if (ret) 187 + return ret; 188 + 189 + gpio->find = nouveau_gpio_find; 190 + gpio->set = nouveau_gpio_set; 191 + gpio->get = nouveau_gpio_get; 192 + gpio->reset = impl->reset; 193 + 194 + ret = nouveau_event_create(2, impl->lines, &gpio->events); 195 + if (ret) 196 + return ret; 197 + 198 + gpio->events->priv = gpio; 199 + gpio->events->enable = nouveau_gpio_intr_enable; 200 + gpio->events->disable = nouveau_gpio_intr_disable; 201 + nv_subdev(gpio)->intr = nouveau_gpio_intr; 202 + return 0; 203 + } 204 + 205 + int 206 + _nouveau_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 207 + struct nouveau_oclass *oclass, void *data, u32 size, 208 + struct nouveau_object **pobject) 209 + { 210 + struct nouveau_gpio *gpio; 211 + int ret; 212 + 213 + ret = nouveau_gpio_create(parent, engine, oclass, &gpio); 214 + *pobject = nv_object(gpio); 215 + if (ret) 216 + return ret; 217 + 218 + return 0; 175 219 }
+27 -88
drivers/gpu/drm/nouveau/core/subdev/gpio/nv10.c
··· 26 26 27 27 #include "priv.h" 28 28 29 - struct nv10_gpio_priv { 30 - struct nouveau_gpio base; 31 - }; 32 - 33 29 static int 34 30 nv10_gpio_sense(struct nouveau_gpio *gpio, int line) 35 31 { ··· 79 83 } 80 84 81 85 static void 82 - nv10_gpio_intr(struct nouveau_subdev *subdev) 86 + nv10_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo) 83 87 { 84 - struct nv10_gpio_priv *priv = (void *)subdev; 85 - u32 intr = nv_rd32(priv, 0x001104); 86 - u32 hi = (intr & 0x0000ffff) >> 0; 87 - u32 lo = (intr & 0xffff0000) >> 16; 88 - int i; 89 - 90 - for (i = 0; (hi | lo) && i < 32; i++) { 91 - if ((hi | lo) & (1 << i)) 92 - nouveau_event_trigger(priv->base.events, i); 93 - } 94 - 95 - nv_wr32(priv, 0x001104, intr); 88 + u32 intr = nv_rd32(gpio, 0x001104); 89 + u32 stat = nv_rd32(gpio, 0x001144) & intr; 90 + *lo = (stat & 0xffff0000) >> 16; 91 + *hi = (stat & 0x0000ffff); 92 + nv_wr32(gpio, 0x001104, intr); 96 93 } 97 94 98 95 static void 99 - nv10_gpio_intr_enable(struct nouveau_event *event, int line) 96 + nv10_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data) 100 97 { 101 - nv_wr32(event->priv, 0x001104, 0x00010001 << line); 102 - nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00010001 << line); 98 + u32 inte = nv_rd32(gpio, 0x001144); 99 + if (type & NVKM_GPIO_LO) 100 + inte = (inte & ~(mask << 16)) | (data << 16); 101 + if (type & NVKM_GPIO_HI) 102 + inte = (inte & ~mask) | data; 103 + nv_wr32(gpio, 0x001144, inte); 103 104 } 104 105 105 - static void 106 - nv10_gpio_intr_disable(struct nouveau_event *event, int line) 107 - { 108 - nv_wr32(event->priv, 0x001104, 0x00010001 << line); 109 - nv_mask(event->priv, 0x001144, 0x00010001 << line, 0x00000000); 110 - } 111 - 112 - static int 113 - nv10_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 114 - struct nouveau_oclass *oclass, void *data, u32 size, 115 - struct nouveau_object **pobject) 116 - { 117 - struct nv10_gpio_priv *priv; 118 - int ret; 119 - 120 - ret = nouveau_gpio_create(parent, engine, oclass, 16, &priv); 121 - *pobject = nv_object(priv); 122 - if (ret) 123 - return ret; 124 - 125 - priv->base.drive = nv10_gpio_drive; 126 - priv->base.sense = nv10_gpio_sense; 127 - priv->base.events->priv = priv; 128 - priv->base.events->enable = nv10_gpio_intr_enable; 129 - priv->base.events->disable = nv10_gpio_intr_disable; 130 - nv_subdev(priv)->intr = nv10_gpio_intr; 131 - return 0; 132 - } 133 - 134 - static void 135 - nv10_gpio_dtor(struct nouveau_object *object) 136 - { 137 - struct nv10_gpio_priv *priv = (void *)object; 138 - nouveau_gpio_destroy(&priv->base); 139 - } 140 - 141 - static int 142 - nv10_gpio_init(struct nouveau_object *object) 143 - { 144 - struct nv10_gpio_priv *priv = (void *)object; 145 - int ret; 146 - 147 - ret = nouveau_gpio_init(&priv->base); 148 - if (ret) 149 - return ret; 150 - 151 - nv_wr32(priv, 0x001144, 0x00000000); 152 - nv_wr32(priv, 0x001104, 0xffffffff); 153 - return 0; 154 - } 155 - 156 - static int 157 - nv10_gpio_fini(struct nouveau_object *object, bool suspend) 158 - { 159 - struct nv10_gpio_priv *priv = (void *)object; 160 - nv_wr32(priv, 0x001144, 0x00000000); 161 - return nouveau_gpio_fini(&priv->base, suspend); 162 - } 163 - 164 - struct nouveau_oclass 165 - nv10_gpio_oclass = { 166 - .handle = NV_SUBDEV(GPIO, 0x10), 167 - .ofuncs = &(struct nouveau_ofuncs) { 168 - .ctor = nv10_gpio_ctor, 169 - .dtor = nv10_gpio_dtor, 170 - .init = nv10_gpio_init, 171 - .fini = nv10_gpio_fini, 106 + struct nouveau_oclass * 107 + nv10_gpio_oclass = &(struct nouveau_gpio_impl) { 108 + .base.handle = NV_SUBDEV(GPIO, 0x10), 109 + .base.ofuncs = &(struct nouveau_ofuncs) { 110 + .ctor = _nouveau_gpio_ctor, 111 + .dtor = _nouveau_gpio_dtor, 112 + .init = _nouveau_gpio_init, 113 + .fini = _nouveau_gpio_fini, 172 114 }, 173 - }; 115 + .lines = 16, 116 + .intr_stat = nv10_gpio_intr_stat, 117 + .intr_mask = nv10_gpio_intr_mask, 118 + .drive = nv10_gpio_drive, 119 + .sense = nv10_gpio_sense, 120 + }.base;
+34 -118
drivers/gpu/drm/nouveau/core/subdev/gpio/nv50.c
··· 24 24 25 25 #include "priv.h" 26 26 27 - struct nv50_gpio_priv { 28 - struct nouveau_gpio base; 29 - }; 30 - 31 - static void 27 + void 32 28 nv50_gpio_reset(struct nouveau_gpio *gpio, u8 match) 33 29 { 34 30 struct nouveau_bios *bios = nouveau_bios(gpio); 35 - struct nv50_gpio_priv *priv = (void *)gpio; 36 31 u8 ver, len; 37 32 u16 entry; 38 33 int ent = -1; ··· 50 55 51 56 gpio->set(gpio, 0, func, line, defs); 52 57 53 - nv_mask(priv, reg, 0x00010001 << lsh, val << lsh); 58 + nv_mask(gpio, reg, 0x00010001 << lsh, val << lsh); 54 59 } 55 60 } 56 61 ··· 67 72 return 0; 68 73 } 69 74 70 - static int 75 + int 71 76 nv50_gpio_drive(struct nouveau_gpio *gpio, int line, int dir, int out) 72 77 { 73 78 u32 reg, shift; ··· 79 84 return 0; 80 85 } 81 86 82 - static int 87 + int 83 88 nv50_gpio_sense(struct nouveau_gpio *gpio, int line) 84 89 { 85 90 u32 reg, shift; ··· 90 95 return !!(nv_rd32(gpio, reg) & (4 << shift)); 91 96 } 92 97 93 - void 94 - nv50_gpio_intr(struct nouveau_subdev *subdev) 98 + static void 99 + nv50_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo) 95 100 { 96 - struct nv50_gpio_priv *priv = (void *)subdev; 97 - u32 intr0, intr1 = 0; 98 - u32 hi, lo; 99 - int i; 100 - 101 - intr0 = nv_rd32(priv, 0xe054) & nv_rd32(priv, 0xe050); 102 - if (nv_device(priv)->chipset > 0x92) 103 - intr1 = nv_rd32(priv, 0xe074) & nv_rd32(priv, 0xe070); 104 - 105 - hi = (intr0 & 0x0000ffff) | (intr1 << 16); 106 - lo = (intr0 >> 16) | (intr1 & 0xffff0000); 107 - 108 - for (i = 0; (hi | lo) && i < 32; i++) { 109 - if ((hi | lo) & (1 << i)) 110 - nouveau_event_trigger(priv->base.events, i); 111 - } 112 - 113 - nv_wr32(priv, 0xe054, intr0); 114 - if (nv_device(priv)->chipset > 0x92) 115 - nv_wr32(priv, 0xe074, intr1); 101 + u32 intr = nv_rd32(gpio, 0x00e054); 102 + u32 stat = nv_rd32(gpio, 0x00e050) & intr; 103 + *lo = (stat & 0xffff0000) >> 16; 104 + *hi = (stat & 0x0000ffff); 105 + nv_wr32(gpio, 0x00e054, intr); 116 106 } 117 107 118 - void 119 - nv50_gpio_intr_enable(struct nouveau_event *event, int line) 108 + static void 109 + nv50_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data) 120 110 { 121 - const u32 addr = line < 16 ? 0xe050 : 0xe070; 122 - const u32 mask = 0x00010001 << (line & 0xf); 123 - nv_wr32(event->priv, addr + 0x04, mask); 124 - nv_mask(event->priv, addr + 0x00, mask, mask); 111 + u32 inte = nv_rd32(gpio, 0x00e050); 112 + if (type & NVKM_GPIO_LO) 113 + inte = (inte & ~(mask << 16)) | (data << 16); 114 + if (type & NVKM_GPIO_HI) 115 + inte = (inte & ~mask) | data; 116 + nv_wr32(gpio, 0x00e050, inte); 125 117 } 126 118 127 - void 128 - nv50_gpio_intr_disable(struct nouveau_event *event, int line) 129 - { 130 - const u32 addr = line < 16 ? 0xe050 : 0xe070; 131 - const u32 mask = 0x00010001 << (line & 0xf); 132 - nv_wr32(event->priv, addr + 0x04, mask); 133 - nv_mask(event->priv, addr + 0x00, mask, 0x00000000); 134 - } 135 - 136 - static int 137 - nv50_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 138 - struct nouveau_oclass *oclass, void *data, u32 size, 139 - struct nouveau_object **pobject) 140 - { 141 - struct nv50_gpio_priv *priv; 142 - int ret; 143 - 144 - ret = nouveau_gpio_create(parent, engine, oclass, 145 - nv_device(parent)->chipset > 0x92 ? 32 : 16, 146 - &priv); 147 - *pobject = nv_object(priv); 148 - if (ret) 149 - return ret; 150 - 151 - priv->base.reset = nv50_gpio_reset; 152 - priv->base.drive = nv50_gpio_drive; 153 - priv->base.sense = nv50_gpio_sense; 154 - priv->base.events->priv = priv; 155 - priv->base.events->enable = nv50_gpio_intr_enable; 156 - priv->base.events->disable = nv50_gpio_intr_disable; 157 - nv_subdev(priv)->intr = nv50_gpio_intr; 158 - return 0; 159 - } 160 - 161 - void 162 - nv50_gpio_dtor(struct nouveau_object *object) 163 - { 164 - struct nv50_gpio_priv *priv = (void *)object; 165 - nouveau_gpio_destroy(&priv->base); 166 - } 167 - 168 - int 169 - nv50_gpio_init(struct nouveau_object *object) 170 - { 171 - struct nv50_gpio_priv *priv = (void *)object; 172 - int ret; 173 - 174 - ret = nouveau_gpio_init(&priv->base); 175 - if (ret) 176 - return ret; 177 - 178 - /* disable, and ack any pending gpio interrupts */ 179 - nv_wr32(priv, 0xe050, 0x00000000); 180 - nv_wr32(priv, 0xe054, 0xffffffff); 181 - if (nv_device(priv)->chipset > 0x92) { 182 - nv_wr32(priv, 0xe070, 0x00000000); 183 - nv_wr32(priv, 0xe074, 0xffffffff); 184 - } 185 - 186 - return 0; 187 - } 188 - 189 - int 190 - nv50_gpio_fini(struct nouveau_object *object, bool suspend) 191 - { 192 - struct nv50_gpio_priv *priv = (void *)object; 193 - nv_wr32(priv, 0xe050, 0x00000000); 194 - if (nv_device(priv)->chipset > 0x92) 195 - nv_wr32(priv, 0xe070, 0x00000000); 196 - return nouveau_gpio_fini(&priv->base, suspend); 197 - } 198 - 199 - struct nouveau_oclass 200 - nv50_gpio_oclass = { 201 - .handle = NV_SUBDEV(GPIO, 0x50), 202 - .ofuncs = &(struct nouveau_ofuncs) { 203 - .ctor = nv50_gpio_ctor, 204 - .dtor = nv50_gpio_dtor, 205 - .init = nv50_gpio_init, 206 - .fini = nv50_gpio_fini, 119 + struct nouveau_oclass * 120 + nv50_gpio_oclass = &(struct nouveau_gpio_impl) { 121 + .base.handle = NV_SUBDEV(GPIO, 0x50), 122 + .base.ofuncs = &(struct nouveau_ofuncs) { 123 + .ctor = _nouveau_gpio_ctor, 124 + .dtor = _nouveau_gpio_dtor, 125 + .init = _nouveau_gpio_init, 126 + .fini = _nouveau_gpio_fini, 207 127 }, 208 - }; 128 + .lines = 16, 129 + .intr_stat = nv50_gpio_intr_stat, 130 + .intr_mask = nv50_gpio_intr_mask, 131 + .drive = nv50_gpio_drive, 132 + .sense = nv50_gpio_sense, 133 + .reset = nv50_gpio_reset, 134 + }.base;
+74
drivers/gpu/drm/nouveau/core/subdev/gpio/nv92.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 + void 28 + nv92_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo) 29 + { 30 + u32 intr0 = nv_rd32(gpio, 0x00e054); 31 + u32 intr1 = nv_rd32(gpio, 0x00e074); 32 + u32 stat0 = nv_rd32(gpio, 0x00e050) & intr0; 33 + u32 stat1 = nv_rd32(gpio, 0x00e070) & intr1; 34 + *lo = (stat1 & 0xffff0000) | (stat0 >> 16); 35 + *hi = (stat1 << 16) | (stat0 & 0x0000ffff); 36 + nv_wr32(gpio, 0x00e054, intr0); 37 + nv_wr32(gpio, 0x00e074, intr1); 38 + } 39 + 40 + void 41 + nv92_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data) 42 + { 43 + u32 inte0 = nv_rd32(gpio, 0x00e050); 44 + u32 inte1 = nv_rd32(gpio, 0x00e070); 45 + if (type & NVKM_GPIO_LO) 46 + inte0 = (inte0 & ~(mask << 16)) | (data << 16); 47 + if (type & NVKM_GPIO_HI) 48 + inte0 = (inte0 & ~(mask & 0xffff)) | (data & 0xffff); 49 + mask >>= 16; 50 + data >>= 16; 51 + if (type & NVKM_GPIO_LO) 52 + inte1 = (inte1 & ~(mask << 16)) | (data << 16); 53 + if (type & NVKM_GPIO_HI) 54 + inte1 = (inte1 & ~mask) | data; 55 + nv_wr32(gpio, 0x00e050, inte0); 56 + nv_wr32(gpio, 0x00e070, inte1); 57 + } 58 + 59 + struct nouveau_oclass * 60 + nv92_gpio_oclass = &(struct nouveau_gpio_impl) { 61 + .base.handle = NV_SUBDEV(GPIO, 0x92), 62 + .base.ofuncs = &(struct nouveau_ofuncs) { 63 + .ctor = _nouveau_gpio_ctor, 64 + .dtor = _nouveau_gpio_dtor, 65 + .init = _nouveau_gpio_init, 66 + .fini = _nouveau_gpio_fini, 67 + }, 68 + .lines = 32, 69 + .intr_stat = nv92_gpio_intr_stat, 70 + .intr_mask = nv92_gpio_intr_mask, 71 + .drive = nv50_gpio_drive, 72 + .sense = nv50_gpio_sense, 73 + .reset = nv50_gpio_reset, 74 + }.base;
+17 -39
drivers/gpu/drm/nouveau/core/subdev/gpio/nvd0.c
··· 24 24 25 25 #include "priv.h" 26 26 27 - struct nvd0_gpio_priv { 28 - struct nouveau_gpio base; 29 - }; 30 - 31 27 void 32 28 nvd0_gpio_reset(struct nouveau_gpio *gpio, u8 match) 33 29 { 34 30 struct nouveau_bios *bios = nouveau_bios(gpio); 35 - struct nvd0_gpio_priv *priv = (void *)gpio; 36 31 u8 ver, len; 37 32 u16 entry; 38 33 int ent = -1; ··· 46 51 47 52 gpio->set(gpio, 0, func, line, defs); 48 53 49 - nv_mask(priv, 0x00d610 + (line * 4), 0xff, unk0); 54 + nv_mask(gpio, 0x00d610 + (line * 4), 0xff, unk0); 50 55 if (unk1--) 51 - nv_mask(priv, 0x00d740 + (unk1 * 4), 0xff, line); 56 + nv_mask(gpio, 0x00d740 + (unk1 * 4), 0xff, line); 52 57 } 53 58 } 54 59 ··· 67 72 return !!(nv_rd32(gpio, 0x00d610 + (line * 4)) & 0x00004000); 68 73 } 69 74 70 - static int 71 - nvd0_gpio_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 72 - struct nouveau_oclass *oclass, void *data, u32 size, 73 - struct nouveau_object **pobject) 74 - { 75 - struct nvd0_gpio_priv *priv; 76 - int ret; 77 - 78 - ret = nouveau_gpio_create(parent, engine, oclass, 32, &priv); 79 - *pobject = nv_object(priv); 80 - if (ret) 81 - return ret; 82 - 83 - priv->base.reset = nvd0_gpio_reset; 84 - priv->base.drive = nvd0_gpio_drive; 85 - priv->base.sense = nvd0_gpio_sense; 86 - priv->base.events->priv = priv; 87 - priv->base.events->enable = nv50_gpio_intr_enable; 88 - priv->base.events->disable = nv50_gpio_intr_disable; 89 - nv_subdev(priv)->intr = nv50_gpio_intr; 90 - return 0; 91 - } 92 - 93 - struct nouveau_oclass 94 - nvd0_gpio_oclass = { 95 - .handle = NV_SUBDEV(GPIO, 0xd0), 96 - .ofuncs = &(struct nouveau_ofuncs) { 97 - .ctor = nvd0_gpio_ctor, 98 - .dtor = nv50_gpio_dtor, 99 - .init = nv50_gpio_init, 100 - .fini = nv50_gpio_fini, 75 + struct nouveau_oclass * 76 + nvd0_gpio_oclass = &(struct nouveau_gpio_impl) { 77 + .base.handle = NV_SUBDEV(GPIO, 0xd0), 78 + .base.ofuncs = &(struct nouveau_ofuncs) { 79 + .ctor = _nouveau_gpio_ctor, 80 + .dtor = _nouveau_gpio_dtor, 81 + .init = _nouveau_gpio_init, 82 + .fini = _nouveau_gpio_fini, 101 83 }, 102 - }; 84 + .lines = 32, 85 + .intr_stat = nv92_gpio_intr_stat, 86 + .intr_mask = nv92_gpio_intr_mask, 87 + .drive = nvd0_gpio_drive, 88 + .sense = nvd0_gpio_sense, 89 + .reset = nvd0_gpio_reset, 90 + }.base;
+40 -97
drivers/gpu/drm/nouveau/core/subdev/gpio/nve0.c
··· 24 24 25 25 #include "priv.h" 26 26 27 - struct nve0_gpio_priv { 28 - struct nouveau_gpio base; 29 - }; 30 - 31 - void 32 - nve0_gpio_intr(struct nouveau_subdev *subdev) 27 + static void 28 + nve0_gpio_intr_stat(struct nouveau_gpio *gpio, u32 *hi, u32 *lo) 33 29 { 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, 0xdc80, intr1); 30 + u32 intr0 = nv_rd32(gpio, 0x00dc00); 31 + u32 intr1 = nv_rd32(gpio, 0x00dc80); 32 + u32 stat0 = nv_rd32(gpio, 0x00dc08) & intr0; 33 + u32 stat1 = nv_rd32(gpio, 0x00dc88) & intr1; 34 + *lo = (stat1 & 0xffff0000) | (stat0 >> 16); 35 + *hi = (stat1 << 16) | (stat0 & 0x0000ffff); 36 + nv_wr32(gpio, 0x00dc00, intr0); 37 + nv_wr32(gpio, 0x00dc80, intr1); 48 38 } 49 39 50 40 void 51 - nve0_gpio_intr_enable(struct nouveau_event *event, int line) 41 + nve0_gpio_intr_mask(struct nouveau_gpio *gpio, u32 type, u32 mask, u32 data) 52 42 { 53 - const u32 addr = line < 16 ? 0xdc00 : 0xdc80; 54 - const u32 mask = 0x00010001 << (line & 0xf); 55 - nv_wr32(event->priv, addr + 0x00, mask); 56 - nv_mask(event->priv, addr + 0x08, mask, mask); 43 + u32 inte0 = nv_rd32(gpio, 0x00dc08); 44 + u32 inte1 = nv_rd32(gpio, 0x00dc88); 45 + if (type & NVKM_GPIO_LO) 46 + inte0 = (inte0 & ~(mask << 16)) | (data << 16); 47 + if (type & NVKM_GPIO_HI) 48 + inte0 = (inte0 & ~(mask & 0xffff)) | (data & 0xffff); 49 + mask >>= 16; 50 + data >>= 16; 51 + if (type & NVKM_GPIO_LO) 52 + inte1 = (inte1 & ~(mask << 16)) | (data << 16); 53 + if (type & NVKM_GPIO_HI) 54 + inte1 = (inte1 & ~mask) | data; 55 + nv_wr32(gpio, 0x00dc08, inte0); 56 + nv_wr32(gpio, 0x00dc88, inte1); 57 57 } 58 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_mask(event->priv, addr + 0x08, mask, 0x00000000); 65 - nv_wr32(event->priv, addr + 0x00, mask); 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, 59 + struct nouveau_oclass * 60 + nve0_gpio_oclass = &(struct nouveau_gpio_impl) { 61 + .base.handle = NV_SUBDEV(GPIO, 0xe0), 62 + .base.ofuncs = &(struct nouveau_ofuncs) { 63 + .ctor = _nouveau_gpio_ctor, 64 + .dtor = _nouveau_gpio_dtor, 65 + .init = _nouveau_gpio_init, 66 + .fini = _nouveau_gpio_fini, 130 67 }, 131 - }; 68 + .lines = 32, 69 + .intr_stat = nve0_gpio_intr_stat, 70 + .intr_mask = nve0_gpio_intr_mask, 71 + .drive = nvd0_gpio_drive, 72 + .sense = nvd0_gpio_sense, 73 + .reset = nvd0_gpio_reset, 74 + }.base;
+56 -6
drivers/gpu/drm/nouveau/core/subdev/gpio/priv.h
··· 3 3 4 4 #include <subdev/gpio.h> 5 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); 6 + #define nouveau_gpio_create(p,e,o,d) \ 7 + nouveau_gpio_create_((p), (e), (o), sizeof(**d), (void **)d) 8 + #define nouveau_gpio_destroy(p) ({ \ 9 + struct nouveau_gpio *gpio = (p); \ 10 + _nouveau_gpio_dtor(nv_object(gpio)); \ 11 + }) 12 + #define nouveau_gpio_init(p) ({ \ 13 + struct nouveau_gpio *gpio = (p); \ 14 + _nouveau_gpio_init(nv_object(gpio)); \ 15 + }) 16 + #define nouveau_gpio_fini(p,s) ({ \ 17 + struct nouveau_gpio *gpio = (p); \ 18 + _nouveau_gpio_fini(nv_object(gpio), (s)); \ 19 + }) 20 + 21 + int nouveau_gpio_create_(struct nouveau_object *, struct nouveau_object *, 22 + struct nouveau_oclass *, int, void **); 23 + int _nouveau_gpio_ctor(struct nouveau_object *, struct nouveau_object *, 24 + struct nouveau_oclass *, void *, u32, 25 + struct nouveau_object **); 26 + void _nouveau_gpio_dtor(struct nouveau_object *); 27 + int _nouveau_gpio_init(struct nouveau_object *); 28 + int _nouveau_gpio_fini(struct nouveau_object *, bool); 29 + 30 + struct nouveau_gpio_impl { 31 + struct nouveau_oclass base; 32 + int lines; 33 + 34 + /* read and ack pending interrupts, returning only data 35 + * for lines that have not been masked off, while still 36 + * performing the ack for anything that was pending. 37 + */ 38 + void (*intr_stat)(struct nouveau_gpio *, u32 *, u32 *); 39 + 40 + /* mask on/off interrupts for hi/lo transitions on a 41 + * given set of gpio lines 42 + */ 43 + void (*intr_mask)(struct nouveau_gpio *, u32, u32, u32); 44 + 45 + /* configure gpio direction and output value */ 46 + int (*drive)(struct nouveau_gpio *, int line, int dir, int out); 47 + 48 + /* sense current state of given gpio line */ 49 + int (*sense)(struct nouveau_gpio *, int line); 50 + 51 + /*XXX*/ 52 + void (*reset)(struct nouveau_gpio *, u8); 53 + }; 54 + 55 + void nv50_gpio_reset(struct nouveau_gpio *, u8); 56 + int nv50_gpio_drive(struct nouveau_gpio *, int, int, int); 57 + int nv50_gpio_sense(struct nouveau_gpio *, int); 58 + 59 + void nv92_gpio_intr_stat(struct nouveau_gpio *, u32 *, u32 *); 60 + void nv92_gpio_intr_mask(struct nouveau_gpio *, u32, u32, u32); 12 61 13 62 void nvd0_gpio_reset(struct nouveau_gpio *, u8); 14 63 int nvd0_gpio_drive(struct nouveau_gpio *, int, int, int); 15 64 int nvd0_gpio_sense(struct nouveau_gpio *, int); 65 + 16 66 17 67 #endif
+21 -6
drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c
··· 22 22 * Authors: Ben Skeggs <bskeggs@redhat.com> 23 23 */ 24 24 25 - #include <subdev/i2c.h> 25 + #include "port.h" 26 26 27 27 struct anx9805_i2c_port { 28 28 struct nouveau_i2c_port base; ··· 36 36 struct anx9805_i2c_port *chan = (void *)port; 37 37 struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent; 38 38 u8 tmp, i; 39 + 40 + DBG("ANX9805 train %d 0x%02x %d\n", link_nr, link_bw, enh); 39 41 40 42 nv_wri2cr(mast, chan->addr, 0xa0, link_bw); 41 43 nv_wri2cr(mast, chan->addr, 0xa1, link_nr | (enh ? 0x80 : 0x00)); ··· 62 60 } 63 61 64 62 static int 65 - anx9805_aux(struct nouveau_i2c_port *port, u8 type, u32 addr, u8 *data, u8 size) 63 + anx9805_aux(struct nouveau_i2c_port *port, bool retry, 64 + u8 type, u32 addr, u8 *data, u8 size) 66 65 { 67 66 struct anx9805_i2c_port *chan = (void *)port; 68 67 struct nouveau_i2c_port *mast = (void *)nv_object(chan)->parent; 69 68 int i, ret = -ETIMEDOUT; 69 + u8 buf[16] = {}; 70 70 u8 tmp; 71 + 72 + DBG("%02x %05x %d\n", type, addr, size); 71 73 72 74 tmp = nv_rdi2cr(mast, chan->ctrl, 0x07) & ~0x04; 73 75 nv_wri2cr(mast, chan->ctrl, 0x07, tmp | 0x04); ··· 79 73 nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01); 80 74 81 75 nv_wri2cr(mast, chan->addr, 0xe4, 0x80); 82 - for (i = 0; !(type & 1) && i < size; i++) 83 - nv_wri2cr(mast, chan->addr, 0xf0 + i, data[i]); 76 + if (!(type & 1)) { 77 + memcpy(buf, data, size); 78 + DBG("%16ph", buf); 79 + for (i = 0; i < size; i++) 80 + nv_wri2cr(mast, chan->addr, 0xf0 + i, buf[i]); 81 + } 84 82 nv_wri2cr(mast, chan->addr, 0xe5, ((size - 1) << 4) | type); 85 83 nv_wri2cr(mast, chan->addr, 0xe6, (addr & 0x000ff) >> 0); 86 84 nv_wri2cr(mast, chan->addr, 0xe7, (addr & 0x0ff00) >> 8); ··· 103 93 goto done; 104 94 } 105 95 106 - for (i = 0; (type & 1) && i < size; i++) 107 - data[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); 96 + if (type & 1) { 97 + for (i = 0; i < size; i++) 98 + buf[i] = nv_rdi2cr(mast, chan->addr, 0xf0 + i); 99 + DBG("%16ph", buf); 100 + memcpy(data, buf, size); 101 + } 102 + 108 103 ret = 0; 109 104 done: 110 105 nv_wri2cr(mast, chan->ctrl, 0xf7, 0x01);
+25 -11
drivers/gpu/drm/nouveau/core/subdev/i2c/aux.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <subdev/i2c.h> 25 + #include "priv.h" 26 26 27 27 int 28 28 nv_rdaux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size) 29 29 { 30 + struct nouveau_i2c *i2c = nouveau_i2c(port); 30 31 if (port->func->aux) { 31 - if (port->func->acquire) 32 - port->func->acquire(port); 33 - return port->func->aux(port, 9, addr, data, size); 32 + int ret = i2c->acquire(port, 0); 33 + if (ret == 0) { 34 + ret = port->func->aux(port, true, 9, addr, data, size); 35 + i2c->release(port); 36 + } 37 + return ret; 34 38 } 35 39 return -ENODEV; 36 40 } ··· 42 38 int 43 39 nv_wraux(struct nouveau_i2c_port *port, u32 addr, u8 *data, u8 size) 44 40 { 41 + struct nouveau_i2c *i2c = nouveau_i2c(port); 45 42 if (port->func->aux) { 46 - if (port->func->acquire) 47 - port->func->acquire(port); 48 - return port->func->aux(port, 8, addr, data, size); 43 + int ret = i2c->acquire(port, 0); 44 + if (ret == 0) { 45 + ret = port->func->aux(port, true, 8, addr, data, size); 46 + i2c->release(port); 47 + } 48 + return ret; 49 49 } 50 50 return -ENODEV; 51 51 } ··· 58 50 aux_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) 59 51 { 60 52 struct nouveau_i2c_port *port = adap->algo_data; 53 + struct nouveau_i2c *i2c = nouveau_i2c(port); 61 54 struct i2c_msg *msg = msgs; 62 55 int ret, mcnt = num; 63 56 64 57 if (!port->func->aux) 65 58 return -ENODEV; 66 - if ( port->func->acquire) 67 - port->func->acquire(port); 59 + 60 + ret = i2c->acquire(port, 0); 61 + if (ret) 62 + return ret; 68 63 69 64 while (mcnt--) { 70 65 u8 remaining = msg->len; ··· 85 74 if (mcnt || remaining > 16) 86 75 cmd |= 4; /* MOT */ 87 76 88 - ret = port->func->aux(port, cmd, msg->addr, ptr, cnt); 89 - if (ret < 0) 77 + ret = port->func->aux(port, true, cmd, msg->addr, ptr, cnt); 78 + if (ret < 0) { 79 + i2c->release(port); 90 80 return ret; 81 + } 91 82 92 83 ptr += cnt; 93 84 remaining -= cnt; ··· 98 85 msg++; 99 86 } 100 87 88 + i2c->release(port); 101 89 return num; 102 90 } 103 91
+201 -11
drivers/gpu/drm/nouveau/core/subdev/i2c/base.c
··· 23 23 */ 24 24 25 25 #include <core/option.h> 26 + #include <core/event.h> 26 27 27 28 #include <subdev/bios.h> 28 29 #include <subdev/bios/dcb.h> 29 30 #include <subdev/bios/i2c.h> 30 - #include <subdev/i2c.h> 31 31 #include <subdev/vga.h> 32 + 33 + #include "priv.h" 34 + #include "pad.h" 32 35 33 36 /****************************************************************************** 34 37 * interface to linux i2c bit-banging algorithm ··· 48 45 { 49 46 struct i2c_algo_bit_data *bit = adap->algo_data; 50 47 struct nouveau_i2c_port *port = bit->data; 51 - if (port->func->acquire) 52 - port->func->acquire(port); 53 - return 0; 48 + return nouveau_i2c(port)->acquire(port, bit->timeout); 49 + } 50 + 51 + static void 52 + nouveau_i2c_post_xfer(struct i2c_adapter *adap) 53 + { 54 + struct i2c_algo_bit_data *bit = adap->algo_data; 55 + struct nouveau_i2c_port *port = bit->data; 56 + return nouveau_i2c(port)->release(port); 54 57 } 55 58 56 59 static void ··· 91 82 * base i2c "port" class implementation 92 83 *****************************************************************************/ 93 84 85 + int 86 + _nouveau_i2c_port_fini(struct nouveau_object *object, bool suspend) 87 + { 88 + struct nouveau_i2c_port *port = (void *)object; 89 + struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); 90 + nv_ofuncs(pad)->fini(nv_object(pad), suspend); 91 + return nouveau_object_fini(&port->base, suspend); 92 + } 93 + 94 94 void 95 95 _nouveau_i2c_port_dtor(struct nouveau_object *object) 96 96 { ··· 116 98 const struct nouveau_i2c_func *func, 117 99 int size, void **pobject) 118 100 { 119 - struct nouveau_device *device = nv_device(parent); 101 + struct nouveau_device *device = nv_device(engine); 120 102 struct nouveau_i2c *i2c = (void *)engine; 121 103 struct nouveau_i2c_port *port; 122 104 int ret; ··· 131 113 port->adapter.owner = THIS_MODULE; 132 114 port->adapter.dev.parent = nv_device_base(device); 133 115 port->index = index; 116 + port->aux = -1; 134 117 port->func = func; 135 - i2c_set_adapdata(&port->adapter, i2c); 118 + mutex_init(&port->mutex); 136 119 137 120 if ( algo == &nouveau_i2c_bit_algo && 138 121 !nouveau_boolopt(device->cfgopt, "NvI2C", CSTMSEL)) { ··· 147 128 bit->timeout = usecs_to_jiffies(2200); 148 129 bit->data = port; 149 130 bit->pre_xfer = nouveau_i2c_pre_xfer; 131 + bit->post_xfer = nouveau_i2c_post_xfer; 150 132 bit->setsda = nouveau_i2c_setsda; 151 133 bit->setscl = nouveau_i2c_setscl; 152 134 bit->getsda = nouveau_i2c_getsda; ··· 161 141 ret = i2c_add_adapter(&port->adapter); 162 142 } 163 143 164 - /* drop port's i2c subdev refcount, i2c handles this itself */ 165 144 if (ret == 0) 166 145 list_add_tail(&port->head, &i2c->ports); 167 146 return ret; ··· 212 193 return NULL; 213 194 } 214 195 196 + static void 197 + nouveau_i2c_release_pad(struct nouveau_i2c_port *port) 198 + { 199 + struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); 200 + struct nouveau_i2c *i2c = nouveau_i2c(port); 201 + 202 + if (atomic_dec_and_test(&nv_object(pad)->usecount)) { 203 + nv_ofuncs(pad)->fini(nv_object(pad), false); 204 + wake_up_all(&i2c->wait); 205 + } 206 + } 207 + 208 + static int 209 + nouveau_i2c_try_acquire_pad(struct nouveau_i2c_port *port) 210 + { 211 + struct nvkm_i2c_pad *pad = nvkm_i2c_pad(port); 212 + 213 + if (atomic_add_return(1, &nv_object(pad)->usecount) != 1) { 214 + struct nouveau_object *owner = (void *)pad->port; 215 + do { 216 + if (owner == (void *)port) 217 + return 0; 218 + owner = owner->parent; 219 + } while(owner); 220 + nouveau_i2c_release_pad(port); 221 + return -EBUSY; 222 + } 223 + 224 + pad->next = port; 225 + nv_ofuncs(pad)->init(nv_object(pad)); 226 + return 0; 227 + } 228 + 229 + static int 230 + nouveau_i2c_acquire_pad(struct nouveau_i2c_port *port, unsigned long timeout) 231 + { 232 + struct nouveau_i2c *i2c = nouveau_i2c(port); 233 + 234 + if (timeout) { 235 + if (wait_event_timeout(i2c->wait, 236 + nouveau_i2c_try_acquire_pad(port) == 0, 237 + timeout) == 0) 238 + return -EBUSY; 239 + } else { 240 + wait_event(i2c->wait, nouveau_i2c_try_acquire_pad(port) == 0); 241 + } 242 + 243 + return 0; 244 + } 245 + 246 + static void 247 + nouveau_i2c_release(struct nouveau_i2c_port *port) 248 + __releases(pad->mutex) 249 + { 250 + nouveau_i2c(port)->release_pad(port); 251 + mutex_unlock(&port->mutex); 252 + } 253 + 254 + static int 255 + nouveau_i2c_acquire(struct nouveau_i2c_port *port, unsigned long timeout) 256 + __acquires(pad->mutex) 257 + { 258 + int ret; 259 + mutex_lock(&port->mutex); 260 + if ((ret = nouveau_i2c(port)->acquire_pad(port, timeout))) 261 + mutex_unlock(&port->mutex); 262 + return ret; 263 + } 264 + 215 265 static int 216 266 nouveau_i2c_identify(struct nouveau_i2c *i2c, int index, const char *what, 217 267 struct nouveau_i2c_board_info *info, ··· 325 237 return -ENODEV; 326 238 } 327 239 240 + static void 241 + nouveau_i2c_intr_disable(struct nouveau_event *event, int type, int index) 242 + { 243 + struct nouveau_i2c *i2c = nouveau_i2c(event->priv); 244 + struct nouveau_i2c_port *port = i2c->find(i2c, index); 245 + const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass; 246 + if (port && port->aux >= 0) 247 + impl->aux_mask(i2c, type, 1 << port->aux, 0); 248 + } 249 + 250 + static void 251 + nouveau_i2c_intr_enable(struct nouveau_event *event, int type, int index) 252 + { 253 + struct nouveau_i2c *i2c = nouveau_i2c(event->priv); 254 + struct nouveau_i2c_port *port = i2c->find(i2c, index); 255 + const struct nouveau_i2c_impl *impl = (void *)nv_object(i2c)->oclass; 256 + if (port && port->aux >= 0) 257 + impl->aux_mask(i2c, type, 1 << port->aux, 1 << port->aux); 258 + } 259 + 260 + static void 261 + nouveau_i2c_intr(struct nouveau_subdev *subdev) 262 + { 263 + struct nouveau_i2c_impl *impl = (void *)nv_oclass(subdev); 264 + struct nouveau_i2c *i2c = nouveau_i2c(subdev); 265 + struct nouveau_i2c_port *port; 266 + u32 hi, lo, rq, tx, e; 267 + 268 + if (impl->aux_stat) { 269 + impl->aux_stat(i2c, &hi, &lo, &rq, &tx); 270 + if (hi || lo || rq || tx) { 271 + list_for_each_entry(port, &i2c->ports, head) { 272 + if (e = 0, port->aux < 0) 273 + continue; 274 + 275 + if (hi & (1 << port->aux)) e |= NVKM_I2C_PLUG; 276 + if (lo & (1 << port->aux)) e |= NVKM_I2C_UNPLUG; 277 + if (rq & (1 << port->aux)) e |= NVKM_I2C_IRQ; 278 + if (tx & (1 << port->aux)) e |= NVKM_I2C_DONE; 279 + 280 + nouveau_event_trigger(i2c->ntfy, e, port->index); 281 + } 282 + } 283 + } 284 + } 285 + 328 286 int 329 287 _nouveau_i2c_fini(struct nouveau_object *object, bool suspend) 330 288 { 289 + struct nouveau_i2c_impl *impl = (void *)nv_oclass(object); 331 290 struct nouveau_i2c *i2c = (void *)object; 332 291 struct nouveau_i2c_port *port; 292 + u32 mask; 333 293 int ret; 334 294 335 295 list_for_each_entry(port, &i2c->ports, head) { 336 296 ret = nv_ofuncs(port)->fini(nv_object(port), suspend); 337 297 if (ret && suspend) 338 298 goto fail; 299 + } 300 + 301 + if ((mask = (1 << impl->aux) - 1), impl->aux_stat) { 302 + impl->aux_mask(i2c, NVKM_I2C_ANY, mask, 0); 303 + impl->aux_stat(i2c, &mask, &mask, &mask, &mask); 339 304 } 340 305 341 306 return nouveau_subdev_fini(&i2c->base, suspend); ··· 431 290 struct nouveau_i2c *i2c = (void *)object; 432 291 struct nouveau_i2c_port *port, *temp; 433 292 293 + nouveau_event_destroy(&i2c->ntfy); 294 + 434 295 list_for_each_entry_safe(port, temp, &i2c->ports, head) { 435 296 nouveau_object_ref(NULL, (struct nouveau_object **)&port); 436 297 } ··· 449 306 nouveau_i2c_create_(struct nouveau_object *parent, 450 307 struct nouveau_object *engine, 451 308 struct nouveau_oclass *oclass, 452 - struct nouveau_oclass *sclass, 453 309 int length, void **pobject) 454 310 { 311 + const struct nouveau_i2c_impl *impl = (void *)oclass; 455 312 struct nouveau_bios *bios = nouveau_bios(parent); 456 313 struct nouveau_i2c *i2c; 457 314 struct nouveau_object *object; 458 315 struct dcb_i2c_entry info; 459 - int ret, i, j, index = -1; 316 + int ret, i, j, index = -1, pad; 460 317 struct dcb_output outp; 461 318 u8 ver, hdr; 462 319 u32 data; ··· 467 324 if (ret) 468 325 return ret; 469 326 327 + nv_subdev(i2c)->intr = nouveau_i2c_intr; 470 328 i2c->find = nouveau_i2c_find; 471 329 i2c->find_type = nouveau_i2c_find_type; 330 + i2c->acquire_pad = nouveau_i2c_acquire_pad; 331 + i2c->release_pad = nouveau_i2c_release_pad; 332 + i2c->acquire = nouveau_i2c_acquire; 333 + i2c->release = nouveau_i2c_release; 472 334 i2c->identify = nouveau_i2c_identify; 335 + init_waitqueue_head(&i2c->wait); 473 336 INIT_LIST_HEAD(&i2c->ports); 474 337 475 338 while (!dcb_i2c_parse(bios, ++index, &info)) { 476 339 if (info.type == DCB_I2C_UNUSED) 477 340 continue; 478 341 479 - oclass = sclass; 342 + if (info.share != DCB_I2C_UNUSED) { 343 + if (info.type == DCB_I2C_NVIO_AUX) 344 + pad = info.drive; 345 + else 346 + pad = info.share; 347 + oclass = impl->pad_s; 348 + } else { 349 + pad = 0x100 + info.drive; 350 + oclass = impl->pad_x; 351 + } 352 + 353 + ret = nouveau_object_ctor(NULL, *pobject, oclass, 354 + NULL, pad, &parent); 355 + if (ret < 0) 356 + continue; 357 + 358 + oclass = impl->sclass; 480 359 do { 481 360 ret = -EINVAL; 482 361 if (oclass->handle == info.type) { 483 - ret = nouveau_object_ctor(*pobject, *pobject, 362 + ret = nouveau_object_ctor(parent, *pobject, 484 363 oclass, &info, 485 364 index, &object); 486 365 } 487 366 } while (ret && (++oclass)->handle); 367 + 368 + nouveau_object_ref(NULL, &parent); 488 369 } 489 370 490 371 /* in addition to the busses specified in the i2c table, there ··· 546 379 } while (ret && (++oclass)->handle); 547 380 } 548 381 } 382 + 383 + ret = nouveau_event_create(4, index, &i2c->ntfy); 384 + if (ret) 385 + return ret; 386 + 387 + i2c->ntfy->priv = i2c; 388 + i2c->ntfy->enable = nouveau_i2c_intr_enable; 389 + i2c->ntfy->disable = nouveau_i2c_intr_disable; 390 + return 0; 391 + } 392 + 393 + int 394 + _nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 395 + struct nouveau_oclass *oclass, void *data, u32 size, 396 + struct nouveau_object **pobject) 397 + { 398 + struct nouveau_i2c *i2c; 399 + int ret; 400 + 401 + ret = nouveau_i2c_create(parent, engine, oclass, &i2c); 402 + *pobject = nv_object(i2c); 403 + if (ret) 404 + return ret; 549 405 550 406 return 0; 551 407 }
+5 -3
drivers/gpu/drm/nouveau/core/subdev/i2c/bit.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include "subdev/i2c.h" 25 + #include "priv.h" 26 26 27 27 #ifdef CONFIG_NOUVEAU_I2C_INTERNAL 28 28 #define T_TIMEOUT 2200000 ··· 187 187 struct i2c_msg *msg = msgs; 188 188 int ret = 0, mcnt = num; 189 189 190 - if (port->func->acquire) 191 - port->func->acquire(port); 190 + ret = nouveau_i2c(port)->acquire(port, nsecs_to_jiffies(T_TIMEOUT)); 191 + if (ret) 192 + return ret; 192 193 193 194 while (!ret && mcnt--) { 194 195 u8 remaining = msg->len; ··· 211 210 } 212 211 213 212 i2c_stop(port); 213 + nouveau_i2c(port)->release(port); 214 214 return (ret < 0) ? ret : num; 215 215 } 216 216 #else
+10 -23
drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <subdev/i2c.h> 26 25 #include <subdev/vga.h> 26 + 27 + #include "priv.h" 27 28 28 29 struct nv04_i2c_priv { 29 30 struct nouveau_i2c base; ··· 116 115 {} 117 116 }; 118 117 119 - static int 120 - nv04_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 121 - struct nouveau_oclass *oclass, void *data, u32 size, 122 - struct nouveau_object **pobject) 123 - { 124 - struct nv04_i2c_priv *priv; 125 - int ret; 126 - 127 - ret = nouveau_i2c_create(parent, engine, oclass, nv04_i2c_sclass, &priv); 128 - *pobject = nv_object(priv); 129 - if (ret) 130 - return ret; 131 - 132 - return 0; 133 - } 134 - 135 - struct nouveau_oclass 136 - nv04_i2c_oclass = { 137 - .handle = NV_SUBDEV(I2C, 0x04), 138 - .ofuncs = &(struct nouveau_ofuncs) { 139 - .ctor = nv04_i2c_ctor, 118 + struct nouveau_oclass * 119 + nv04_i2c_oclass = &(struct nouveau_i2c_impl) { 120 + .base.handle = NV_SUBDEV(I2C, 0x04), 121 + .base.ofuncs = &(struct nouveau_ofuncs) { 122 + .ctor = _nouveau_i2c_ctor, 140 123 .dtor = _nouveau_i2c_dtor, 141 124 .init = _nouveau_i2c_init, 142 125 .fini = _nouveau_i2c_fini, 143 126 }, 144 - }; 127 + .sclass = nv04_i2c_sclass, 128 + .pad_x = &nv04_i2c_pad_oclass, 129 + }.base;
+10 -23
drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c
··· 22 22 * Authors: Ben Skeggs 23 23 */ 24 24 25 - #include <subdev/i2c.h> 26 25 #include <subdev/vga.h> 26 + 27 + #include "priv.h" 27 28 28 29 struct nv4e_i2c_priv { 29 30 struct nouveau_i2c base; ··· 108 107 {} 109 108 }; 110 109 111 - static int 112 - nv4e_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 113 - struct nouveau_oclass *oclass, void *data, u32 size, 114 - struct nouveau_object **pobject) 115 - { 116 - struct nv4e_i2c_priv *priv; 117 - int ret; 118 - 119 - ret = nouveau_i2c_create(parent, engine, oclass, nv4e_i2c_sclass, &priv); 120 - *pobject = nv_object(priv); 121 - if (ret) 122 - return ret; 123 - 124 - return 0; 125 - } 126 - 127 - struct nouveau_oclass 128 - nv4e_i2c_oclass = { 129 - .handle = NV_SUBDEV(I2C, 0x4e), 130 - .ofuncs = &(struct nouveau_ofuncs) { 131 - .ctor = nv4e_i2c_ctor, 110 + struct nouveau_oclass * 111 + nv4e_i2c_oclass = &(struct nouveau_i2c_impl) { 112 + .base.handle = NV_SUBDEV(I2C, 0x4e), 113 + .base.ofuncs = &(struct nouveau_ofuncs) { 114 + .ctor = _nouveau_i2c_ctor, 132 115 .dtor = _nouveau_i2c_dtor, 133 116 .init = _nouveau_i2c_init, 134 117 .fini = _nouveau_i2c_fini, 135 118 }, 136 - }; 119 + .sclass = nv4e_i2c_sclass, 120 + .pad_x = &nv04_i2c_pad_oclass, 121 + }.base;
+8 -22
drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c
··· 121 121 {} 122 122 }; 123 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, 124 + struct nouveau_oclass * 125 + nv50_i2c_oclass = &(struct nouveau_i2c_impl) { 126 + .base.handle = NV_SUBDEV(I2C, 0x50), 127 + .base.ofuncs = &(struct nouveau_ofuncs) { 128 + .ctor = _nouveau_i2c_ctor, 145 129 .dtor = _nouveau_i2c_dtor, 146 130 .init = _nouveau_i2c_init, 147 131 .fini = _nouveau_i2c_fini, 148 132 }, 149 - }; 133 + .sclass = nv50_i2c_sclass, 134 + .pad_x = &nv04_i2c_pad_oclass, 135 + }.base;
+1 -1
drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.h
··· 1 1 #ifndef __NV50_I2C_H__ 2 2 #define __NV50_I2C_H__ 3 3 4 - #include <subdev/i2c.h> 4 + #include "priv.h" 5 5 6 6 struct nv50_i2c_priv { 7 7 struct nouveau_i2c base;
+57 -51
drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c
··· 24 24 25 25 #include "nv50.h" 26 26 27 + void 28 + nv94_aux_stat(struct nouveau_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) 29 + { 30 + u32 intr = nv_rd32(i2c, 0x00e06c); 31 + u32 stat = nv_rd32(i2c, 0x00e068) & intr, i; 32 + for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { 33 + if ((stat & (1 << (i * 4)))) *hi |= 1 << i; 34 + if ((stat & (2 << (i * 4)))) *lo |= 1 << i; 35 + if ((stat & (4 << (i * 4)))) *rq |= 1 << i; 36 + if ((stat & (8 << (i * 4)))) *tx |= 1 << i; 37 + } 38 + nv_wr32(i2c, 0x00e06c, intr); 39 + } 40 + 41 + void 42 + nv94_aux_mask(struct nouveau_i2c *i2c, u32 type, u32 mask, u32 data) 43 + { 44 + u32 temp = nv_rd32(i2c, 0x00e068), i; 45 + for (i = 0; i < 8; i++) { 46 + if (mask & (1 << i)) { 47 + if (!(data & (1 << i))) { 48 + temp &= ~(type << (i * 4)); 49 + continue; 50 + } 51 + temp |= type << (i * 4); 52 + } 53 + } 54 + nv_wr32(i2c, 0x00e068, temp); 55 + } 56 + 27 57 #define AUX_DBG(fmt, args...) nv_debug(aux, "AUXCH(%d): " fmt, ch, ##args) 28 58 #define AUX_ERR(fmt, args...) nv_error(aux, "AUXCH(%d): " fmt, ch, ##args) 29 59 ··· 99 69 } 100 70 101 71 int 102 - nv94_aux(struct nouveau_i2c_port *base, u8 type, u32 addr, u8 *data, u8 size) 72 + nv94_aux(struct nouveau_i2c_port *base, bool retry, 73 + u8 type, u32 addr, u8 *data, u8 size) 103 74 { 104 75 struct nouveau_i2c *aux = nouveau_i2c(base); 105 76 struct nv50_i2c_port *port = (void *)base; ··· 136 105 ctrl |= size - 1; 137 106 nv_wr32(aux, 0x00e4e0 + (ch * 0x50), addr); 138 107 139 - /* retry transaction a number of times on failure... */ 140 - ret = -EREMOTEIO; 141 - for (retries = 0; retries < 32; retries++) { 108 + /* (maybe) retry transaction a number of times on failure... */ 109 + for (retries = 0; !ret && retries < 32; retries++) { 142 110 /* reset, and delay a while if this is a retry */ 143 111 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x80000000 | ctrl); 144 112 nv_wr32(aux, 0x00e4e4 + (ch * 0x50), 0x00000000 | ctrl); ··· 153 123 udelay(1); 154 124 if (!timeout--) { 155 125 AUX_ERR("tx req timeout 0x%08x\n", ctrl); 126 + ret = -EIO; 156 127 goto out; 157 128 } 158 129 } while (ctrl & 0x00010000); 130 + ret = 1; 159 131 160 132 /* read status, and check if transaction completed ok */ 161 133 stat = nv_mask(aux, 0x00e4e8 + (ch * 0x50), 0, 0); 162 - if (!(stat & 0x000f0f00)) { 163 - ret = 0; 164 - break; 165 - } 134 + if ((stat & 0x000f0000) == 0x00080000 || 135 + (stat & 0x000f0000) == 0x00020000) 136 + ret = retry ? 0 : 1; 137 + if ((stat & 0x00000100)) 138 + ret = -ETIMEDOUT; 139 + if ((stat & 0x00000e00)) 140 + ret = -EIO; 166 141 167 142 AUX_DBG("%02d 0x%08x 0x%08x\n", retries, ctrl, stat); 168 143 } ··· 182 147 183 148 out: 184 149 auxch_fini(aux, ch); 185 - return ret; 186 - } 187 - 188 - void 189 - nv94_i2c_acquire(struct nouveau_i2c_port *base) 190 - { 191 - struct nv50_i2c_priv *priv = (void *)nv_object(base)->engine; 192 - struct nv50_i2c_port *port = (void *)base; 193 - if (port->ctrl) { 194 - nv_mask(priv, port->ctrl + 0x0c, 0x00000001, 0x00000000); 195 - nv_mask(priv, port->ctrl + 0x00, 0x0000f003, port->data); 196 - } 197 - } 198 - 199 - void 200 - nv94_i2c_release(struct nouveau_i2c_port *base) 201 - { 150 + return ret < 0 ? ret : (stat & 0x000f0000) >> 16; 202 151 } 203 152 204 153 static const struct nouveau_i2c_func 205 154 nv94_i2c_func = { 206 - .acquire = nv94_i2c_acquire, 207 - .release = nv94_i2c_release, 208 155 .drive_scl = nv50_i2c_drive_scl, 209 156 .drive_sda = nv50_i2c_drive_sda, 210 157 .sense_scl = nv50_i2c_sense_scl, ··· 223 206 224 207 static const struct nouveau_i2c_func 225 208 nv94_aux_func = { 226 - .acquire = nv94_i2c_acquire, 227 - .release = nv94_i2c_release, 228 209 .aux = nv94_aux, 229 210 }; 230 211 ··· 242 227 if (ret) 243 228 return ret; 244 229 230 + port->base.aux = info->drive; 245 231 port->addr = info->drive; 246 232 if (info->share != DCB_I2C_UNUSED) { 247 233 port->ctrl = 0x00e500 + (info->drive * 0x50); ··· 273 257 {} 274 258 }; 275 259 276 - static int 277 - nv94_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 278 - struct nouveau_oclass *oclass, void *data, u32 size, 279 - struct nouveau_object **pobject) 280 - { 281 - struct nv50_i2c_priv *priv; 282 - int ret; 283 - 284 - ret = nouveau_i2c_create(parent, engine, oclass, nv94_i2c_sclass, &priv); 285 - *pobject = nv_object(priv); 286 - if (ret) 287 - return ret; 288 - 289 - return 0; 290 - } 291 - 292 - struct nouveau_oclass 293 - nv94_i2c_oclass = { 294 - .handle = NV_SUBDEV(I2C, 0x94), 295 - .ofuncs = &(struct nouveau_ofuncs) { 296 - .ctor = nv94_i2c_ctor, 260 + struct nouveau_oclass * 261 + nv94_i2c_oclass = &(struct nouveau_i2c_impl) { 262 + .base.handle = NV_SUBDEV(I2C, 0x94), 263 + .base.ofuncs = &(struct nouveau_ofuncs) { 264 + .ctor = _nouveau_i2c_ctor, 297 265 .dtor = _nouveau_i2c_dtor, 298 266 .init = _nouveau_i2c_init, 299 267 .fini = _nouveau_i2c_fini, 300 268 }, 301 - }; 269 + .sclass = nv94_i2c_sclass, 270 + .pad_x = &nv04_i2c_pad_oclass, 271 + .pad_s = &nv94_i2c_pad_oclass, 272 + .aux = 4, 273 + .aux_stat = nv94_aux_stat, 274 + .aux_mask = nv94_aux_mask, 275 + }.base;
+13 -25
drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c
··· 42 42 43 43 static const struct nouveau_i2c_func 44 44 nvd0_i2c_func = { 45 - .acquire = nv94_i2c_acquire, 46 - .release = nv94_i2c_release, 47 45 .drive_scl = nv50_i2c_drive_scl, 48 46 .drive_sda = nv50_i2c_drive_sda, 49 47 .sense_scl = nvd0_i2c_sense_scl, ··· 73 75 return 0; 74 76 } 75 77 76 - static struct nouveau_oclass 78 + struct nouveau_oclass 77 79 nvd0_i2c_sclass[] = { 78 80 { .handle = NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT), 79 81 .ofuncs = &(struct nouveau_ofuncs) { ··· 94 96 {} 95 97 }; 96 98 97 - static int 98 - nvd0_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 99 - struct nouveau_oclass *oclass, void *data, u32 size, 100 - struct nouveau_object **pobject) 101 - { 102 - struct nv50_i2c_priv *priv; 103 - int ret; 104 - 105 - ret = nouveau_i2c_create(parent, engine, oclass, nvd0_i2c_sclass, &priv); 106 - *pobject = nv_object(priv); 107 - if (ret) 108 - return ret; 109 - 110 - return 0; 111 - } 112 - 113 - struct nouveau_oclass 114 - nvd0_i2c_oclass = { 115 - .handle = NV_SUBDEV(I2C, 0xd0), 116 - .ofuncs = &(struct nouveau_ofuncs) { 117 - .ctor = nvd0_i2c_ctor, 99 + struct nouveau_oclass * 100 + nvd0_i2c_oclass = &(struct nouveau_i2c_impl) { 101 + .base.handle = NV_SUBDEV(I2C, 0xd0), 102 + .base.ofuncs = &(struct nouveau_ofuncs) { 103 + .ctor = _nouveau_i2c_ctor, 118 104 .dtor = _nouveau_i2c_dtor, 119 105 .init = _nouveau_i2c_init, 120 106 .fini = _nouveau_i2c_fini, 121 107 }, 122 - }; 108 + .sclass = nvd0_i2c_sclass, 109 + .pad_x = &nv04_i2c_pad_oclass, 110 + .pad_s = &nv94_i2c_pad_oclass, 111 + .aux = 4, 112 + .aux_stat = nv94_aux_stat, 113 + .aux_mask = nv94_aux_mask, 114 + }.base;
+72
drivers/gpu/drm/nouveau/core/subdev/i2c/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 "nv50.h" 26 + 27 + static void 28 + nve0_aux_stat(struct nouveau_i2c *i2c, u32 *hi, u32 *lo, u32 *rq, u32 *tx) 29 + { 30 + u32 intr = nv_rd32(i2c, 0x00dc60); 31 + u32 stat = nv_rd32(i2c, 0x00dc68) & intr, i; 32 + for (i = 0, *hi = *lo = *rq = *tx = 0; i < 8; i++) { 33 + if ((stat & (1 << (i * 4)))) *hi |= 1 << i; 34 + if ((stat & (2 << (i * 4)))) *lo |= 1 << i; 35 + if ((stat & (4 << (i * 4)))) *rq |= 1 << i; 36 + if ((stat & (8 << (i * 4)))) *tx |= 1 << i; 37 + } 38 + nv_wr32(i2c, 0x00dc60, intr); 39 + } 40 + 41 + static void 42 + nve0_aux_mask(struct nouveau_i2c *i2c, u32 type, u32 mask, u32 data) 43 + { 44 + u32 temp = nv_rd32(i2c, 0x00dc68), i; 45 + for (i = 0; i < 8; i++) { 46 + if (mask & (1 << i)) { 47 + if (!(data & (1 << i))) { 48 + temp &= ~(type << (i * 4)); 49 + continue; 50 + } 51 + temp |= type << (i * 4); 52 + } 53 + } 54 + nv_wr32(i2c, 0x00dc68, temp); 55 + } 56 + 57 + struct nouveau_oclass * 58 + nve0_i2c_oclass = &(struct nouveau_i2c_impl) { 59 + .base.handle = NV_SUBDEV(I2C, 0xe0), 60 + .base.ofuncs = &(struct nouveau_ofuncs) { 61 + .ctor = _nouveau_i2c_ctor, 62 + .dtor = _nouveau_i2c_dtor, 63 + .init = _nouveau_i2c_init, 64 + .fini = _nouveau_i2c_fini, 65 + }, 66 + .sclass = nvd0_i2c_sclass, 67 + .pad_x = &nv04_i2c_pad_oclass, 68 + .pad_s = &nv94_i2c_pad_oclass, 69 + .aux = 4, 70 + .aux_stat = nve0_aux_stat, 71 + .aux_mask = nve0_aux_mask, 72 + }.base;
+84
drivers/gpu/drm/nouveau/core/subdev/i2c/pad.c
··· 1 + /* 2 + * Copyright 2014 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 "pad.h" 26 + 27 + int 28 + _nvkm_i2c_pad_fini(struct nouveau_object *object, bool suspend) 29 + { 30 + struct nvkm_i2c_pad *pad = (void *)object; 31 + DBG("-> NULL\n"); 32 + pad->port = NULL; 33 + return nouveau_object_fini(&pad->base, suspend); 34 + } 35 + 36 + int 37 + _nvkm_i2c_pad_init(struct nouveau_object *object) 38 + { 39 + struct nvkm_i2c_pad *pad = (void *)object; 40 + DBG("-> PORT:%02x\n", pad->next->index); 41 + pad->port = pad->next; 42 + return nouveau_object_init(&pad->base); 43 + } 44 + 45 + int 46 + nvkm_i2c_pad_create_(struct nouveau_object *parent, 47 + struct nouveau_object *engine, 48 + struct nouveau_oclass *oclass, int index, 49 + int size, void **pobject) 50 + { 51 + struct nouveau_i2c *i2c = (void *)engine; 52 + struct nouveau_i2c_port *port; 53 + struct nvkm_i2c_pad *pad; 54 + int ret; 55 + 56 + list_for_each_entry(port, &i2c->ports, head) { 57 + pad = nvkm_i2c_pad(port); 58 + if (pad->index == index) { 59 + atomic_inc(&nv_object(pad)->refcount); 60 + *pobject = pad; 61 + return 1; 62 + } 63 + } 64 + 65 + ret = nouveau_object_create_(parent, engine, oclass, 0, size, pobject); 66 + pad = *pobject; 67 + if (ret) 68 + return ret; 69 + 70 + pad->index = index; 71 + return 0; 72 + } 73 + 74 + int 75 + _nvkm_i2c_pad_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 76 + struct nouveau_oclass *oclass, void *data, u32 index, 77 + struct nouveau_object **pobject) 78 + { 79 + struct nvkm_i2c_pad *pad; 80 + int ret; 81 + ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); 82 + *pobject = nv_object(pad); 83 + return ret; 84 + }
+58
drivers/gpu/drm/nouveau/core/subdev/i2c/pad.h
··· 1 + #ifndef __NVKM_I2C_PAD_H__ 2 + #define __NVKM_I2C_PAD_H__ 3 + 4 + #include "priv.h" 5 + 6 + struct nvkm_i2c_pad { 7 + struct nouveau_object base; 8 + int index; 9 + struct nouveau_i2c_port *port; 10 + struct nouveau_i2c_port *next; 11 + }; 12 + 13 + static inline struct nvkm_i2c_pad * 14 + nvkm_i2c_pad(struct nouveau_i2c_port *port) 15 + { 16 + struct nouveau_object *pad = nv_object(port); 17 + while (pad->parent) 18 + pad = pad->parent; 19 + return (void *)pad; 20 + } 21 + 22 + #define nvkm_i2c_pad_create(p,e,o,i,d) \ 23 + nvkm_i2c_pad_create_((p), (e), (o), (i), sizeof(**d), (void **)d) 24 + #define nvkm_i2c_pad_destroy(p) ({ \ 25 + struct nvkm_i2c_pad *_p = (p); \ 26 + _nvkm_i2c_pad_dtor(nv_object(_p)); \ 27 + }) 28 + #define nvkm_i2c_pad_init(p) ({ \ 29 + struct nvkm_i2c_pad *_p = (p); \ 30 + _nvkm_i2c_pad_init(nv_object(_p)); \ 31 + }) 32 + #define nvkm_i2c_pad_fini(p,s) ({ \ 33 + struct nvkm_i2c_pad *_p = (p); \ 34 + _nvkm_i2c_pad_fini(nv_object(_p), (s)); \ 35 + }) 36 + 37 + int nvkm_i2c_pad_create_(struct nouveau_object *, struct nouveau_object *, 38 + struct nouveau_oclass *, int index, int, void **); 39 + 40 + int _nvkm_i2c_pad_ctor(struct nouveau_object *, struct nouveau_object *, 41 + struct nouveau_oclass *, void *, u32, 42 + struct nouveau_object **); 43 + #define _nvkm_i2c_pad_dtor nouveau_object_destroy 44 + int _nvkm_i2c_pad_init(struct nouveau_object *); 45 + int _nvkm_i2c_pad_fini(struct nouveau_object *, bool); 46 + 47 + #ifndef MSG 48 + #define MSG(l,f,a...) do { \ 49 + struct nvkm_i2c_pad *_pad = (void *)pad; \ 50 + nv_##l(nv_object(_pad)->engine, "PAD:%c:%02x: "f, \ 51 + _pad->index >= 0x100 ? 'X' : 'S', \ 52 + _pad->index >= 0x100 ? _pad->index - 0x100 : _pad->index, ##a); \ 53 + } while(0) 54 + #define DBG(f,a...) MSG(debug, f, ##a) 55 + #define ERR(f,a...) MSG(error, f, ##a) 56 + #endif 57 + 58 + #endif
+35
drivers/gpu/drm/nouveau/core/subdev/i2c/padnv04.c
··· 1 + /* 2 + * Copyright 2014 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 "pad.h" 26 + 27 + struct nouveau_oclass 28 + nv04_i2c_pad_oclass = { 29 + .ofuncs = &(struct nouveau_ofuncs) { 30 + .ctor = _nvkm_i2c_pad_ctor, 31 + .dtor = _nvkm_i2c_pad_dtor, 32 + .init = _nvkm_i2c_pad_init, 33 + .fini = _nvkm_i2c_pad_fini, 34 + }, 35 + };
+86
drivers/gpu/drm/nouveau/core/subdev/i2c/padnv94.c
··· 1 + /* 2 + * Copyright 2014 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 "pad.h" 26 + 27 + struct nv94_i2c_pad { 28 + struct nvkm_i2c_pad base; 29 + int addr; 30 + }; 31 + 32 + static int 33 + nv94_i2c_pad_fini(struct nouveau_object *object, bool suspend) 34 + { 35 + struct nouveau_i2c *i2c = (void *)object->engine; 36 + struct nv94_i2c_pad *pad = (void *)object; 37 + nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000001); 38 + return nvkm_i2c_pad_fini(&pad->base, suspend); 39 + } 40 + 41 + static int 42 + nv94_i2c_pad_init(struct nouveau_object *object) 43 + { 44 + struct nouveau_i2c *i2c = (void *)object->engine; 45 + struct nv94_i2c_pad *pad = (void *)object; 46 + 47 + switch (nv_oclass(pad->base.next)->handle) { 48 + case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_AUX): 49 + nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x00000002); 50 + break; 51 + case NV_I2C_TYPE_DCBI2C(DCB_I2C_NVIO_BIT): 52 + default: 53 + nv_mask(i2c, 0x00e500 + pad->addr, 0x0000c003, 0x0000c001); 54 + break; 55 + } 56 + 57 + nv_mask(i2c, 0x00e50c + pad->addr, 0x00000001, 0x00000000); 58 + return nvkm_i2c_pad_init(&pad->base); 59 + } 60 + 61 + static int 62 + nv94_i2c_pad_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 63 + struct nouveau_oclass *oclass, void *data, u32 index, 64 + struct nouveau_object **pobject) 65 + { 66 + struct nv94_i2c_pad *pad; 67 + int ret; 68 + 69 + ret = nvkm_i2c_pad_create(parent, engine, oclass, index, &pad); 70 + *pobject = nv_object(pad); 71 + if (ret) 72 + return ret; 73 + 74 + pad->addr = index * 0x50;; 75 + return 0; 76 + } 77 + 78 + struct nouveau_oclass 79 + nv94_i2c_pad_oclass = { 80 + .ofuncs = &(struct nouveau_ofuncs) { 81 + .ctor = nv94_i2c_pad_ctor, 82 + .dtor = _nvkm_i2c_pad_dtor, 83 + .init = nv94_i2c_pad_init, 84 + .fini = nv94_i2c_pad_fini, 85 + }, 86 + };
+15
drivers/gpu/drm/nouveau/core/subdev/i2c/port.h
··· 1 + #ifndef __NVKM_I2C_PORT_H__ 2 + #define __NVKM_I2C_PORT_H__ 3 + 4 + #include "priv.h" 5 + 6 + #ifndef MSG 7 + #define MSG(l,f,a...) do { \ 8 + struct nouveau_i2c_port *_port = (void *)port; \ 9 + nv_##l(nv_object(_port)->engine, "PORT:%02x: "f, _port->index, ##a); \ 10 + } while(0) 11 + #define DBG(f,a...) MSG(debug, f, ##a) 12 + #define ERR(f,a...) MSG(error, f, ##a) 13 + #endif 14 + 15 + #endif
+85
drivers/gpu/drm/nouveau/core/subdev/i2c/priv.h
··· 1 + #ifndef __NVKM_I2C_H__ 2 + #define __NVKM_I2C_H__ 3 + 4 + #include <subdev/i2c.h> 5 + 6 + extern struct nouveau_oclass nv04_i2c_pad_oclass; 7 + extern struct nouveau_oclass nv94_i2c_pad_oclass; 8 + 9 + #define nouveau_i2c_port_create(p,e,o,i,a,f,d) \ 10 + nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f), \ 11 + sizeof(**d), (void **)d) 12 + #define nouveau_i2c_port_destroy(p) ({ \ 13 + struct nouveau_i2c_port *port = (p); \ 14 + _nouveau_i2c_port_dtor(nv_object(i2c)); \ 15 + }) 16 + #define nouveau_i2c_port_init(p) \ 17 + nouveau_object_init(&(p)->base) 18 + #define nouveau_i2c_port_fini(p,s) \ 19 + nouveau_object_fini(&(p)->base, (s)) 20 + 21 + int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, 22 + struct nouveau_oclass *, u8, 23 + const struct i2c_algorithm *, 24 + const struct nouveau_i2c_func *, 25 + int, void **); 26 + void _nouveau_i2c_port_dtor(struct nouveau_object *); 27 + #define _nouveau_i2c_port_init nouveau_object_init 28 + int _nouveau_i2c_port_fini(struct nouveau_object *, bool); 29 + 30 + #define nouveau_i2c_create(p,e,o,d) \ 31 + nouveau_i2c_create_((p), (e), (o), sizeof(**d), (void **)d) 32 + #define nouveau_i2c_destroy(p) ({ \ 33 + struct nouveau_i2c *i2c = (p); \ 34 + _nouveau_i2c_dtor(nv_object(i2c)); \ 35 + }) 36 + #define nouveau_i2c_init(p) ({ \ 37 + struct nouveau_i2c *i2c = (p); \ 38 + _nouveau_i2c_init(nv_object(i2c)); \ 39 + }) 40 + #define nouveau_i2c_fini(p,s) ({ \ 41 + struct nouveau_i2c *i2c = (p); \ 42 + _nouveau_i2c_fini(nv_object(i2c), (s)); \ 43 + }) 44 + 45 + int nouveau_i2c_create_(struct nouveau_object *, struct nouveau_object *, 46 + struct nouveau_oclass *, int, void **); 47 + int _nouveau_i2c_ctor(struct nouveau_object *, struct nouveau_object *, 48 + struct nouveau_oclass *, void *, u32, 49 + struct nouveau_object **); 50 + void _nouveau_i2c_dtor(struct nouveau_object *); 51 + int _nouveau_i2c_init(struct nouveau_object *); 52 + int _nouveau_i2c_fini(struct nouveau_object *, bool); 53 + 54 + extern struct nouveau_oclass nouveau_anx9805_sclass[]; 55 + extern struct nouveau_oclass nvd0_i2c_sclass[]; 56 + 57 + extern const struct i2c_algorithm nouveau_i2c_bit_algo; 58 + extern const struct i2c_algorithm nouveau_i2c_aux_algo; 59 + 60 + struct nouveau_i2c_impl { 61 + struct nouveau_oclass base; 62 + 63 + /* supported i2c port classes */ 64 + struct nouveau_oclass *sclass; 65 + struct nouveau_oclass *pad_x; 66 + struct nouveau_oclass *pad_s; 67 + 68 + /* number of native dp aux channels present */ 69 + int aux; 70 + 71 + /* read and ack pending interrupts, returning only data 72 + * for ports that have not been masked off, while still 73 + * performing the ack for anything that was pending. 74 + */ 75 + void (*aux_stat)(struct nouveau_i2c *, u32 *, u32 *, u32 *, u32 *); 76 + 77 + /* mask on/off interrupt types for a given set of auxch 78 + */ 79 + void (*aux_mask)(struct nouveau_i2c *, u32, u32, u32); 80 + }; 81 + 82 + void nv94_aux_stat(struct nouveau_i2c *, u32 *, u32 *, u32 *, u32 *); 83 + void nv94_aux_mask(struct nouveau_i2c *, u32, u32, u32); 84 + 85 + #endif
+2 -1
drivers/gpu/drm/nouveau/core/subdev/mc/nv50.c
··· 34 34 { 0x00008000, NVDEV_ENGINE_BSP }, /* NV84- */ 35 35 { 0x00020000, NVDEV_ENGINE_VP }, /* NV84- */ 36 36 { 0x00100000, NVDEV_SUBDEV_TIMER }, 37 - { 0x00200000, NVDEV_SUBDEV_GPIO }, 37 + { 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */ 38 + { 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */ 38 39 { 0x10000000, NVDEV_SUBDEV_BUS }, 39 40 { 0x80000000, NVDEV_ENGINE_SW }, 40 41 { 0x0002d101, NVDEV_SUBDEV_FB },
+2 -1
drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c
··· 36 36 { 0x00040000, NVDEV_SUBDEV_PWR }, /* NVA3:NVC0 */ 37 37 { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ 38 38 { 0x00100000, NVDEV_SUBDEV_TIMER }, 39 - { 0x00200000, NVDEV_SUBDEV_GPIO }, 39 + { 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */ 40 + { 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */ 40 41 { 0x00400000, NVDEV_ENGINE_COPY0 }, /* NVA3- */ 41 42 { 0x10000000, NVDEV_SUBDEV_BUS }, 42 43 { 0x80000000, NVDEV_ENGINE_SW },
+2 -1
drivers/gpu/drm/nouveau/core/subdev/mc/nvc0.c
··· 38 38 { 0x00040000, NVDEV_SUBDEV_THERM }, 39 39 { 0x00020000, NVDEV_ENGINE_VP }, 40 40 { 0x00100000, NVDEV_SUBDEV_TIMER }, 41 - { 0x00200000, NVDEV_SUBDEV_GPIO }, 41 + { 0x00200000, NVDEV_SUBDEV_GPIO }, /* PMGR->GPIO */ 42 + { 0x00200000, NVDEV_SUBDEV_I2C }, /* PMGR->I2C/AUX */ 42 43 { 0x01000000, NVDEV_SUBDEV_PWR }, 43 44 { 0x02000000, NVDEV_SUBDEV_LTCG }, 44 45 { 0x08000000, NVDEV_SUBDEV_FB },
+1 -1
drivers/gpu/drm/nouveau/core/subdev/mxm/nv50.c
··· 150 150 * common example is DP->eDP. 151 151 */ 152 152 conn = bios->data; 153 - conn += dcb_conn(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len); 153 + conn += nvbios_connEe(bios, (ctx.outp[0] & 0x0000f000) >> 12, &ver, &len); 154 154 type = conn[0]; 155 155 switch (ctx.desc.conn_type) { 156 156 case 0x01: /* LVDS */
+137 -71
drivers/gpu/drm/nouveau/nouveau_connector.c
··· 44 44 45 45 #include <subdev/i2c.h> 46 46 #include <subdev/gpio.h> 47 + #include <engine/disp.h> 47 48 48 49 MODULE_PARM_DESC(tv_disable, "Disable TV-out detection"); 49 50 static int nouveau_tv_disable = 0; ··· 76 75 continue; 77 76 nv_encoder = nouveau_encoder(obj_to_encoder(obj)); 78 77 79 - if (type == DCB_OUTPUT_ANY || nv_encoder->dcb->type == type) 78 + if (type == DCB_OUTPUT_ANY || 79 + (nv_encoder->dcb && nv_encoder->dcb->type == type)) 80 80 return nv_encoder; 81 81 } 82 82 ··· 102 100 nouveau_connector_destroy(struct drm_connector *connector) 103 101 { 104 102 struct nouveau_connector *nv_connector = nouveau_connector(connector); 105 - nouveau_event_ref(NULL, &nv_connector->hpd_func); 103 + nouveau_event_ref(NULL, &nv_connector->hpd); 106 104 kfree(nv_connector->edid); 107 105 drm_sysfs_connector_remove(connector); 108 106 drm_connector_cleanup(connector); 107 + if (nv_connector->aux.transfer) 108 + drm_dp_aux_unregister(&nv_connector->aux); 109 109 kfree(connector); 110 110 } 111 111 112 - static struct nouveau_i2c_port * 113 - nouveau_connector_ddc_detect(struct drm_connector *connector, 114 - struct nouveau_encoder **pnv_encoder) 112 + static struct nouveau_encoder * 113 + nouveau_connector_ddc_detect(struct drm_connector *connector) 115 114 { 116 115 struct drm_device *dev = connector->dev; 117 116 struct nouveau_connector *nv_connector = nouveau_connector(connector); 118 117 struct nouveau_drm *drm = nouveau_drm(dev); 119 118 struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 120 - struct nouveau_i2c_port *port = NULL; 119 + struct nouveau_encoder *nv_encoder; 120 + struct drm_mode_object *obj; 121 121 int i, panel = -ENODEV; 122 122 123 123 /* eDP panels need powering on by us (if the VBIOS doesn't default it ··· 134 130 } 135 131 } 136 132 137 - for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { 138 - struct nouveau_encoder *nv_encoder; 139 - struct drm_mode_object *obj; 140 - int id; 141 - 142 - id = connector->encoder_ids[i]; 143 - if (!id) 133 + for (i = 0; nv_encoder = NULL, i < DRM_CONNECTOR_MAX_ENCODER; i++) { 134 + int id = connector->encoder_ids[i]; 135 + if (id == 0) 144 136 break; 145 137 146 138 obj = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER); ··· 144 144 continue; 145 145 nv_encoder = nouveau_encoder(obj_to_encoder(obj)); 146 146 147 - port = nv_encoder->i2c; 148 - if (port && nv_probe_i2c(port, 0x50)) { 149 - *pnv_encoder = nv_encoder; 150 - break; 147 + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { 148 + int ret = nouveau_dp_detect(nv_encoder); 149 + if (ret == 0) 150 + break; 151 + } else 152 + if (nv_encoder->i2c) { 153 + if (nv_probe_i2c(nv_encoder->i2c, 0x50)) 154 + break; 151 155 } 152 - 153 - port = NULL; 154 156 } 155 157 156 158 /* eDP panel not detected, restore panel power GPIO to previous 157 159 * state to avoid confusing the SOR for other output types. 158 160 */ 159 - if (!port && panel == 0) 161 + if (!nv_encoder && panel == 0) 160 162 gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); 161 163 162 - return port; 164 + return nv_encoder; 163 165 } 164 166 165 167 static struct nouveau_encoder * ··· 260 258 if (ret < 0 && ret != -EACCES) 261 259 return conn_status; 262 260 263 - i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); 264 - if (i2c) { 261 + nv_encoder = nouveau_connector_ddc_detect(connector); 262 + if (nv_encoder && (i2c = nv_encoder->i2c) != NULL) { 265 263 nv_connector->edid = drm_get_edid(connector, &i2c->adapter); 266 264 drm_mode_connector_update_edid_property(connector, 267 265 nv_connector->edid); ··· 269 267 NV_ERROR(drm, "DDC responded, but no EDID for %s\n", 270 268 connector->name); 271 269 goto detect_analog; 272 - } 273 - 274 - if (nv_encoder->dcb->type == DCB_OUTPUT_DP && 275 - !nouveau_dp_detect(to_drm_encoder(nv_encoder))) { 276 - NV_ERROR(drm, "Detected %s, but failed init\n", 277 - connector->name); 278 - conn_status = connector_status_disconnected; 279 - goto out; 280 270 } 281 271 282 272 /* Override encoder type for DVI-I based on whether EDID ··· 906 912 }; 907 913 908 914 static void 915 + nouveau_connector_dp_dpms(struct drm_connector *connector, int mode) 916 + { 917 + struct nouveau_encoder *nv_encoder = NULL; 918 + 919 + if (connector->encoder) 920 + nv_encoder = nouveau_encoder(connector->encoder); 921 + if (nv_encoder && nv_encoder->dcb && 922 + nv_encoder->dcb->type == DCB_OUTPUT_DP) { 923 + if (mode == DRM_MODE_DPMS_ON) { 924 + u8 data = DP_SET_POWER_D0; 925 + nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1); 926 + usleep_range(1000, 2000); 927 + } else { 928 + u8 data = DP_SET_POWER_D3; 929 + nv_wraux(nv_encoder->i2c, DP_SET_POWER, &data, 1); 930 + } 931 + } 932 + 933 + drm_helper_connector_dpms(connector, mode); 934 + } 935 + 936 + static const struct drm_connector_funcs 937 + nouveau_connector_funcs_dp = { 938 + .dpms = nouveau_connector_dp_dpms, 939 + .save = NULL, 940 + .restore = NULL, 941 + .detect = nouveau_connector_detect, 942 + .destroy = nouveau_connector_destroy, 943 + .fill_modes = drm_helper_probe_single_connector_modes, 944 + .set_property = nouveau_connector_set_property, 945 + .force = nouveau_connector_force 946 + }; 947 + 948 + static void 909 949 nouveau_connector_hotplug_work(struct work_struct *work) 910 950 { 911 951 struct nouveau_connector *nv_connector = 912 - container_of(work, struct nouveau_connector, hpd_work); 952 + container_of(work, typeof(*nv_connector), work); 913 953 struct drm_connector *connector = &nv_connector->base; 914 - struct drm_device *dev = connector->dev; 915 - struct nouveau_drm *drm = nouveau_drm(dev); 916 - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 917 - bool plugged = gpio->get(gpio, 0, nv_connector->hpd.func, 0xff); 954 + struct nouveau_drm *drm = nouveau_drm(connector->dev); 955 + const char *name = connector->name; 918 956 919 - NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", 920 - connector->name); 957 + if (nv_connector->status & NVKM_HPD_IRQ) { 958 + } else { 959 + bool plugged = (nv_connector->status != NVKM_HPD_UNPLUG); 921 960 922 - if (plugged) 923 - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); 924 - else 925 - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); 961 + NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", name); 926 962 927 - drm_helper_hpd_irq_event(dev); 963 + if (plugged) 964 + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); 965 + else 966 + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); 967 + drm_helper_hpd_irq_event(connector->dev); 968 + } 969 + 970 + nouveau_event_get(nv_connector->hpd); 928 971 } 929 972 930 973 static int 931 - nouveau_connector_hotplug(void *data, int index) 974 + nouveau_connector_hotplug(void *data, u32 type, int index) 932 975 { 933 976 struct nouveau_connector *nv_connector = data; 934 - schedule_work(&nv_connector->hpd_work); 935 - return NVKM_EVENT_KEEP; 977 + nv_connector->status = type; 978 + schedule_work(&nv_connector->work); 979 + return NVKM_EVENT_DROP; 980 + } 981 + 982 + static ssize_t 983 + nouveau_connector_aux_xfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) 984 + { 985 + struct nouveau_connector *nv_connector = 986 + container_of(aux, typeof(*nv_connector), aux); 987 + struct nouveau_encoder *nv_encoder; 988 + struct nouveau_i2c_port *port; 989 + int ret; 990 + 991 + nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP); 992 + if (!nv_encoder || !(port = nv_encoder->i2c)) 993 + return -ENODEV; 994 + if (WARN_ON(msg->size > 16)) 995 + return -E2BIG; 996 + if (msg->size == 0) 997 + return msg->size; 998 + 999 + ret = nouveau_i2c(port)->acquire(port, 0); 1000 + if (ret) 1001 + return ret; 1002 + 1003 + ret = port->func->aux(port, false, msg->request, msg->address, 1004 + msg->buffer, msg->size); 1005 + nouveau_i2c(port)->release(port); 1006 + if (ret >= 0) { 1007 + msg->reply = ret; 1008 + return msg->size; 1009 + } 1010 + 1011 + return ret; 936 1012 } 937 1013 938 1014 static int ··· 1038 974 { 1039 975 const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; 1040 976 struct nouveau_drm *drm = nouveau_drm(dev); 1041 - struct nouveau_gpio *gpio = nouveau_gpio(drm->device); 1042 977 struct nouveau_display *disp = nouveau_display(dev); 1043 978 struct nouveau_connector *nv_connector = NULL; 979 + struct nouveau_disp *pdisp = nouveau_disp(drm->device); 1044 980 struct drm_connector *connector; 1045 981 int type, ret = 0; 1046 982 bool dummy; ··· 1056 992 return ERR_PTR(-ENOMEM); 1057 993 1058 994 connector = &nv_connector->base; 1059 - INIT_WORK(&nv_connector->hpd_work, nouveau_connector_hotplug_work); 1060 995 nv_connector->index = index; 1061 996 1062 997 /* attempt to parse vbios connector type and hotplug gpio */ 1063 998 nv_connector->dcb = olddcb_conn(dev, index); 1064 999 if (nv_connector->dcb) { 1065 - static const u8 hpd[16] = { 1066 - 0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff, 1067 - 0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60, 1068 - }; 1069 - 1070 1000 u32 entry = ROM16(nv_connector->dcb[0]); 1071 1001 if (olddcb_conntab(dev)[3] >= 4) 1072 1002 entry |= (u32)ROM16(nv_connector->dcb[2]) << 16; 1073 - 1074 - ret = gpio->find(gpio, 0, hpd[ffs((entry & 0x07033000) >> 12)], 1075 - DCB_GPIO_UNUSED, &nv_connector->hpd); 1076 - if (ret) 1077 - nv_connector->hpd.func = DCB_GPIO_UNUSED; 1078 - 1079 - if (nv_connector->hpd.func != DCB_GPIO_UNUSED) { 1080 - nouveau_event_new(gpio->events, nv_connector->hpd.line, 1081 - nouveau_connector_hotplug, 1082 - nv_connector, 1083 - &nv_connector->hpd_func); 1084 - } 1085 1003 1086 1004 nv_connector->type = nv_connector->dcb[0]; 1087 1005 if (drm_conntype_from_dcb(nv_connector->type) == ··· 1086 1040 } 1087 1041 } else { 1088 1042 nv_connector->type = DCB_CONNECTOR_NONE; 1089 - nv_connector->hpd.func = DCB_GPIO_UNUSED; 1090 1043 } 1091 1044 1092 1045 /* no vbios data, or an unknown dcb connector type - attempt to ··· 1125 1080 } 1126 1081 } 1127 1082 1128 - type = drm_conntype_from_dcb(nv_connector->type); 1129 - if (type == DRM_MODE_CONNECTOR_LVDS) { 1083 + switch ((type = drm_conntype_from_dcb(nv_connector->type))) { 1084 + case DRM_MODE_CONNECTOR_LVDS: 1130 1085 ret = nouveau_bios_parse_lvds_table(dev, 0, &dummy, &dummy); 1131 1086 if (ret) { 1132 1087 NV_ERROR(drm, "Error parsing LVDS table, disabling\n"); ··· 1135 1090 } 1136 1091 1137 1092 funcs = &nouveau_connector_funcs_lvds; 1138 - } else { 1093 + break; 1094 + case DRM_MODE_CONNECTOR_DisplayPort: 1095 + case DRM_MODE_CONNECTOR_eDP: 1096 + nv_connector->aux.dev = dev->dev; 1097 + nv_connector->aux.transfer = nouveau_connector_aux_xfer; 1098 + ret = drm_dp_aux_register(&nv_connector->aux); 1099 + if (ret) { 1100 + NV_ERROR(drm, "failed to register aux channel\n"); 1101 + kfree(nv_connector); 1102 + return ERR_PTR(ret); 1103 + } 1104 + 1105 + funcs = &nouveau_connector_funcs_dp; 1106 + break; 1107 + default: 1139 1108 funcs = &nouveau_connector_funcs; 1109 + break; 1140 1110 } 1141 1111 1142 1112 /* defaults, will get overridden in detect() */ ··· 1226 1166 break; 1227 1167 } 1228 1168 1229 - connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1230 - if (nv_connector->hpd.func != DCB_GPIO_UNUSED) 1169 + ret = nouveau_event_new(pdisp->hpd, NVKM_HPD, index, 1170 + nouveau_connector_hotplug, 1171 + nv_connector, &nv_connector->hpd); 1172 + if (ret) 1173 + connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1174 + else 1231 1175 connector->polled = DRM_CONNECTOR_POLL_HPD; 1176 + 1177 + INIT_WORK(&nv_connector->work, nouveau_connector_hotplug_work); 1232 1178 1233 1179 drm_sysfs_connector_add(connector); 1234 1180 return connector;
+6 -4
drivers/gpu/drm/nouveau/nouveau_connector.h
··· 28 28 #define __NOUVEAU_CONNECTOR_H__ 29 29 30 30 #include <drm/drm_edid.h> 31 + #include <drm/drm_dp_helper.h> 31 32 #include "nouveau_crtc.h" 32 33 33 34 #include <core/event.h> 34 35 35 36 #include <subdev/bios.h> 36 - #include <subdev/bios/gpio.h> 37 37 38 38 struct nouveau_i2c_port; 39 39 ··· 67 67 u8 index; 68 68 u8 *dcb; 69 69 70 - struct dcb_gpio_func hpd; 71 - struct work_struct hpd_work; 72 - struct nouveau_eventh *hpd_func; 70 + struct nouveau_eventh *hpd; 71 + u32 status; 72 + struct work_struct work; 73 + 74 + struct drm_dp_aux aux; 73 75 74 76 int dithering_mode; 75 77 int dithering_depth;
+1 -1
drivers/gpu/drm/nouveau/nouveau_crtc.h
··· 74 74 75 75 static inline struct nouveau_crtc *nouveau_crtc(struct drm_crtc *crtc) 76 76 { 77 - return container_of(crtc, struct nouveau_crtc, base); 77 + return crtc ? container_of(crtc, struct nouveau_crtc, base) : NULL; 78 78 } 79 79 80 80 static inline struct drm_crtc *to_drm_crtc(struct nouveau_crtc *crtc)
+4 -4
drivers/gpu/drm/nouveau/nouveau_display.c
··· 42 42 #include <core/class.h> 43 43 44 44 static int 45 - nouveau_display_vblank_handler(void *data, int head) 45 + nouveau_display_vblank_handler(void *data, u32 type, int head) 46 46 { 47 47 struct nouveau_drm *drm = data; 48 48 drm_handle_vblank(drm->dev, head); ··· 178 178 return -ENOMEM; 179 179 180 180 for (i = 0; i < dev->mode_config.num_crtc; i++) { 181 - ret = nouveau_event_new(pdisp->vblank, i, 181 + ret = nouveau_event_new(pdisp->vblank, 1, i, 182 182 nouveau_display_vblank_handler, 183 183 drm, &disp->vblank[i]); 184 184 if (ret) { ··· 393 393 /* enable hotplug interrupts */ 394 394 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 395 395 struct nouveau_connector *conn = nouveau_connector(connector); 396 - if (conn->hpd_func) nouveau_event_get(conn->hpd_func); 396 + if (conn->hpd) nouveau_event_get(conn->hpd); 397 397 } 398 398 399 399 return ret; ··· 408 408 /* disable hotplug interrupts */ 409 409 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 410 410 struct nouveau_connector *conn = nouveau_connector(connector); 411 - if (conn->hpd_func) nouveau_event_put(conn->hpd_func); 411 + if (conn->hpd) nouveau_event_put(conn->hpd); 412 412 } 413 413 414 414 drm_kms_helper_poll_disable(dev);
+6 -8
drivers/gpu/drm/nouveau/nouveau_dp.c
··· 55 55 56 56 } 57 57 58 - bool 59 - nouveau_dp_detect(struct drm_encoder *encoder) 58 + int 59 + nouveau_dp_detect(struct nouveau_encoder *nv_encoder) 60 60 { 61 - struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 62 - struct drm_device *dev = encoder->dev; 61 + struct drm_device *dev = nv_encoder->base.base.dev; 63 62 struct nouveau_drm *drm = nouveau_drm(dev); 64 63 struct nouveau_i2c_port *auxch; 65 64 u8 *dpcd = nv_encoder->dp.dpcd; ··· 66 67 67 68 auxch = nv_encoder->i2c; 68 69 if (!auxch) 69 - return false; 70 + return -ENODEV; 70 71 71 72 ret = nv_rdaux(auxch, DP_DPCD_REV, dpcd, 8); 72 73 if (ret) 73 - return false; 74 + return ret; 74 75 75 76 nv_encoder->dp.link_bw = 27000 * dpcd[1]; 76 77 nv_encoder->dp.link_nr = dpcd[2] & DP_MAX_LANE_COUNT_MASK; ··· 90 91 nv_encoder->dp.link_nr, nv_encoder->dp.link_bw); 91 92 92 93 nouveau_dp_probe_oui(dev, auxch, dpcd); 93 - 94 - return true; 94 + return 0; 95 95 }
+2 -3
drivers/gpu/drm/nouveau/nouveau_encoder.h
··· 46 46 /* different to drm_encoder.crtc, this reflects what's 47 47 * actually programmed on the hw, not the proposed crtc */ 48 48 struct drm_crtc *crtc; 49 + u32 ctrl; 49 50 50 51 struct drm_display_mode mode; 51 52 int last_dpms; ··· 85 84 } 86 85 87 86 /* nouveau_dp.c */ 88 - bool nouveau_dp_detect(struct drm_encoder *); 89 - void nouveau_dp_dpms(struct drm_encoder *, int mode, u32 datarate, 90 - struct nouveau_object *); 87 + int nouveau_dp_detect(struct nouveau_encoder *); 91 88 92 89 struct nouveau_connector * 93 90 nouveau_encoder_connector_get(struct nouveau_encoder *encoder);
+2 -2
drivers/gpu/drm/nouveau/nouveau_fence.c
··· 166 166 } 167 167 168 168 static int 169 - nouveau_fence_wait_uevent_handler(void *data, int index) 169 + nouveau_fence_wait_uevent_handler(void *data, u32 type, int index) 170 170 { 171 171 struct nouveau_fence_priv *priv = data; 172 172 wake_up_all(&priv->waiting); ··· 183 183 struct nouveau_eventh *handler; 184 184 int ret = 0; 185 185 186 - ret = nouveau_event_new(pfifo->uevent, 0, 186 + ret = nouveau_event_new(pfifo->uevent, 1, 0, 187 187 nouveau_fence_wait_uevent_handler, 188 188 priv, &handler); 189 189 if (ret)
+58 -43
drivers/gpu/drm/nouveau/nv50_display.c
··· 26 26 27 27 #include <drm/drmP.h> 28 28 #include <drm/drm_crtc_helper.h> 29 + #include <drm/drm_dp_helper.h> 29 30 30 31 #include "nouveau_drm.h" 31 32 #include "nouveau_dma.h" ··· 1208 1207 nv50_crtc_disable(struct drm_crtc *crtc) 1209 1208 { 1210 1209 struct nv50_head *head = nv50_head(crtc); 1210 + evo_sync(crtc->dev); 1211 1211 if (head->image) 1212 1212 nouveau_bo_unpin(head->image); 1213 1213 nouveau_bo_ref(NULL, &head->image); ··· 1702 1700 } 1703 1701 1704 1702 static void 1705 - nv50_hdmi_disconnect(struct drm_encoder *encoder) 1703 + nv50_hdmi_disconnect(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc) 1706 1704 { 1707 1705 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1708 - struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); 1709 1706 struct nv50_disp *disp = nv50_disp(encoder->dev); 1710 1707 const u32 moff = (nv_crtc->index << 3) | nv_encoder->or; 1711 1708 ··· 1723 1722 struct drm_device *dev = encoder->dev; 1724 1723 struct nv50_disp *disp = nv50_disp(dev); 1725 1724 struct drm_encoder *partner; 1726 - int or = nv_encoder->or; 1725 + u32 mthd; 1727 1726 1728 1727 nv_encoder->last_dpms = mode; 1729 1728 ··· 1741 1740 } 1742 1741 } 1743 1742 1744 - nv_call(disp->core, NV50_DISP_SOR_PWR + or, (mode == DRM_MODE_DPMS_ON)); 1743 + mthd = (ffs(nv_encoder->dcb->sorconf.link) - 1) << 2; 1744 + mthd |= nv_encoder->or; 1745 + 1746 + if (nv_encoder->dcb->type == DCB_OUTPUT_DP) { 1747 + nv_call(disp->core, NV50_DISP_SOR_PWR | mthd, 1); 1748 + mthd |= NV94_DISP_SOR_DP_PWR; 1749 + } else { 1750 + mthd |= NV50_DISP_SOR_PWR; 1751 + } 1752 + 1753 + nv_call(disp->core, mthd, (mode == DRM_MODE_DPMS_ON)); 1745 1754 } 1746 1755 1747 1756 static bool ··· 1775 1764 } 1776 1765 1777 1766 static void 1767 + nv50_sor_ctrl(struct nouveau_encoder *nv_encoder, u32 mask, u32 data) 1768 + { 1769 + struct nv50_mast *mast = nv50_mast(nv_encoder->base.base.dev); 1770 + u32 temp = (nv_encoder->ctrl & ~mask) | (data & mask), *push; 1771 + if (temp != nv_encoder->ctrl && (push = evo_wait(mast, 2))) { 1772 + if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { 1773 + evo_mthd(push, 0x0600 + (nv_encoder->or * 0x40), 1); 1774 + evo_data(push, (nv_encoder->ctrl = temp)); 1775 + } else { 1776 + evo_mthd(push, 0x0200 + (nv_encoder->or * 0x20), 1); 1777 + evo_data(push, (nv_encoder->ctrl = temp)); 1778 + } 1779 + evo_kick(push, mast); 1780 + } 1781 + } 1782 + 1783 + static void 1778 1784 nv50_sor_disconnect(struct drm_encoder *encoder) 1779 1785 { 1780 1786 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 1781 - struct nv50_mast *mast = nv50_mast(encoder->dev); 1782 - const int or = nv_encoder->or; 1783 - u32 *push; 1784 - 1785 - if (nv_encoder->crtc) { 1786 - nv50_crtc_prepare(nv_encoder->crtc); 1787 - 1788 - push = evo_wait(mast, 4); 1789 - if (push) { 1790 - if (nv50_vers(mast) < NVD0_DISP_MAST_CLASS) { 1791 - evo_mthd(push, 0x0600 + (or * 0x40), 1); 1792 - evo_data(push, 0x00000000); 1793 - } else { 1794 - evo_mthd(push, 0x0200 + (or * 0x20), 1); 1795 - evo_data(push, 0x00000000); 1796 - } 1797 - evo_kick(push, mast); 1798 - } 1799 - 1800 - nv50_hdmi_disconnect(encoder); 1801 - } 1787 + struct nouveau_crtc *nv_crtc = nouveau_crtc(nv_encoder->crtc); 1802 1788 1803 1789 nv_encoder->last_dpms = DRM_MODE_DPMS_OFF; 1804 1790 nv_encoder->crtc = NULL; 1791 + 1792 + if (nv_crtc) { 1793 + nv50_crtc_prepare(&nv_crtc->base); 1794 + nv50_sor_ctrl(nv_encoder, 1 << nv_crtc->index, 0); 1795 + nv50_hdmi_disconnect(&nv_encoder->base.base, nv_crtc); 1796 + } 1805 1797 } 1806 1798 1807 1799 static void ··· 1824 1810 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 1825 1811 struct nouveau_connector *nv_connector; 1826 1812 struct nvbios *bios = &drm->vbios; 1827 - u32 *push, lvds = 0; 1813 + u32 lvds = 0, mask, ctrl; 1828 1814 u8 owner = 1 << nv_crtc->index; 1829 1815 u8 proto = 0xf; 1830 1816 u8 depth = 0x0; 1831 1817 1832 1818 nv_connector = nouveau_encoder_connector_get(nv_encoder); 1819 + nv_encoder->crtc = encoder->crtc; 1820 + 1833 1821 switch (nv_encoder->dcb->type) { 1834 1822 case DCB_OUTPUT_TMDS: 1835 1823 if (nv_encoder->dcb->sorconf.link & 1) { ··· 1843 1827 proto = 0x2; 1844 1828 } 1845 1829 1846 - nv50_hdmi_mode_set(encoder, mode); 1830 + nv50_hdmi_mode_set(&nv_encoder->base.base, mode); 1847 1831 break; 1848 1832 case DCB_OUTPUT_LVDS: 1849 1833 proto = 0x0; ··· 1899 1883 break; 1900 1884 } 1901 1885 1902 - nv50_sor_dpms(encoder, DRM_MODE_DPMS_ON); 1886 + nv50_sor_dpms(&nv_encoder->base.base, DRM_MODE_DPMS_ON); 1903 1887 1904 - push = evo_wait(nv50_mast(dev), 8); 1905 - if (push) { 1906 - if (nv50_vers(mast) < NVD0_DISP_CLASS) { 1907 - u32 ctrl = (depth << 16) | (proto << 8) | owner; 1908 - if (mode->flags & DRM_MODE_FLAG_NHSYNC) 1909 - ctrl |= 0x00001000; 1910 - if (mode->flags & DRM_MODE_FLAG_NVSYNC) 1911 - ctrl |= 0x00002000; 1912 - evo_mthd(push, 0x0600 + (nv_encoder->or * 0x040), 1); 1913 - evo_data(push, ctrl); 1914 - } else { 1888 + if (nv50_vers(mast) >= NVD0_DISP_CLASS) { 1889 + u32 *push = evo_wait(mast, 3); 1890 + if (push) { 1915 1891 u32 magic = 0x31ec6000 | (nv_crtc->index << 25); 1916 1892 u32 syncs = 0x00000001; 1917 1893 ··· 1918 1910 evo_mthd(push, 0x0404 + (nv_crtc->index * 0x300), 2); 1919 1911 evo_data(push, syncs | (depth << 6)); 1920 1912 evo_data(push, magic); 1921 - evo_mthd(push, 0x0200 + (nv_encoder->or * 0x020), 1); 1922 - evo_data(push, owner | (proto << 8)); 1913 + evo_kick(push, mast); 1923 1914 } 1924 1915 1925 - evo_kick(push, mast); 1916 + ctrl = proto << 8; 1917 + mask = 0x00000f00; 1918 + } else { 1919 + ctrl = (depth << 16) | (proto << 8); 1920 + if (mode->flags & DRM_MODE_FLAG_NHSYNC) 1921 + ctrl |= 0x00001000; 1922 + if (mode->flags & DRM_MODE_FLAG_NVSYNC) 1923 + ctrl |= 0x00002000; 1924 + mask = 0x000f3f00; 1926 1925 } 1927 1926 1928 - nv_encoder->crtc = encoder->crtc; 1927 + nv50_sor_ctrl(nv_encoder, mask | owner, ctrl | owner); 1929 1928 } 1930 1929 1931 1930 static void