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

drm/nouveau: introduce gpio engine

Signed-off-by: Ben Skeggs <bskeggs@redhat.com>

+100 -38
+1 -1
drivers/gpu/drm/nouveau/Makefile
··· 22 22 nv50_cursor.o nv50_display.o nv50_fbcon.o \ 23 23 nv04_dac.o nv04_dfp.o nv04_tv.o nv17_tv.o nv17_tv_modes.o \ 24 24 nv04_crtc.o nv04_display.o nv04_cursor.o nv04_fbcon.o \ 25 - nv17_gpio.o nv50_gpio.o \ 25 + nv10_gpio.o nv50_gpio.o \ 26 26 nv50_calc.o 27 27 28 28 nouveau-$(CONFIG_DRM_NOUVEAU_DEBUG) += nouveau_debugfs.o
+2 -1
drivers/gpu/drm/nouveau/nouveau_bios.c
··· 3136 3136 */ 3137 3137 3138 3138 struct drm_nouveau_private *dev_priv = bios->dev->dev_private; 3139 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 3139 3140 const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; 3140 3141 int i; 3141 3142 ··· 3157 3156 BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", 3158 3157 offset, gpio->tag, gpio->state_default); 3159 3158 if (bios->execute) 3160 - nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default); 3159 + pgpio->set(bios->dev, gpio->tag, gpio->state_default); 3161 3160 3162 3161 /* The NVIDIA binary driver doesn't appear to actually do 3163 3162 * any of this, my VBIOS does however.
+4 -2
drivers/gpu/drm/nouveau/nouveau_dp.c
··· 272 272 nouveau_dp_link_train(struct drm_encoder *encoder) 273 273 { 274 274 struct drm_device *dev = encoder->dev; 275 + struct drm_nouveau_private *dev_priv = dev->dev_private; 276 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 275 277 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 276 278 struct nouveau_connector *nv_connector; 277 279 struct bit_displayport_encoder_table *dpe; ··· 297 295 /* disable hotplug detect, this flips around on some panels during 298 296 * link training. 299 297 */ 300 - nv50_gpio_irq_enable(dev, nv_connector->dcb->gpio_tag, false); 298 + pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, false); 301 299 302 300 if (dpe->script0) { 303 301 NV_DEBUG_KMS(dev, "SOR-%d: running DP script 0\n", nv_encoder->or); ··· 438 436 } 439 437 440 438 /* re-enable hotplug detect */ 441 - nv50_gpio_irq_enable(dev, nv_connector->dcb->gpio_tag, true); 439 + pgpio->irq_enable(dev, nv_connector->dcb->gpio_tag, true); 442 440 443 441 return eq_done; 444 442 }
+15 -3
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 359 359 void (*destroy)(struct drm_device *); 360 360 }; 361 361 362 + struct nouveau_gpio_engine { 363 + int (*init)(struct drm_device *); 364 + void (*takedown)(struct drm_device *); 365 + 366 + int (*get)(struct drm_device *, enum dcb_gpio_tag); 367 + int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); 368 + 369 + void (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); 370 + }; 371 + 362 372 struct nouveau_engine { 363 373 struct nouveau_instmem_engine instmem; 364 374 struct nouveau_mc_engine mc; ··· 377 367 struct nouveau_pgraph_engine graph; 378 368 struct nouveau_fifo_engine fifo; 379 369 struct nouveau_display_engine display; 370 + struct nouveau_gpio_engine gpio; 380 371 }; 381 372 382 373 struct nouveau_pll_vals { ··· 1160 1149 extern int nouveau_gem_ioctl_info(struct drm_device *, void *, 1161 1150 struct drm_file *); 1162 1151 1163 - /* nv17_gpio.c */ 1164 - int nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1165 - int nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1152 + /* nv10_gpio.c */ 1153 + int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1154 + int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1166 1155 1167 1156 /* nv50_gpio.c */ 1157 + int nv50_gpio_init(struct drm_device *dev); 1168 1158 int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1169 1159 int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1170 1160 void nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on);
+40 -1
drivers/gpu/drm/nouveau/nouveau_state.c
··· 38 38 #include "nv50_display.h" 39 39 40 40 static void nouveau_stub_takedown(struct drm_device *dev) {} 41 + static int nouveau_stub_init(struct drm_device *dev) { return 0; } 41 42 42 43 static int nouveau_init_engine_ptrs(struct drm_device *dev) 43 44 { ··· 90 89 engine->display.create = nv04_display_create; 91 90 engine->display.init = nv04_display_init; 92 91 engine->display.destroy = nv04_display_destroy; 92 + engine->gpio.init = nouveau_stub_init; 93 + engine->gpio.takedown = nouveau_stub_takedown; 94 + engine->gpio.get = NULL; 95 + engine->gpio.set = NULL; 96 + engine->gpio.irq_enable = NULL; 93 97 break; 94 98 case 0x10: 95 99 engine->instmem.init = nv04_instmem_init; ··· 142 136 engine->display.create = nv04_display_create; 143 137 engine->display.init = nv04_display_init; 144 138 engine->display.destroy = nv04_display_destroy; 139 + engine->gpio.init = nouveau_stub_init; 140 + engine->gpio.takedown = nouveau_stub_takedown; 141 + engine->gpio.get = nv10_gpio_get; 142 + engine->gpio.set = nv10_gpio_set; 143 + engine->gpio.irq_enable = NULL; 145 144 break; 146 145 case 0x20: 147 146 engine->instmem.init = nv04_instmem_init; ··· 194 183 engine->display.create = nv04_display_create; 195 184 engine->display.init = nv04_display_init; 196 185 engine->display.destroy = nv04_display_destroy; 186 + engine->gpio.init = nouveau_stub_init; 187 + engine->gpio.takedown = nouveau_stub_takedown; 188 + engine->gpio.get = nv10_gpio_get; 189 + engine->gpio.set = nv10_gpio_set; 190 + engine->gpio.irq_enable = NULL; 197 191 break; 198 192 case 0x30: 199 193 engine->instmem.init = nv04_instmem_init; ··· 246 230 engine->display.create = nv04_display_create; 247 231 engine->display.init = nv04_display_init; 248 232 engine->display.destroy = nv04_display_destroy; 233 + engine->gpio.init = nouveau_stub_init; 234 + engine->gpio.takedown = nouveau_stub_takedown; 235 + engine->gpio.get = nv10_gpio_get; 236 + engine->gpio.set = nv10_gpio_set; 237 + engine->gpio.irq_enable = NULL; 249 238 break; 250 239 case 0x40: 251 240 case 0x60: ··· 299 278 engine->display.create = nv04_display_create; 300 279 engine->display.init = nv04_display_init; 301 280 engine->display.destroy = nv04_display_destroy; 281 + engine->gpio.init = nouveau_stub_init; 282 + engine->gpio.takedown = nouveau_stub_takedown; 283 + engine->gpio.get = nv10_gpio_get; 284 + engine->gpio.set = nv10_gpio_set; 285 + engine->gpio.irq_enable = NULL; 302 286 break; 303 287 case 0x50: 304 288 case 0x80: /* gotta love NVIDIA's consistency.. */ ··· 353 327 engine->display.create = nv50_display_create; 354 328 engine->display.init = nv50_display_init; 355 329 engine->display.destroy = nv50_display_destroy; 330 + engine->gpio.init = nv50_gpio_init; 331 + engine->gpio.takedown = nouveau_stub_takedown; 332 + engine->gpio.get = nv50_gpio_get; 333 + engine->gpio.set = nv50_gpio_set; 334 + engine->gpio.irq_enable = nv50_gpio_irq_enable; 356 335 break; 357 336 default: 358 337 NV_ERROR(dev, "NV%02x unsupported\n", dev_priv->chipset); ··· 516 485 if (ret) 517 486 goto out_gpuobj; 518 487 488 + /* PGPIO */ 489 + ret = engine->gpio.init(dev); 490 + if (ret) 491 + goto out_mc; 492 + 519 493 /* PTIMER */ 520 494 ret = engine->timer.init(dev); 521 495 if (ret) 522 - goto out_mc; 496 + goto out_gpio; 523 497 524 498 /* PFB */ 525 499 ret = engine->fb.init(dev); ··· 590 554 engine->fb.takedown(dev); 591 555 out_timer: 592 556 engine->timer.takedown(dev); 557 + out_gpio: 558 + engine->gpio.takedown(dev); 593 559 out_mc: 594 560 engine->mc.takedown(dev); 595 561 out_gpuobj: ··· 630 592 } 631 593 engine->fb.takedown(dev); 632 594 engine->timer.takedown(dev); 595 + engine->gpio.takedown(dev); 633 596 engine->mc.takedown(dev); 634 597 engine->display.late_takedown(dev); 635 598
+7 -6
drivers/gpu/drm/nouveau/nv04_dac.c
··· 220 220 { 221 221 struct drm_device *dev = encoder->dev; 222 222 struct drm_nouveau_private *dev_priv = dev->dev_private; 223 + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 223 224 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; 224 225 uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); 225 226 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, ··· 252 251 nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); 253 252 } 254 253 255 - saved_gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); 256 - saved_gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); 254 + saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); 255 + saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); 257 256 258 - nv17_gpio_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); 259 - nv17_gpio_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); 257 + gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); 258 + gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); 260 259 261 260 msleep(4); 262 261 ··· 304 303 nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); 305 304 nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); 306 305 307 - nv17_gpio_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); 308 - nv17_gpio_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); 306 + gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1); 307 + gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0); 309 308 310 309 return sample; 311 310 }
+2 -2
drivers/gpu/drm/nouveau/nv17_gpio.c drivers/gpu/drm/nouveau/nv10_gpio.c
··· 55 55 } 56 56 57 57 int 58 - nv17_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) 58 + nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) 59 59 { 60 60 struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); 61 61 uint32_t reg, shift, mask, value; ··· 72 72 } 73 73 74 74 int 75 - nv17_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) 75 + nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) 76 76 { 77 77 struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); 78 78 uint32_t reg, shift, mask, value;
+11 -8
drivers/gpu/drm/nouveau/nv17_tv.c
··· 37 37 { 38 38 struct drm_device *dev = encoder->dev; 39 39 struct drm_nouveau_private *dev_priv = dev->dev_private; 40 + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 40 41 uint32_t testval, regoffset = nv04_dac_output_offset(encoder); 41 42 uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, 42 43 fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; ··· 53 52 head = (dacclk & 0x100) >> 8; 54 53 55 54 /* Save the previous state. */ 56 - gpio1 = nv17_gpio_get(dev, DCB_GPIO_TVDAC1); 57 - gpio0 = nv17_gpio_get(dev, DCB_GPIO_TVDAC0); 55 + gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); 56 + gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); 58 57 fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); 59 58 fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); 60 59 fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); ··· 65 64 ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); 66 65 67 66 /* Prepare the DAC for load detection. */ 68 - nv17_gpio_set(dev, DCB_GPIO_TVDAC1, true); 69 - nv17_gpio_set(dev, DCB_GPIO_TVDAC0, true); 67 + gpio->set(dev, DCB_GPIO_TVDAC1, true); 68 + gpio->set(dev, DCB_GPIO_TVDAC0, true); 70 69 71 70 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); 72 71 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); ··· 111 110 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); 112 111 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); 113 112 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); 114 - nv17_gpio_set(dev, DCB_GPIO_TVDAC1, gpio1); 115 - nv17_gpio_set(dev, DCB_GPIO_TVDAC0, gpio0); 113 + gpio->set(dev, DCB_GPIO_TVDAC1, gpio1); 114 + gpio->set(dev, DCB_GPIO_TVDAC0, gpio0); 116 115 117 116 return sample; 118 117 } ··· 336 335 static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) 337 336 { 338 337 struct drm_device *dev = encoder->dev; 338 + struct drm_nouveau_private *dev_priv = dev->dev_private; 339 + struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 339 340 struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; 340 341 struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); 341 342 ··· 362 359 363 360 nv_load_ptv(dev, regs, 200); 364 361 365 - nv17_gpio_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); 366 - nv17_gpio_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); 362 + gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); 363 + gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); 367 364 368 365 nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); 369 366 }
+2 -1
drivers/gpu/drm/nouveau/nv50_display.c
··· 193 193 { 194 194 struct drm_nouveau_private *dev_priv = dev->dev_private; 195 195 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; 196 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 196 197 struct nouveau_channel *evo = dev_priv->evo; 197 198 struct drm_connector *connector; 198 199 uint32_t val, ram_amount; ··· 380 379 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 381 380 struct nouveau_connector *conn = nouveau_connector(connector); 382 381 383 - nv50_gpio_irq_enable(dev, conn->dcb->gpio_tag, true); 382 + pgpio->irq_enable(dev, conn->dcb->gpio_tag, true); 384 383 } 385 384 386 385 return 0;
+16
drivers/gpu/drm/nouveau/nv50_gpio.c
··· 93 93 nv_wr32(dev, reg + 4, mask); 94 94 nv_mask(dev, reg + 0, mask, on ? mask : 0); 95 95 } 96 + 97 + int 98 + nv50_gpio_init(struct drm_device *dev) 99 + { 100 + struct drm_nouveau_private *dev_priv = dev->dev_private; 101 + 102 + /* disable, and ack any pending gpio interrupts */ 103 + nv_wr32(dev, 0xe050, 0x00000000); 104 + nv_wr32(dev, 0xe054, 0xffffffff); 105 + if (dev_priv->chipset >= 0x90) { 106 + nv_wr32(dev, 0xe070, 0x00000000); 107 + nv_wr32(dev, 0xe074, 0xffffffff); 108 + } 109 + 110 + return 0; 111 + }
-13
drivers/gpu/drm/nouveau/nv50_mc.c
··· 31 31 int 32 32 nv50_mc_init(struct drm_device *dev) 33 33 { 34 - struct drm_nouveau_private *dev_priv = dev->dev_private; 35 - 36 34 nv_wr32(dev, NV03_PMC_ENABLE, 0xFFFFFFFF); 37 - 38 - /* disable, and ack any pending gpio interrupts 39 - * XXX doesn't technically belong here, but it'll do for the moment 40 - */ 41 - nv_wr32(dev, 0xe050, 0x00000000); 42 - nv_wr32(dev, 0xe054, 0xffffffff); 43 - if (dev_priv->chipset >= 0x90) { 44 - nv_wr32(dev, 0xe070, 0x00000000); 45 - nv_wr32(dev, 0xe074, 0xffffffff); 46 - } 47 - 48 35 return 0; 49 36 } 50 37