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

drm/nouveau/gpio: reimplement as nouveau_gpio.c, fixing a number of issues

- moves out of nouveau_bios.c and demagics the logical state definitions
- simplifies chipset-specific driver interface
- makes most of gpio irq handling common, will use for nv4x hpd later
- api extended to allow both direct gpio access, and access using the
logical function states
- api extended to allow for future use of gpio extender chips
- pre-nv50 was handled very badly, the main issue being that all GPIOs
were being treated as output-only.
- fixes nvd0 so gpio changes actually stick, magic reg needs bashing

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

+655 -648
+1 -1
drivers/gpu/drm/nouveau/Makefile
··· 11 11 nouveau_display.o nouveau_connector.o nouveau_fbcon.o \ 12 12 nouveau_hdmi.o nouveau_dp.o nouveau_ramht.o \ 13 13 nouveau_pm.o nouveau_volt.o nouveau_perf.o nouveau_temp.o \ 14 - nouveau_mm.o nouveau_vm.o nouveau_mxm.o \ 14 + nouveau_mm.o nouveau_vm.o nouveau_mxm.o nouveau_gpio.o \ 15 15 nv04_timer.o \ 16 16 nv04_mc.o nv40_mc.o nv50_mc.o \ 17 17 nv04_fb.o nv10_fb.o nv30_fb.o nv40_fb.o nv50_fb.o nvc0_fb.o \
+3 -203
drivers/gpu/drm/nouveau/nouveau_bios.c
··· 27 27 #include "nouveau_drv.h" 28 28 #include "nouveau_hw.h" 29 29 #include "nouveau_encoder.h" 30 + #include "nouveau_gpio.h" 30 31 31 32 #include <linux/io-mapping.h> 32 33 ··· 3125 3124 return 1; 3126 3125 } 3127 3126 3128 - static void 3129 - init_gpio_unknv50(struct nvbios *bios, struct dcb_gpio_entry *gpio) 3130 - { 3131 - const uint32_t nv50_gpio_ctl[2] = { 0xe100, 0xe28c }; 3132 - u32 r, s, v; 3133 - 3134 - /* Not a clue, needs de-magicing */ 3135 - r = nv50_gpio_ctl[gpio->line >> 4]; 3136 - s = (gpio->line & 0x0f); 3137 - v = bios_rd32(bios, r) & ~(0x00010001 << s); 3138 - switch ((gpio->entry & 0x06000000) >> 25) { 3139 - case 1: 3140 - v |= (0x00000001 << s); 3141 - break; 3142 - case 2: 3143 - v |= (0x00010000 << s); 3144 - break; 3145 - default: 3146 - break; 3147 - } 3148 - 3149 - bios_wr32(bios, r, v); 3150 - } 3151 - 3152 - static void 3153 - init_gpio_unknvd0(struct nvbios *bios, struct dcb_gpio_entry *gpio) 3154 - { 3155 - u32 v, i; 3156 - 3157 - v = bios_rd32(bios, 0x00d610 + (gpio->line * 4)); 3158 - v &= 0xffffff00; 3159 - v |= (gpio->entry & 0x00ff0000) >> 16; 3160 - bios_wr32(bios, 0x00d610 + (gpio->line * 4), v); 3161 - 3162 - i = (gpio->entry & 0x1f000000) >> 24; 3163 - if (i) { 3164 - v = bios_rd32(bios, 0x00d640 + ((i - 1) * 4)); 3165 - v &= 0xffffff00; 3166 - v |= gpio->line; 3167 - bios_wr32(bios, 0x00d640 + ((i - 1) * 4), v); 3168 - } 3169 - } 3170 - 3171 3127 static int 3172 3128 init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) 3173 3129 { ··· 3137 3179 * each GPIO according to various values listed in each entry 3138 3180 */ 3139 3181 3140 - struct drm_nouveau_private *dev_priv = bios->dev->dev_private; 3141 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 3142 - int i; 3143 - 3144 - if (dev_priv->card_type < NV_50) { 3145 - NV_ERROR(bios->dev, "INIT_GPIO on unsupported chipset\n"); 3146 - return 1; 3147 - } 3148 - 3149 - if (!iexec->execute) 3150 - return 1; 3151 - 3152 - for (i = 0; i < bios->dcb.gpio.entries; i++) { 3153 - struct dcb_gpio_entry *gpio = &bios->dcb.gpio.entry[i]; 3154 - 3155 - BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); 3156 - 3157 - BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", 3158 - offset, gpio->tag, gpio->state_default); 3159 - 3160 - if (!bios->execute) 3161 - continue; 3162 - 3163 - pgpio->set(bios->dev, gpio->tag, gpio->state_default); 3164 - if (dev_priv->card_type < NV_D0) 3165 - init_gpio_unknv50(bios, gpio); 3166 - else 3167 - init_gpio_unknvd0(bios, gpio); 3168 - } 3182 + if (iexec->execute && bios->execute) 3183 + nouveau_gpio_reset(bios->dev); 3169 3184 3170 3185 return 1; 3171 3186 } ··· 5574 5643 return 0; 5575 5644 } 5576 5645 5577 - static struct dcb_gpio_entry * 5578 - new_gpio_entry(struct nvbios *bios) 5579 - { 5580 - struct drm_device *dev = bios->dev; 5581 - struct dcb_gpio_table *gpio = &bios->dcb.gpio; 5582 - 5583 - if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) { 5584 - NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n"); 5585 - return NULL; 5586 - } 5587 - 5588 - return &gpio->entry[gpio->entries++]; 5589 - } 5590 - 5591 - struct dcb_gpio_entry * 5592 - nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag) 5593 - { 5594 - struct drm_nouveau_private *dev_priv = dev->dev_private; 5595 - struct nvbios *bios = &dev_priv->vbios; 5596 - int i; 5597 - 5598 - for (i = 0; i < bios->dcb.gpio.entries; i++) { 5599 - if (bios->dcb.gpio.entry[i].tag != tag) 5600 - continue; 5601 - 5602 - return &bios->dcb.gpio.entry[i]; 5603 - } 5604 - 5605 - return NULL; 5606 - } 5607 - 5608 - static void 5609 - parse_dcb_gpio_table(struct nvbios *bios) 5610 - { 5611 - struct drm_device *dev = bios->dev; 5612 - struct dcb_gpio_entry *e; 5613 - u8 headerlen, entries, recordlen; 5614 - u8 *dcb, *gpio = NULL, *entry; 5615 - int i; 5616 - 5617 - dcb = ROMPTR(dev, bios->data[0x36]); 5618 - if (dcb[0] >= 0x30) { 5619 - gpio = ROMPTR(dev, dcb[10]); 5620 - if (!gpio) 5621 - goto no_table; 5622 - 5623 - headerlen = gpio[1]; 5624 - entries = gpio[2]; 5625 - recordlen = gpio[3]; 5626 - } else 5627 - if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) { 5628 - gpio = ROMPTR(dev, dcb[-15]); 5629 - if (!gpio) 5630 - goto no_table; 5631 - 5632 - headerlen = 3; 5633 - entries = gpio[2]; 5634 - recordlen = gpio[1]; 5635 - } else 5636 - if (dcb[0] >= 0x22) { 5637 - /* No GPIO table present, parse the TVDAC GPIO data. */ 5638 - uint8_t *tvdac_gpio = &dcb[-5]; 5639 - 5640 - if (tvdac_gpio[0] & 1) { 5641 - e = new_gpio_entry(bios); 5642 - e->tag = DCB_GPIO_TVDAC0; 5643 - e->line = tvdac_gpio[1] >> 4; 5644 - e->state[0] = !!(tvdac_gpio[0] & 2); 5645 - e->state[1] = !e->state[0]; 5646 - } 5647 - 5648 - goto no_table; 5649 - } else { 5650 - NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]); 5651 - goto no_table; 5652 - } 5653 - 5654 - entry = gpio + headerlen; 5655 - for (i = 0; i < entries; i++, entry += recordlen) { 5656 - e = new_gpio_entry(bios); 5657 - if (!e) 5658 - break; 5659 - 5660 - if (gpio[0] < 0x40) { 5661 - e->entry = ROM16(entry[0]); 5662 - e->tag = (e->entry & 0x07e0) >> 5; 5663 - if (e->tag == 0x3f) { 5664 - bios->dcb.gpio.entries--; 5665 - continue; 5666 - } 5667 - 5668 - e->line = (e->entry & 0x001f); 5669 - e->state[0] = ((e->entry & 0xf800) >> 11) != 4; 5670 - e->state[1] = !e->state[0]; 5671 - } else { 5672 - e->entry = ROM32(entry[0]); 5673 - e->tag = (e->entry & 0x0000ff00) >> 8; 5674 - if (e->tag == 0xff) { 5675 - bios->dcb.gpio.entries--; 5676 - continue; 5677 - } 5678 - 5679 - e->line = (e->entry & 0x0000001f) >> 0; 5680 - if (gpio[0] == 0x40) { 5681 - e->state_default = (e->entry & 0x01000000) >> 24; 5682 - e->state[0] = (e->entry & 0x18000000) >> 27; 5683 - e->state[1] = (e->entry & 0x60000000) >> 29; 5684 - } else { 5685 - e->state_default = (e->entry & 0x00000080) >> 7; 5686 - e->state[0] = (entry[4] >> 4) & 3; 5687 - e->state[1] = (entry[4] >> 6) & 3; 5688 - } 5689 - } 5690 - } 5691 - 5692 - no_table: 5693 - /* Apple iMac G4 NV18 */ 5694 - if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { 5695 - e = new_gpio_entry(bios); 5696 - if (e) { 5697 - e->tag = DCB_GPIO_TVDAC0; 5698 - e->line = 4; 5699 - } 5700 - } 5701 - } 5702 - 5703 5646 void * 5704 5647 dcb_table(struct drm_device *dev) 5705 5648 { ··· 6171 6366 NV_TRACE(dev, "DCB version %d.%d\n", dcbt[0] >> 4, dcbt[0] & 0xf); 6172 6367 6173 6368 dcb->version = dcbt[0]; 6174 - if (dcb->version >= 0x30) 6175 - dcb->gpio_table_ptr = ROM16(dcbt[10]); 6176 - 6177 6369 dcb_outp_foreach(dev, NULL, parse_dcb_entry); 6178 6370 6179 6371 /* ··· 6195 6393 } 6196 6394 } 6197 6395 dcb_fake_connectors(bios); 6198 - 6199 - parse_dcb_gpio_table(bios); 6200 6396 return 0; 6201 6397 } 6202 6398
-17
drivers/gpu/drm/nouveau/nouveau_bios.h
··· 61 61 DCB_GPIO_UNUSED = 0xff 62 62 }; 63 63 64 - struct dcb_gpio_entry { 65 - enum dcb_gpio_tag tag; 66 - int line; 67 - uint32_t entry; 68 - uint8_t state_default; 69 - uint8_t state[2]; 70 - }; 71 - 72 - struct dcb_gpio_table { 73 - int entries; 74 - struct dcb_gpio_entry entry[DCB_MAX_NUM_GPIO_ENTRIES]; 75 - }; 76 - 77 64 enum dcb_connector_type { 78 65 DCB_CONNECTOR_VGA = 0x00, 79 66 DCB_CONNECTOR_TV_0 = 0x10, ··· 129 142 130 143 struct dcb_table { 131 144 uint8_t version; 132 - 133 145 int entries; 134 146 struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; 135 - 136 - uint16_t gpio_table_ptr; 137 - struct dcb_gpio_table gpio; 138 147 }; 139 148 140 149 enum nouveau_or {
+11 -13
drivers/gpu/drm/nouveau/nouveau_connector.c
··· 35 35 #include "nouveau_encoder.h" 36 36 #include "nouveau_crtc.h" 37 37 #include "nouveau_connector.h" 38 + #include "nouveau_gpio.h" 38 39 #include "nouveau_hw.h" 39 40 40 41 static void nouveau_connector_hotplug(void *, int); ··· 84 83 { 85 84 struct nouveau_connector *nv_connector = nouveau_connector(connector); 86 85 struct drm_nouveau_private *dev_priv; 87 - struct nouveau_gpio_engine *pgpio; 88 86 struct drm_device *dev; 89 87 90 88 if (!nv_connector) ··· 93 93 dev_priv = dev->dev_private; 94 94 NV_DEBUG_KMS(dev, "\n"); 95 95 96 - pgpio = &dev_priv->engine.gpio; 97 - if (pgpio->irq_unregister) { 98 - pgpio->irq_unregister(dev, nv_connector->hpd, 99 - nouveau_connector_hotplug, connector); 96 + if (nv_connector->hpd != DCB_GPIO_UNUSED) { 97 + nouveau_gpio_isr_del(dev, 0, nv_connector->hpd, 0xff, 98 + nouveau_connector_hotplug, connector); 100 99 } 101 100 102 101 kfree(nv_connector->edid); ··· 875 876 const struct drm_connector_funcs *funcs = &nouveau_connector_funcs; 876 877 struct drm_nouveau_private *dev_priv = dev->dev_private; 877 878 struct nouveau_display_engine *disp = &dev_priv->engine.display; 878 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 879 879 struct nouveau_connector *nv_connector = NULL; 880 880 struct drm_connector *connector; 881 881 int type, ret = 0; ··· 1048 1050 break; 1049 1051 } 1050 1052 1051 - if (nv_connector->hpd != DCB_GPIO_UNUSED && pgpio->irq_register) { 1052 - pgpio->irq_register(dev, nv_connector->hpd, 1053 - nouveau_connector_hotplug, connector); 1054 - 1055 - connector->polled = DRM_CONNECTOR_POLL_HPD; 1056 - } else { 1057 - connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1053 + connector->polled = DRM_CONNECTOR_POLL_CONNECT; 1054 + if (nv_connector->hpd != DCB_GPIO_UNUSED) { 1055 + ret = nouveau_gpio_isr_add(dev, 0, nv_connector->hpd, 0xff, 1056 + nouveau_connector_hotplug, 1057 + connector); 1058 + if (ret == 0) 1059 + connector->polled = DRM_CONNECTOR_POLL_HPD; 1058 1060 } 1059 1061 1060 1062 drm_sysfs_connector_add(connector);
+3 -4
drivers/gpu/drm/nouveau/nouveau_dp.c
··· 29 29 #include "nouveau_connector.h" 30 30 #include "nouveau_encoder.h" 31 31 #include "nouveau_crtc.h" 32 + #include "nouveau_gpio.h" 32 33 33 34 /****************************************************************************** 34 35 * aux channel util functions ··· 557 556 bool 558 557 nouveau_dp_link_train(struct drm_encoder *encoder, u32 datarate) 559 558 { 560 - struct drm_nouveau_private *dev_priv = encoder->dev->dev_private; 561 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 562 559 struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); 563 560 struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc); 564 561 struct nouveau_connector *nv_connector = ··· 586 587 * we take during link training (DP_SET_POWER is one), we need 587 588 * to ignore them for the moment to avoid races. 588 589 */ 589 - pgpio->irq_enable(dev, nv_connector->hpd, false); 590 + nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, false); 590 591 591 592 /* enable down-spreading, if possible */ 592 593 if (dp.table[1] >= 16) { ··· 635 636 nouveau_bios_run_init_table(dev, ROM16(dp.entry[8]), dp.dcb, dp.crtc); 636 637 637 638 /* re-enable hotplug detect */ 638 - pgpio->irq_enable(dev, nv_connector->hpd, true); 639 + nouveau_gpio_irq(dev, 0, nv_connector->hpd, 0xff, true); 639 640 return true; 640 641 } 641 642
+18 -27
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 408 408 }; 409 409 410 410 struct nouveau_gpio_engine { 411 - void *priv; 412 - 413 - int (*init)(struct drm_device *); 414 - void (*takedown)(struct drm_device *); 415 - 416 - int (*get)(struct drm_device *, enum dcb_gpio_tag); 417 - int (*set)(struct drm_device *, enum dcb_gpio_tag, int state); 418 - 419 - int (*irq_register)(struct drm_device *, enum dcb_gpio_tag, 420 - void (*)(void *, int), void *); 421 - void (*irq_unregister)(struct drm_device *, enum dcb_gpio_tag, 422 - void (*)(void *, int), void *); 423 - bool (*irq_enable)(struct drm_device *, enum dcb_gpio_tag, bool on); 411 + spinlock_t lock; 412 + struct list_head isr; 413 + int (*init)(struct drm_device *); 414 + void (*fini)(struct drm_device *); 415 + int (*drive)(struct drm_device *, int line, int dir, int out); 416 + int (*sense)(struct drm_device *, int line); 417 + void (*irq_enable)(struct drm_device *, int line, bool); 424 418 }; 425 419 426 420 struct nouveau_pm_voltage_level { ··· 1085 1091 extern void nouveau_bios_run_init_table(struct drm_device *, uint16_t table, 1086 1092 struct dcb_entry *, int crtc); 1087 1093 extern void nouveau_bios_init_exec(struct drm_device *, uint16_t table); 1088 - extern struct dcb_gpio_entry *nouveau_bios_gpio_entry(struct drm_device *, 1089 - enum dcb_gpio_tag); 1090 1094 extern struct dcb_connector_table_entry * 1091 1095 nouveau_bios_connector_entry(struct drm_device *, int index); 1092 1096 extern u32 get_pll_register(struct drm_device *, enum pll_types); ··· 1468 1476 uint32_t handle); 1469 1477 1470 1478 /* nv10_gpio.c */ 1471 - int nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1472 - int nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1479 + int nv10_gpio_init(struct drm_device *dev); 1480 + void nv10_gpio_fini(struct drm_device *dev); 1481 + int nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out); 1482 + int nv10_gpio_sense(struct drm_device *dev, int line); 1483 + void nv10_gpio_irq_enable(struct drm_device *, int line, bool on); 1473 1484 1474 1485 /* nv50_gpio.c */ 1475 1486 int nv50_gpio_init(struct drm_device *dev); 1476 1487 void nv50_gpio_fini(struct drm_device *dev); 1477 - int nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1478 - int nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1479 - int nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag); 1480 - int nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state); 1481 - int nv50_gpio_irq_register(struct drm_device *, enum dcb_gpio_tag, 1482 - void (*)(void *, int), void *); 1483 - void nv50_gpio_irq_unregister(struct drm_device *, enum dcb_gpio_tag, 1484 - void (*)(void *, int), void *); 1485 - bool nv50_gpio_irq_enable(struct drm_device *, enum dcb_gpio_tag, bool on); 1488 + int nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out); 1489 + int nv50_gpio_sense(struct drm_device *dev, int line); 1490 + void nv50_gpio_irq_enable(struct drm_device *, int line, bool on); 1491 + int nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out); 1492 + int nvd0_gpio_sense(struct drm_device *dev, int line); 1486 1493 1487 - /* nv50_calc. */ 1494 + /* nv50_calc.c */ 1488 1495 int nv50_calc_pll(struct drm_device *, struct pll_lims *, int clk, 1489 1496 int *N1, int *M1, int *N2, int *M2, int *P); 1490 1497 int nva3_calc_pll(struct drm_device *, struct pll_lims *,
+400
drivers/gpu/drm/nouveau/nouveau_gpio.c
··· 1 + /* 2 + * Copyright 2011 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + * 22 + * Authors: Ben Skeggs 23 + */ 24 + 25 + #include "drmP.h" 26 + #include "nouveau_drv.h" 27 + #include "nouveau_i2c.h" 28 + #include "nouveau_gpio.h" 29 + 30 + static u8 * 31 + dcb_gpio_table(struct drm_device *dev) 32 + { 33 + u8 *dcb = dcb_table(dev); 34 + if (dcb) { 35 + if (dcb[0] >= 0x30 && dcb[1] >= 0x0c) 36 + return ROMPTR(dev, dcb[0x0a]); 37 + if (dcb[0] >= 0x22 && dcb[-1] >= 0x13) 38 + return ROMPTR(dev, dcb[-15]); 39 + } 40 + return NULL; 41 + } 42 + 43 + static u8 * 44 + dcb_gpio_entry(struct drm_device *dev, int idx, int ent, u8 *version) 45 + { 46 + u8 *table = dcb_gpio_table(dev); 47 + if (table) { 48 + *version = table[0]; 49 + if (*version < 0x30 && ent < table[2]) 50 + return table + 3 + (ent * table[1]); 51 + else if (ent < table[2]) 52 + return table + table[1] + (ent * table[3]); 53 + } 54 + return NULL; 55 + } 56 + 57 + int 58 + nouveau_gpio_drive(struct drm_device *dev, int idx, int line, int dir, int out) 59 + { 60 + struct drm_nouveau_private *dev_priv = dev->dev_private; 61 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 62 + 63 + return pgpio->drive ? pgpio->drive(dev, line, dir, out) : -ENODEV; 64 + } 65 + 66 + int 67 + nouveau_gpio_sense(struct drm_device *dev, int idx, int line) 68 + { 69 + struct drm_nouveau_private *dev_priv = dev->dev_private; 70 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 71 + 72 + return pgpio->sense ? pgpio->sense(dev, line) : -ENODEV; 73 + } 74 + 75 + int 76 + nouveau_gpio_find(struct drm_device *dev, int idx, u8 func, u8 line, 77 + struct gpio_func *gpio) 78 + { 79 + u8 *table, *entry, version; 80 + int i = -1; 81 + 82 + if (line == 0xff && func == 0xff) 83 + return -EINVAL; 84 + 85 + while ((entry = dcb_gpio_entry(dev, idx, ++i, &version))) { 86 + if (version < 0x40) { 87 + u16 data = ROM16(entry[0]); 88 + *gpio = (struct gpio_func) { 89 + .line = (data & 0x001f) >> 0, 90 + .func = (data & 0x07e0) >> 5, 91 + .log[0] = (data & 0x1800) >> 11, 92 + .log[1] = (data & 0x6000) >> 13, 93 + }; 94 + } else 95 + if (version < 0x41) { 96 + *gpio = (struct gpio_func) { 97 + .line = entry[0] & 0x1f, 98 + .func = entry[1], 99 + .log[0] = (entry[3] & 0x18) >> 3, 100 + .log[1] = (entry[3] & 0x60) >> 5, 101 + }; 102 + } else { 103 + *gpio = (struct gpio_func) { 104 + .line = entry[0] & 0x3f, 105 + .func = entry[1], 106 + .log[0] = (entry[4] & 0x30) >> 4, 107 + .log[1] = (entry[4] & 0xc0) >> 6, 108 + }; 109 + } 110 + 111 + if ((line == 0xff || line == gpio->line) && 112 + (func == 0xff || func == gpio->func)) 113 + return 0; 114 + } 115 + 116 + /* DCB 2.2, fixed TVDAC GPIO data */ 117 + if ((table = dcb_table(dev)) && table[0] >= 0x22) { 118 + if (func == DCB_GPIO_TVDAC0) { 119 + *gpio = (struct gpio_func) { 120 + .func = DCB_GPIO_TVDAC0, 121 + .line = table[-4] >> 4, 122 + .log[0] = !!(table[-5] & 2), 123 + .log[1] = !(table[-5] & 2), 124 + }; 125 + return 0; 126 + } 127 + } 128 + 129 + /* Apple iMac G4 NV18 */ 130 + if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { 131 + if (func == DCB_GPIO_TVDAC0) { 132 + *gpio = (struct gpio_func) { 133 + .func = DCB_GPIO_TVDAC0, 134 + .line = 4, 135 + .log[0] = 0, 136 + .log[1] = 1, 137 + }; 138 + return 0; 139 + } 140 + } 141 + 142 + return -EINVAL; 143 + } 144 + 145 + int 146 + nouveau_gpio_set(struct drm_device *dev, int idx, u8 tag, u8 line, int state) 147 + { 148 + struct gpio_func gpio; 149 + int ret; 150 + 151 + ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); 152 + if (ret == 0) { 153 + int dir = !!(gpio.log[state] & 0x02); 154 + int out = !!(gpio.log[state] & 0x01); 155 + ret = nouveau_gpio_drive(dev, idx, gpio.line, dir, out); 156 + } 157 + 158 + return ret; 159 + } 160 + 161 + int 162 + nouveau_gpio_get(struct drm_device *dev, int idx, u8 tag, u8 line) 163 + { 164 + struct gpio_func gpio; 165 + int ret; 166 + 167 + ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); 168 + if (ret == 0) { 169 + ret = nouveau_gpio_sense(dev, idx, gpio.line); 170 + if (ret >= 0) 171 + ret = (ret == (gpio.log[1] & 1)); 172 + } 173 + 174 + return ret; 175 + } 176 + 177 + int 178 + nouveau_gpio_irq(struct drm_device *dev, int idx, u8 tag, u8 line, bool on) 179 + { 180 + struct drm_nouveau_private *dev_priv = dev->dev_private; 181 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 182 + struct gpio_func gpio; 183 + int ret; 184 + 185 + ret = nouveau_gpio_find(dev, idx, tag, line, &gpio); 186 + if (ret == 0) { 187 + if (idx == 0 && pgpio->irq_enable) 188 + pgpio->irq_enable(dev, gpio.line, on); 189 + else 190 + ret = -ENODEV; 191 + } 192 + 193 + return ret; 194 + } 195 + 196 + struct gpio_isr { 197 + struct drm_device *dev; 198 + struct list_head head; 199 + struct work_struct work; 200 + int idx; 201 + struct gpio_func func; 202 + void (*handler)(void *, int); 203 + void *data; 204 + bool inhibit; 205 + }; 206 + 207 + static void 208 + nouveau_gpio_isr_bh(struct work_struct *work) 209 + { 210 + struct gpio_isr *isr = container_of(work, struct gpio_isr, work); 211 + struct drm_device *dev = isr->dev; 212 + struct drm_nouveau_private *dev_priv = dev->dev_private; 213 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 214 + unsigned long flags; 215 + int state; 216 + 217 + state = nouveau_gpio_get(dev, isr->idx, isr->func.func, isr->func.line); 218 + if (state >= 0) 219 + isr->handler(isr->data, state); 220 + 221 + spin_lock_irqsave(&pgpio->lock, flags); 222 + isr->inhibit = false; 223 + spin_unlock_irqrestore(&pgpio->lock, flags); 224 + } 225 + 226 + void 227 + nouveau_gpio_isr(struct drm_device *dev, int idx, u32 line_mask) 228 + { 229 + struct drm_nouveau_private *dev_priv = dev->dev_private; 230 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 231 + struct gpio_isr *isr; 232 + 233 + if (idx != 0) 234 + return; 235 + 236 + spin_lock(&pgpio->lock); 237 + list_for_each_entry(isr, &pgpio->isr, head) { 238 + if (line_mask & (1 << isr->func.line)) { 239 + if (isr->inhibit) 240 + continue; 241 + isr->inhibit = true; 242 + schedule_work(&isr->work); 243 + } 244 + } 245 + spin_unlock(&pgpio->lock); 246 + } 247 + 248 + int 249 + nouveau_gpio_isr_add(struct drm_device *dev, int idx, u8 tag, u8 line, 250 + void (*handler)(void *, int), void *data) 251 + { 252 + struct drm_nouveau_private *dev_priv = dev->dev_private; 253 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 254 + struct gpio_isr *isr; 255 + unsigned long flags; 256 + int ret; 257 + 258 + isr = kzalloc(sizeof(*isr), GFP_KERNEL); 259 + if (!isr) 260 + return -ENOMEM; 261 + 262 + ret = nouveau_gpio_find(dev, idx, tag, line, &isr->func); 263 + if (ret) { 264 + kfree(isr); 265 + return ret; 266 + } 267 + 268 + INIT_WORK(&isr->work, nouveau_gpio_isr_bh); 269 + isr->dev = dev; 270 + isr->handler = handler; 271 + isr->data = data; 272 + isr->idx = idx; 273 + 274 + spin_lock_irqsave(&pgpio->lock, flags); 275 + list_add(&isr->head, &pgpio->isr); 276 + spin_unlock_irqrestore(&pgpio->lock, flags); 277 + return 0; 278 + } 279 + 280 + void 281 + nouveau_gpio_isr_del(struct drm_device *dev, int idx, u8 tag, u8 line, 282 + void (*handler)(void *, int), void *data) 283 + { 284 + struct drm_nouveau_private *dev_priv = dev->dev_private; 285 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 286 + struct gpio_isr *isr, *tmp; 287 + struct gpio_func func; 288 + unsigned long flags; 289 + LIST_HEAD(tofree); 290 + int ret; 291 + 292 + ret = nouveau_gpio_find(dev, idx, tag, line, &func); 293 + if (ret == 0) { 294 + spin_lock_irqsave(&pgpio->lock, flags); 295 + list_for_each_entry_safe(isr, tmp, &pgpio->isr, head) { 296 + if (memcmp(&isr->func, &func, sizeof(func)) || 297 + isr->idx != idx || 298 + isr->handler != handler || isr->data != data) 299 + continue; 300 + list_move(&isr->head, &tofree); 301 + } 302 + spin_unlock_irqrestore(&pgpio->lock, flags); 303 + 304 + list_for_each_entry_safe(isr, tmp, &tofree, head) { 305 + flush_work_sync(&isr->work); 306 + kfree(isr); 307 + } 308 + } 309 + } 310 + 311 + int 312 + nouveau_gpio_create(struct drm_device *dev) 313 + { 314 + struct drm_nouveau_private *dev_priv = dev->dev_private; 315 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 316 + 317 + INIT_LIST_HEAD(&pgpio->isr); 318 + spin_lock_init(&pgpio->lock); 319 + 320 + return nouveau_gpio_init(dev); 321 + } 322 + 323 + void 324 + nouveau_gpio_destroy(struct drm_device *dev) 325 + { 326 + struct drm_nouveau_private *dev_priv = dev->dev_private; 327 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 328 + 329 + nouveau_gpio_fini(dev); 330 + BUG_ON(!list_empty(&pgpio->isr)); 331 + } 332 + 333 + int 334 + nouveau_gpio_init(struct drm_device *dev) 335 + { 336 + struct drm_nouveau_private *dev_priv = dev->dev_private; 337 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 338 + int ret = 0; 339 + 340 + if (pgpio->init) 341 + ret = pgpio->init(dev); 342 + 343 + return ret; 344 + } 345 + 346 + void 347 + nouveau_gpio_fini(struct drm_device *dev) 348 + { 349 + struct drm_nouveau_private *dev_priv = dev->dev_private; 350 + struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 351 + 352 + if (pgpio->fini) 353 + pgpio->fini(dev); 354 + } 355 + 356 + void 357 + nouveau_gpio_reset(struct drm_device *dev) 358 + { 359 + struct drm_nouveau_private *dev_priv = dev->dev_private; 360 + u8 *entry, version; 361 + int ent = -1; 362 + 363 + while ((entry = dcb_gpio_entry(dev, 0, ++ent, &version))) { 364 + u8 func = 0xff, line, defs, unk0, unk1; 365 + if (version >= 0x41) { 366 + defs = !!(entry[0] & 0x80); 367 + line = entry[0] & 0x3f; 368 + func = entry[1]; 369 + unk0 = entry[2]; 370 + unk1 = entry[3] & 0x1f; 371 + } else 372 + if (version >= 0x40) { 373 + line = entry[0] & 0x1f; 374 + func = entry[1]; 375 + defs = !!(entry[3] & 0x01); 376 + unk0 = !!(entry[3] & 0x02); 377 + unk1 = !!(entry[3] & 0x04); 378 + } else { 379 + break; 380 + } 381 + 382 + if (func == 0xff) 383 + continue; 384 + 385 + nouveau_gpio_func_set(dev, func, defs); 386 + 387 + if (dev_priv->card_type >= NV_D0) { 388 + nv_mask(dev, 0x00d610 + (line * 4), 0xff, unk0); 389 + if (unk1--) 390 + nv_mask(dev, 0x00d640 + (unk1 * 4), 0xff, line); 391 + } else 392 + if (dev_priv->card_type >= NV_50) { 393 + static const u32 regs[] = { 0xe100, 0xe28c }; 394 + u32 val = (unk1 << 16) | unk0; 395 + u32 reg = regs[line >> 4]; line &= 0x0f; 396 + 397 + nv_mask(dev, reg, 0x00010001 << line, val << line); 398 + } 399 + } 400 + }
+71
drivers/gpu/drm/nouveau/nouveau_gpio.h
··· 1 + /* 2 + * Copyright 2011 Red Hat Inc. 3 + * 4 + * Permission is hereby granted, free of charge, to any person obtaining a 5 + * copy of this software and associated documentation files (the "Software"), 6 + * to deal in the Software without restriction, including without limitation 7 + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 + * and/or sell copies of the Software, and to permit persons to whom the 9 + * Software is furnished to do so, subject to the following conditions: 10 + * 11 + * The above copyright notice and this permission notice shall be included in 12 + * all copies or substantial portions of the Software. 13 + * 14 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 + * OTHER DEALINGS IN THE SOFTWARE. 21 + */ 22 + 23 + #ifndef __NOUVEAU_GPIO_H__ 24 + #define __NOUVEAU_GPIO_H__ 25 + 26 + struct gpio_func { 27 + u8 func; 28 + u8 line; 29 + u8 log[2]; 30 + }; 31 + 32 + /* nouveau_gpio.c */ 33 + int nouveau_gpio_create(struct drm_device *); 34 + void nouveau_gpio_destroy(struct drm_device *); 35 + int nouveau_gpio_init(struct drm_device *); 36 + void nouveau_gpio_fini(struct drm_device *); 37 + void nouveau_gpio_reset(struct drm_device *); 38 + int nouveau_gpio_drive(struct drm_device *, int idx, int line, 39 + int dir, int out); 40 + int nouveau_gpio_sense(struct drm_device *, int idx, int line); 41 + int nouveau_gpio_find(struct drm_device *, int idx, u8 tag, u8 line, 42 + struct gpio_func *); 43 + int nouveau_gpio_set(struct drm_device *, int idx, u8 tag, u8 line, int state); 44 + int nouveau_gpio_get(struct drm_device *, int idx, u8 tag, u8 line); 45 + int nouveau_gpio_irq(struct drm_device *, int idx, u8 tag, u8 line, bool on); 46 + void nouveau_gpio_isr(struct drm_device *, int idx, u32 mask); 47 + int nouveau_gpio_isr_add(struct drm_device *, int idx, u8 tag, u8 line, 48 + void (*)(void *, int state), void *data); 49 + void nouveau_gpio_isr_del(struct drm_device *, int idx, u8 tag, u8 line, 50 + void (*)(void *, int state), void *data); 51 + 52 + static inline bool 53 + nouveau_gpio_func_valid(struct drm_device *dev, u8 tag) 54 + { 55 + struct gpio_func func; 56 + return (nouveau_gpio_find(dev, 0, tag, 0xff, &func)) == 0; 57 + } 58 + 59 + static inline int 60 + nouveau_gpio_func_set(struct drm_device *dev, u8 tag, int state) 61 + { 62 + return nouveau_gpio_set(dev, 0, tag, 0xff, state); 63 + } 64 + 65 + static inline int 66 + nouveau_gpio_func_get(struct drm_device *dev, u8 tag) 67 + { 68 + return nouveau_gpio_get(dev, 0, tag, 0xff); 69 + } 70 + 71 + #endif
+21 -22
drivers/gpu/drm/nouveau/nouveau_pm.c
··· 26 26 27 27 #include "nouveau_drv.h" 28 28 #include "nouveau_pm.h" 29 + #include "nouveau_gpio.h" 29 30 30 31 #ifdef CONFIG_ACPI 31 32 #include <linux/acpi.h> ··· 39 38 nouveau_pwmfan_get(struct drm_device *dev) 40 39 { 41 40 struct drm_nouveau_private *dev_priv = dev->dev_private; 42 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 43 41 struct nouveau_pm_engine *pm = &dev_priv->engine.pm; 44 - struct dcb_gpio_entry *gpio = NULL; 42 + struct gpio_func gpio; 45 43 u32 divs, duty; 46 44 int ret; 47 45 48 46 if (!pm->pwm_get) 49 47 return -ENODEV; 50 48 51 - gpio = nouveau_bios_gpio_entry(dev, DCB_GPIO_PWM_FAN); 52 - if (gpio) { 53 - ret = pm->pwm_get(dev, gpio->line, &divs, &duty); 49 + ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); 50 + if (ret == 0) { 51 + ret = pm->pwm_get(dev, gpio.line, &divs, &duty); 54 52 if (ret == 0) { 55 53 divs = max(divs, duty); 56 - if (dev_priv->card_type <= NV_40 || 57 - (gpio->state[0] & 1)) 54 + if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) 58 55 duty = divs - duty; 59 56 return (duty * 100) / divs; 60 57 } 61 58 62 - return pgpio->get(dev, gpio->tag) * 100; 59 + return nouveau_gpio_func_get(dev, gpio.func) * 100; 63 60 } 64 61 65 62 return -ENODEV; ··· 68 69 { 69 70 struct drm_nouveau_private *dev_priv = dev->dev_private; 70 71 struct nouveau_pm_engine *pm = &dev_priv->engine.pm; 71 - struct dcb_gpio_entry *gpio; 72 + struct gpio_func gpio; 72 73 u32 divs, duty; 74 + int ret; 73 75 74 76 if (!pm->pwm_set) 75 77 return -ENODEV; 76 78 77 - gpio = nouveau_bios_gpio_entry(dev, DCB_GPIO_PWM_FAN); 78 - if (gpio) { 79 + ret = nouveau_gpio_find(dev, 0, DCB_GPIO_PWM_FAN, 0xff, &gpio); 80 + if (ret == 0) { 79 81 divs = pm->pwm_divisor; 80 82 if (pm->fan.pwm_freq) { 81 83 /*XXX: PNVIO clock more than likely... */ ··· 86 86 } 87 87 88 88 duty = ((divs * percent) + 99) / 100; 89 - if (dev_priv->card_type <= NV_40 || 90 - (gpio->state[0] & 1)) 89 + if (dev_priv->card_type <= NV_40 || (gpio.log[0] & 1)) 91 90 duty = divs - duty; 92 91 93 - return pm->pwm_set(dev, gpio->line, divs, duty); 92 + return pm->pwm_set(dev, gpio.line, divs, duty); 94 93 } 95 94 96 95 return -ENODEV; ··· 471 472 struct drm_device *dev = dev_get_drvdata(d); 472 473 struct drm_nouveau_private *dev_priv = dev->dev_private; 473 474 struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer; 474 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 475 - struct dcb_gpio_entry *gpio; 475 + struct gpio_func gpio; 476 476 u32 cycles, cur, prev; 477 477 u64 start; 478 + int ret; 478 479 479 - gpio = nouveau_bios_gpio_entry(dev, DCB_GPIO_FAN_SENSE); 480 - if (!gpio) 481 - return -ENODEV; 480 + ret = nouveau_gpio_find(dev, 0, DCB_GPIO_FAN_SENSE, 0xff, &gpio); 481 + if (ret) 482 + return ret; 482 483 483 484 /* Monitor the GPIO input 0x3b for 250ms. 484 485 * When the fan spins, it changes the value of GPIO FAN_SENSE. 485 486 * We get 4 changes (0 -> 1 -> 0 -> 1 -> [...]) per complete rotation. 486 487 */ 487 488 start = ptimer->read(dev); 488 - prev = pgpio->get(dev, DCB_GPIO_FAN_SENSE); 489 + prev = nouveau_gpio_sense(dev, 0, gpio.line); 489 490 cycles = 0; 490 491 do { 491 - cur = pgpio->get(dev, DCB_GPIO_FAN_SENSE); 492 + cur = nouveau_gpio_sense(dev, 0, gpio.line); 492 493 if (prev != cur) { 493 494 cycles++; 494 495 prev = cur; ··· 700 701 } 701 702 702 703 /* if the card can read the fan rpm */ 703 - if (nouveau_bios_gpio_entry(dev, DCB_GPIO_FAN_SENSE)) { 704 + if (nouveau_gpio_func_valid(dev, DCB_GPIO_FAN_SENSE)) { 704 705 ret = sysfs_create_group(&dev->pdev->dev.kobj, 705 706 &hwmon_fan_rpm_attrgroup); 706 707 if (ret)
+21 -43
drivers/gpu/drm/nouveau/nouveau_state.c
··· 36 36 #include "nouveau_drm.h" 37 37 #include "nouveau_fbcon.h" 38 38 #include "nouveau_ramht.h" 39 + #include "nouveau_gpio.h" 39 40 #include "nouveau_pm.h" 40 41 #include "nv50_display.h" 41 42 ··· 84 83 engine->display.destroy = nv04_display_destroy; 85 84 engine->display.init = nv04_display_init; 86 85 engine->display.fini = nv04_display_fini; 87 - engine->gpio.init = nouveau_stub_init; 88 - engine->gpio.takedown = nouveau_stub_takedown; 89 - engine->gpio.get = NULL; 90 - engine->gpio.set = NULL; 91 - engine->gpio.irq_enable = NULL; 92 86 engine->pm.clocks_get = nv04_pm_clocks_get; 93 87 engine->pm.clocks_pre = nv04_pm_clocks_pre; 94 88 engine->pm.clocks_set = nv04_pm_clocks_set; ··· 129 133 engine->display.destroy = nv04_display_destroy; 130 134 engine->display.init = nv04_display_init; 131 135 engine->display.fini = nv04_display_fini; 132 - engine->gpio.init = nouveau_stub_init; 133 - engine->gpio.takedown = nouveau_stub_takedown; 134 - engine->gpio.get = nv10_gpio_get; 135 - engine->gpio.set = nv10_gpio_set; 136 - engine->gpio.irq_enable = NULL; 136 + engine->gpio.drive = nv10_gpio_drive; 137 + engine->gpio.sense = nv10_gpio_sense; 137 138 engine->pm.clocks_get = nv04_pm_clocks_get; 138 139 engine->pm.clocks_pre = nv04_pm_clocks_pre; 139 140 engine->pm.clocks_set = nv04_pm_clocks_set; ··· 176 183 engine->display.destroy = nv04_display_destroy; 177 184 engine->display.init = nv04_display_init; 178 185 engine->display.fini = nv04_display_fini; 179 - engine->gpio.init = nouveau_stub_init; 180 - engine->gpio.takedown = nouveau_stub_takedown; 181 - engine->gpio.get = nv10_gpio_get; 182 - engine->gpio.set = nv10_gpio_set; 183 - engine->gpio.irq_enable = NULL; 186 + engine->gpio.drive = nv10_gpio_drive; 187 + engine->gpio.sense = nv10_gpio_sense; 184 188 engine->pm.clocks_get = nv04_pm_clocks_get; 185 189 engine->pm.clocks_pre = nv04_pm_clocks_pre; 186 190 engine->pm.clocks_set = nv04_pm_clocks_set; ··· 223 233 engine->display.destroy = nv04_display_destroy; 224 234 engine->display.init = nv04_display_init; 225 235 engine->display.fini = nv04_display_fini; 226 - engine->gpio.init = nouveau_stub_init; 227 - engine->gpio.takedown = nouveau_stub_takedown; 228 - engine->gpio.get = nv10_gpio_get; 229 - engine->gpio.set = nv10_gpio_set; 230 - engine->gpio.irq_enable = NULL; 236 + engine->gpio.drive = nv10_gpio_drive; 237 + engine->gpio.sense = nv10_gpio_sense; 231 238 engine->pm.clocks_get = nv04_pm_clocks_get; 232 239 engine->pm.clocks_pre = nv04_pm_clocks_pre; 233 240 engine->pm.clocks_set = nv04_pm_clocks_set; ··· 273 286 engine->display.destroy = nv04_display_destroy; 274 287 engine->display.init = nv04_display_init; 275 288 engine->display.fini = nv04_display_fini; 276 - engine->gpio.init = nouveau_stub_init; 277 - engine->gpio.takedown = nouveau_stub_takedown; 278 - engine->gpio.get = nv10_gpio_get; 279 - engine->gpio.set = nv10_gpio_set; 280 - engine->gpio.irq_enable = NULL; 289 + engine->gpio.drive = nv10_gpio_drive; 290 + engine->gpio.sense = nv10_gpio_sense; 281 291 engine->pm.clocks_get = nv40_pm_clocks_get; 282 292 engine->pm.clocks_pre = nv40_pm_clocks_pre; 283 293 engine->pm.clocks_set = nv40_pm_clocks_set; ··· 329 345 engine->display.init = nv50_display_init; 330 346 engine->display.fini = nv50_display_fini; 331 347 engine->gpio.init = nv50_gpio_init; 332 - engine->gpio.takedown = nv50_gpio_fini; 333 - engine->gpio.get = nv50_gpio_get; 334 - engine->gpio.set = nv50_gpio_set; 335 - engine->gpio.irq_register = nv50_gpio_irq_register; 336 - engine->gpio.irq_unregister = nv50_gpio_irq_unregister; 348 + engine->gpio.fini = nv50_gpio_fini; 349 + engine->gpio.drive = nv50_gpio_drive; 350 + engine->gpio.sense = nv50_gpio_sense; 337 351 engine->gpio.irq_enable = nv50_gpio_irq_enable; 338 352 switch (dev_priv->chipset) { 339 353 case 0x84: ··· 403 421 engine->display.init = nv50_display_init; 404 422 engine->display.fini = nv50_display_fini; 405 423 engine->gpio.init = nv50_gpio_init; 406 - engine->gpio.takedown = nouveau_stub_takedown; 407 - engine->gpio.get = nv50_gpio_get; 408 - engine->gpio.set = nv50_gpio_set; 409 - engine->gpio.irq_register = nv50_gpio_irq_register; 410 - engine->gpio.irq_unregister = nv50_gpio_irq_unregister; 424 + engine->gpio.fini = nv50_gpio_fini; 425 + engine->gpio.drive = nv50_gpio_drive; 426 + engine->gpio.sense = nv50_gpio_sense; 411 427 engine->gpio.irq_enable = nv50_gpio_irq_enable; 412 428 engine->vram.init = nvc0_vram_init; 413 429 engine->vram.takedown = nv50_vram_fini; ··· 454 474 engine->display.init = nvd0_display_init; 455 475 engine->display.fini = nvd0_display_fini; 456 476 engine->gpio.init = nv50_gpio_init; 457 - engine->gpio.takedown = nouveau_stub_takedown; 458 - engine->gpio.get = nvd0_gpio_get; 459 - engine->gpio.set = nvd0_gpio_set; 460 - engine->gpio.irq_register = nv50_gpio_irq_register; 461 - engine->gpio.irq_unregister = nv50_gpio_irq_unregister; 477 + engine->gpio.fini = nv50_gpio_fini; 478 + engine->gpio.drive = nvd0_gpio_drive; 479 + engine->gpio.sense = nvd0_gpio_sense; 462 480 engine->gpio.irq_enable = nv50_gpio_irq_enable; 463 481 engine->vram.init = nvc0_vram_init; 464 482 engine->vram.takedown = nv50_vram_fini; ··· 608 630 goto out_gart; 609 631 610 632 /* PGPIO */ 611 - ret = engine->gpio.init(dev); 633 + ret = nouveau_gpio_create(dev); 612 634 if (ret) 613 635 goto out_mc; 614 636 ··· 776 798 out_timer: 777 799 engine->timer.takedown(dev); 778 800 out_gpio: 779 - engine->gpio.takedown(dev); 801 + nouveau_gpio_destroy(dev); 780 802 out_mc: 781 803 engine->mc.takedown(dev); 782 804 out_gart: ··· 829 851 } 830 852 engine->fb.takedown(dev); 831 853 engine->timer.takedown(dev); 832 - engine->gpio.takedown(dev); 854 + nouveau_gpio_destroy(dev); 833 855 engine->mc.takedown(dev); 834 856 engine->display.late_takedown(dev); 835 857
+4 -5
drivers/gpu/drm/nouveau/nouveau_volt.c
··· 26 26 27 27 #include "nouveau_drv.h" 28 28 #include "nouveau_pm.h" 29 + #include "nouveau_gpio.h" 29 30 30 31 static const enum dcb_gpio_tag vidtag[] = { 0x04, 0x05, 0x06, 0x1a, 0x73 }; 31 32 static int nr_vidtag = sizeof(vidtag) / sizeof(vidtag[0]); ··· 35 34 nouveau_voltage_gpio_get(struct drm_device *dev) 36 35 { 37 36 struct drm_nouveau_private *dev_priv = dev->dev_private; 38 - struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 39 37 struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; 40 38 u8 vid = 0; 41 39 int i; ··· 43 43 if (!(volt->vid_mask & (1 << i))) 44 44 continue; 45 45 46 - vid |= gpio->get(dev, vidtag[i]) << i; 46 + vid |= nouveau_gpio_func_get(dev, vidtag[i]) << i; 47 47 } 48 48 49 49 return nouveau_volt_lvl_lookup(dev, vid); ··· 53 53 nouveau_voltage_gpio_set(struct drm_device *dev, int voltage) 54 54 { 55 55 struct drm_nouveau_private *dev_priv = dev->dev_private; 56 - struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 57 56 struct nouveau_pm_voltage *volt = &dev_priv->engine.pm.voltage; 58 57 int vid, i; 59 58 ··· 64 65 if (!(volt->vid_mask & (1 << i))) 65 66 continue; 66 67 67 - gpio->set(dev, vidtag[i], !!(vid & (1 << i))); 68 + nouveau_gpio_func_set(dev, vidtag[i], !!(vid & (1 << i))); 68 69 } 69 70 70 71 return 0; ··· 193 194 return; 194 195 } 195 196 196 - if (!nouveau_bios_gpio_entry(dev, vidtag[i])) { 197 + if (!nouveau_gpio_func_valid(dev, vidtag[i])) { 197 198 NV_DEBUG(dev, "vid bit %d has no gpio tag\n", i); 198 199 return; 199 200 }
+7 -7
drivers/gpu/drm/nouveau/nv04_dac.c
··· 32 32 #include "nouveau_connector.h" 33 33 #include "nouveau_crtc.h" 34 34 #include "nouveau_hw.h" 35 + #include "nouveau_gpio.h" 35 36 #include "nvreg.h" 36 37 37 38 int nv04_dac_output_offset(struct drm_encoder *encoder) ··· 221 220 { 222 221 struct drm_device *dev = encoder->dev; 223 222 struct drm_nouveau_private *dev_priv = dev->dev_private; 224 - struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 225 223 struct dcb_entry *dcb = nouveau_encoder(encoder)->dcb; 226 224 uint32_t sample, testval, regoffset = nv04_dac_output_offset(encoder); 227 225 uint32_t saved_powerctrl_2 = 0, saved_powerctrl_4 = 0, saved_routput, ··· 252 252 nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4 & 0xffffffcf); 253 253 } 254 254 255 - saved_gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); 256 - saved_gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); 255 + saved_gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); 256 + saved_gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); 257 257 258 - gpio->set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); 259 - gpio->set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); 258 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, dcb->type == OUTPUT_TV); 259 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, dcb->type == OUTPUT_TV); 260 260 261 261 msleep(4); 262 262 ··· 306 306 nvWriteMC(dev, NV_PBUS_POWERCTRL_4, saved_powerctrl_4); 307 307 nvWriteMC(dev, NV_PBUS_POWERCTRL_2, saved_powerctrl_2); 308 308 309 - gpio->set(dev, DCB_GPIO_TVDAC1, saved_gpio1); 310 - gpio->set(dev, DCB_GPIO_TVDAC0, saved_gpio0); 309 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, saved_gpio1); 310 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, saved_gpio0); 311 311 312 312 return sample; 313 313 }
+41 -51
drivers/gpu/drm/nouveau/nv10_gpio.c
··· 28 28 #include "nouveau_drv.h" 29 29 #include "nouveau_hw.h" 30 30 31 - static bool 32 - get_gpio_location(struct dcb_gpio_entry *ent, uint32_t *reg, uint32_t *shift, 33 - uint32_t *mask) 31 + int 32 + nv10_gpio_sense(struct drm_device *dev, int line) 34 33 { 35 - if (ent->line < 2) { 36 - *reg = NV_PCRTC_GPIO; 37 - *shift = ent->line * 16; 38 - *mask = 0x11; 39 - 40 - } else if (ent->line < 10) { 41 - *reg = NV_PCRTC_GPIO_EXT; 42 - *shift = (ent->line - 2) * 4; 43 - *mask = 0x3; 44 - 45 - } else if (ent->line < 14) { 46 - *reg = NV_PCRTC_850; 47 - *shift = (ent->line - 10) * 4; 48 - *mask = 0x3; 49 - 50 - } else { 51 - return false; 34 + if (line < 2) { 35 + line = line * 16; 36 + line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO) >> line; 37 + return !!(line & 0x0100); 38 + } else 39 + if (line < 10) { 40 + line = (line - 2) * 4; 41 + line = NVReadCRTC(dev, 0, NV_PCRTC_GPIO_EXT) >> line; 42 + return !!(line & 0x04); 43 + } else 44 + if (line < 14) { 45 + line = (line - 10) * 4; 46 + line = NVReadCRTC(dev, 0, NV_PCRTC_850) >> line; 47 + return !!(line & 0x04); 52 48 } 53 49 54 - return true; 50 + return -EINVAL; 55 51 } 56 52 57 53 int 58 - nv10_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) 54 + nv10_gpio_drive(struct drm_device *dev, int line, int dir, int out) 59 55 { 60 - struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); 61 - uint32_t reg, shift, mask, value; 56 + u32 reg, mask, data; 62 57 63 - if (!ent) 64 - return -ENODEV; 58 + if (line < 2) { 59 + line = line * 16; 60 + reg = NV_PCRTC_GPIO; 61 + mask = 0x00000011; 62 + data = (dir << 4) | out; 63 + } else 64 + if (line < 10) { 65 + line = (line - 2) * 4; 66 + reg = NV_PCRTC_GPIO_EXT; 67 + mask = 0x00000003 << ((line - 2) * 4); 68 + data = (dir << 1) | out; 69 + } else 70 + if (line < 14) { 71 + line = (line - 10) * 4; 72 + reg = NV_PCRTC_850; 73 + mask = 0x00000003; 74 + data = (dir << 1) | out; 75 + } else { 76 + return -EINVAL; 77 + } 65 78 66 - if (!get_gpio_location(ent, &reg, &shift, &mask)) 67 - return -ENODEV; 68 - 69 - value = NVReadCRTC(dev, 0, reg) >> shift; 70 - 71 - return (value & 1) == ent->state[1]; 72 - } 73 - 74 - int 75 - nv10_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) 76 - { 77 - struct dcb_gpio_entry *ent = nouveau_bios_gpio_entry(dev, tag); 78 - uint32_t reg, shift, mask, value; 79 - 80 - if (!ent) 81 - return -ENODEV; 82 - 83 - if (!get_gpio_location(ent, &reg, &shift, &mask)) 84 - return -ENODEV; 85 - 86 - value = ent->state[state & 1] << shift; 87 - mask = ~(mask << shift); 88 - 89 - NVWriteCRTC(dev, 0, reg, value | (NVReadCRTC(dev, 0, reg) & mask)); 90 - 79 + mask = NVReadCRTC(dev, 0, reg) & ~(mask << line); 80 + NVWriteCRTC(dev, 0, reg, mask | (data << line)); 91 81 return 0; 92 82 }
+9 -11
drivers/gpu/drm/nouveau/nv17_tv.c
··· 30 30 #include "nouveau_encoder.h" 31 31 #include "nouveau_connector.h" 32 32 #include "nouveau_crtc.h" 33 + #include "nouveau_gpio.h" 33 34 #include "nouveau_hw.h" 34 35 #include "nv17_tv.h" 35 36 ··· 38 37 { 39 38 struct drm_device *dev = encoder->dev; 40 39 struct drm_nouveau_private *dev_priv = dev->dev_private; 41 - struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 42 40 uint32_t testval, regoffset = nv04_dac_output_offset(encoder); 43 41 uint32_t gpio0, gpio1, fp_htotal, fp_hsync_start, fp_hsync_end, 44 42 fp_control, test_ctrl, dacclk, ctv_14, ctv_1c, ctv_6c; ··· 53 53 head = (dacclk & 0x100) >> 8; 54 54 55 55 /* Save the previous state. */ 56 - gpio1 = gpio->get(dev, DCB_GPIO_TVDAC1); 57 - gpio0 = gpio->get(dev, DCB_GPIO_TVDAC0); 56 + gpio1 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC1); 57 + gpio0 = nouveau_gpio_func_get(dev, DCB_GPIO_TVDAC0); 58 58 fp_htotal = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL); 59 59 fp_hsync_start = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START); 60 60 fp_hsync_end = NVReadRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END); ··· 65 65 ctv_6c = NVReadRAMDAC(dev, head, 0x680c6c); 66 66 67 67 /* Prepare the DAC for load detection. */ 68 - gpio->set(dev, DCB_GPIO_TVDAC1, true); 69 - gpio->set(dev, DCB_GPIO_TVDAC0, true); 68 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, true); 69 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, true); 70 70 71 71 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, 1343); 72 72 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, 1047); ··· 111 111 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_END, fp_hsync_end); 112 112 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HSYNC_START, fp_hsync_start); 113 113 NVWriteRAMDAC(dev, head, NV_PRAMDAC_FP_HTOTAL, fp_htotal); 114 - gpio->set(dev, DCB_GPIO_TVDAC1, gpio1); 115 - gpio->set(dev, DCB_GPIO_TVDAC0, gpio0); 114 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, gpio1); 115 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, gpio0); 116 116 117 117 return sample; 118 118 } ··· 357 357 static void nv17_tv_dpms(struct drm_encoder *encoder, int mode) 358 358 { 359 359 struct drm_device *dev = encoder->dev; 360 - struct drm_nouveau_private *dev_priv = dev->dev_private; 361 - struct nouveau_gpio_engine *gpio = &dev_priv->engine.gpio; 362 360 struct nv17_tv_state *regs = &to_tv_enc(encoder)->state; 363 361 struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder); 364 362 ··· 381 383 382 384 nv_load_ptv(dev, regs, 200); 383 385 384 - gpio->set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); 385 - gpio->set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); 386 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC1, mode == DRM_MODE_DPMS_ON); 387 + nouveau_gpio_func_set(dev, DCB_GPIO_TVDAC0, mode == DRM_MODE_DPMS_ON); 386 388 387 389 nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); 388 390 }
+2 -7
drivers/gpu/drm/nouveau/nv50_display.c
··· 32 32 #include "nouveau_fb.h" 33 33 #include "nouveau_fbcon.h" 34 34 #include "nouveau_ramht.h" 35 + #include "nouveau_gpio.h" 35 36 #include "drm_crtc_helper.h" 36 37 37 38 static void nv50_display_isr(struct drm_device *); ··· 141 140 int 142 141 nv50_display_init(struct drm_device *dev) 143 142 { 144 - struct drm_nouveau_private *dev_priv = dev->dev_private; 145 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 146 143 struct drm_connector *connector; 147 144 struct nouveau_channel *evo; 148 145 int ret, i; ··· 239 240 /* enable hotplug interrupts */ 240 241 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 241 242 struct nouveau_connector *conn = nouveau_connector(connector); 242 - 243 - if (conn->hpd == DCB_GPIO_UNUSED) 244 - continue; 245 - 246 - pgpio->irq_enable(dev, conn->hpd, true); 243 + nouveau_gpio_irq(dev, 0, conn->hpd, 0xff, true); 247 244 } 248 245 249 246 ret = nv50_evo_init(dev);
+43 -237
drivers/gpu/drm/nouveau/nv50_gpio.c
··· 25 25 #include "drmP.h" 26 26 #include "nouveau_drv.h" 27 27 #include "nouveau_hw.h" 28 + #include "nouveau_gpio.h" 28 29 29 30 #include "nv50_display.h" 30 31 31 - static void nv50_gpio_isr(struct drm_device *dev); 32 - static void nv50_gpio_isr_bh(struct work_struct *work); 33 - 34 - struct nv50_gpio_priv { 35 - struct list_head handlers; 36 - spinlock_t lock; 37 - }; 38 - 39 - struct nv50_gpio_handler { 40 - struct drm_device *dev; 41 - struct list_head head; 42 - struct work_struct work; 43 - bool inhibit; 44 - 45 - struct dcb_gpio_entry *gpio; 46 - 47 - void (*handler)(void *data, int state); 48 - void *data; 49 - }; 50 - 51 32 static int 52 - nv50_gpio_location(struct dcb_gpio_entry *gpio, uint32_t *reg, uint32_t *shift) 33 + nv50_gpio_location(int line, u32 *reg, u32 *shift) 53 34 { 54 35 const uint32_t nv50_gpio_reg[4] = { 0xe104, 0xe108, 0xe280, 0xe284 }; 55 36 56 - if (gpio->line >= 32) 37 + if (line >= 32) 57 38 return -EINVAL; 58 39 59 - *reg = nv50_gpio_reg[gpio->line >> 3]; 60 - *shift = (gpio->line & 7) << 2; 40 + *reg = nv50_gpio_reg[line >> 3]; 41 + *shift = (line & 7) << 2; 61 42 return 0; 62 43 } 63 44 64 45 int 65 - nv50_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) 46 + nv50_gpio_drive(struct drm_device *dev, int line, int dir, int out) 66 47 { 67 - struct dcb_gpio_entry *gpio; 68 - uint32_t r, s, v; 48 + u32 reg, shift; 69 49 70 - gpio = nouveau_bios_gpio_entry(dev, tag); 71 - if (!gpio) 72 - return -ENOENT; 73 - 74 - if (nv50_gpio_location(gpio, &r, &s)) 50 + if (nv50_gpio_location(line, &reg, &shift)) 75 51 return -EINVAL; 76 52 77 - v = nv_rd32(dev, r) >> (s + 2); 78 - return ((v & 1) == (gpio->state[1] & 1)); 53 + nv_mask(dev, reg, 7 << shift, (((dir ^ 1) << 1) | out) << shift); 54 + return 0; 79 55 } 80 56 81 57 int 82 - nv50_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) 58 + nv50_gpio_sense(struct drm_device *dev, int line) 83 59 { 84 - struct dcb_gpio_entry *gpio; 85 - uint32_t r, s, v; 60 + u32 reg, shift; 86 61 87 - gpio = nouveau_bios_gpio_entry(dev, tag); 88 - if (!gpio) 89 - return -ENOENT; 90 - 91 - if (nv50_gpio_location(gpio, &r, &s)) 62 + if (nv50_gpio_location(line, &reg, &shift)) 92 63 return -EINVAL; 93 64 94 - v = nv_rd32(dev, r) & ~(0x3 << s); 95 - v |= (gpio->state[state] ^ 2) << s; 96 - nv_wr32(dev, r, v); 97 - return 0; 98 - } 99 - 100 - int 101 - nvd0_gpio_get(struct drm_device *dev, enum dcb_gpio_tag tag) 102 - { 103 - struct dcb_gpio_entry *gpio; 104 - u32 v; 105 - 106 - gpio = nouveau_bios_gpio_entry(dev, tag); 107 - if (!gpio) 108 - return -ENOENT; 109 - 110 - v = nv_rd32(dev, 0x00d610 + (gpio->line * 4)); 111 - v &= 0x00004000; 112 - return (!!v == (gpio->state[1] & 1)); 113 - } 114 - 115 - int 116 - nvd0_gpio_set(struct drm_device *dev, enum dcb_gpio_tag tag, int state) 117 - { 118 - struct dcb_gpio_entry *gpio; 119 - u32 v; 120 - 121 - gpio = nouveau_bios_gpio_entry(dev, tag); 122 - if (!gpio) 123 - return -ENOENT; 124 - 125 - v = gpio->state[state] ^ 2; 126 - 127 - nv_mask(dev, 0x00d610 + (gpio->line * 4), 0x00003000, v << 12); 128 - return 0; 129 - } 130 - 131 - int 132 - nv50_gpio_irq_register(struct drm_device *dev, enum dcb_gpio_tag tag, 133 - void (*handler)(void *, int), void *data) 134 - { 135 - struct drm_nouveau_private *dev_priv = dev->dev_private; 136 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 137 - struct nv50_gpio_priv *priv = pgpio->priv; 138 - struct nv50_gpio_handler *gpioh; 139 - struct dcb_gpio_entry *gpio; 140 - unsigned long flags; 141 - 142 - gpio = nouveau_bios_gpio_entry(dev, tag); 143 - if (!gpio) 144 - return -ENOENT; 145 - 146 - gpioh = kzalloc(sizeof(*gpioh), GFP_KERNEL); 147 - if (!gpioh) 148 - return -ENOMEM; 149 - 150 - INIT_WORK(&gpioh->work, nv50_gpio_isr_bh); 151 - gpioh->dev = dev; 152 - gpioh->gpio = gpio; 153 - gpioh->handler = handler; 154 - gpioh->data = data; 155 - 156 - spin_lock_irqsave(&priv->lock, flags); 157 - list_add(&gpioh->head, &priv->handlers); 158 - spin_unlock_irqrestore(&priv->lock, flags); 159 - return 0; 65 + return !!(nv_rd32(dev, reg) & (4 << shift)); 160 66 } 161 67 162 68 void 163 - nv50_gpio_irq_unregister(struct drm_device *dev, enum dcb_gpio_tag tag, 164 - void (*handler)(void *, int), void *data) 69 + nv50_gpio_irq_enable(struct drm_device *dev, int line, bool on) 165 70 { 166 - struct drm_nouveau_private *dev_priv = dev->dev_private; 167 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 168 - struct nv50_gpio_priv *priv = pgpio->priv; 169 - struct nv50_gpio_handler *gpioh, *tmp; 170 - struct dcb_gpio_entry *gpio; 171 - LIST_HEAD(tofree); 172 - unsigned long flags; 173 - 174 - gpio = nouveau_bios_gpio_entry(dev, tag); 175 - if (!gpio) 176 - return; 177 - 178 - spin_lock_irqsave(&priv->lock, flags); 179 - list_for_each_entry_safe(gpioh, tmp, &priv->handlers, head) { 180 - if (gpioh->gpio != gpio || 181 - gpioh->handler != handler || 182 - gpioh->data != data) 183 - continue; 184 - list_move(&gpioh->head, &tofree); 185 - } 186 - spin_unlock_irqrestore(&priv->lock, flags); 187 - 188 - list_for_each_entry_safe(gpioh, tmp, &tofree, head) { 189 - flush_work_sync(&gpioh->work); 190 - kfree(gpioh); 191 - } 192 - } 193 - 194 - bool 195 - nv50_gpio_irq_enable(struct drm_device *dev, enum dcb_gpio_tag tag, bool on) 196 - { 197 - struct dcb_gpio_entry *gpio; 198 - u32 reg, mask; 199 - 200 - gpio = nouveau_bios_gpio_entry(dev, tag); 201 - if (!gpio) 202 - return false; 203 - 204 - reg = gpio->line < 16 ? 0xe050 : 0xe070; 205 - mask = 0x00010001 << (gpio->line & 0xf); 71 + u32 reg = line < 16 ? 0xe050 : 0xe070; 72 + u32 mask = 0x00010001 << (line & 0xf); 206 73 207 74 nv_wr32(dev, reg + 4, mask); 208 - reg = nv_mask(dev, reg + 0, mask, on ? mask : 0); 209 - return (reg & mask) == mask; 75 + nv_mask(dev, reg + 0, mask, on ? mask : 0); 210 76 } 211 77 212 - static int 213 - nv50_gpio_create(struct drm_device *dev) 78 + int 79 + nvd0_gpio_drive(struct drm_device *dev, int line, int dir, int out) 214 80 { 215 - struct drm_nouveau_private *dev_priv = dev->dev_private; 216 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 217 - struct nv50_gpio_priv *priv; 218 - 219 - priv = kzalloc(sizeof(*priv), GFP_KERNEL); 220 - if (!priv) 221 - return -ENOMEM; 222 - 223 - INIT_LIST_HEAD(&priv->handlers); 224 - spin_lock_init(&priv->lock); 225 - pgpio->priv = priv; 81 + u32 data = ((dir ^ 1) << 13) | (out << 12); 82 + nv_mask(dev, 0x00d610 + (line * 4), 0x00003000, data); 83 + nv_mask(dev, 0x00d604, 0x00000001, 0x00000001); /* update? */ 226 84 return 0; 227 85 } 228 86 87 + int 88 + nvd0_gpio_sense(struct drm_device *dev, int line) 89 + { 90 + return !!(nv_rd32(dev, 0x00d610 + (line * 4)) & 0x00004000); 91 + } 92 + 229 93 static void 230 - nv50_gpio_destroy(struct drm_device *dev) 94 + nv50_gpio_isr(struct drm_device *dev) 231 95 { 232 96 struct drm_nouveau_private *dev_priv = dev->dev_private; 233 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 97 + u32 intr0, intr1 = 0; 98 + u32 hi, lo; 234 99 235 - kfree(pgpio->priv); 236 - pgpio->priv = NULL; 100 + intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); 101 + if (dev_priv->chipset >= 0x90) 102 + intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); 103 + 104 + hi = (intr0 & 0x0000ffff) | (intr1 << 16); 105 + lo = (intr0 >> 16) | (intr1 & 0xffff0000); 106 + nouveau_gpio_isr(dev, 0, hi | lo); 107 + 108 + nv_wr32(dev, 0xe054, intr0); 109 + if (dev_priv->chipset >= 0x90) 110 + nv_wr32(dev, 0xe074, intr1); 237 111 } 238 112 239 113 int 240 114 nv50_gpio_init(struct drm_device *dev) 241 115 { 242 116 struct drm_nouveau_private *dev_priv = dev->dev_private; 243 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 244 - int ret; 245 - 246 - if (!pgpio->priv) { 247 - ret = nv50_gpio_create(dev); 248 - if (ret) 249 - return ret; 250 - } 251 117 252 118 /* disable, and ack any pending gpio interrupts */ 253 119 nv_wr32(dev, 0xe050, 0x00000000); ··· 136 270 if (dev_priv->chipset >= 0x90) 137 271 nv_wr32(dev, 0xe070, 0x00000000); 138 272 nouveau_irq_unregister(dev, 21); 139 - 140 - nv50_gpio_destroy(dev); 141 - } 142 - 143 - static void 144 - nv50_gpio_isr_bh(struct work_struct *work) 145 - { 146 - struct nv50_gpio_handler *gpioh = 147 - container_of(work, struct nv50_gpio_handler, work); 148 - struct drm_nouveau_private *dev_priv = gpioh->dev->dev_private; 149 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 150 - struct nv50_gpio_priv *priv = pgpio->priv; 151 - unsigned long flags; 152 - int state; 153 - 154 - state = pgpio->get(gpioh->dev, gpioh->gpio->tag); 155 - if (state < 0) 156 - return; 157 - 158 - gpioh->handler(gpioh->data, state); 159 - 160 - spin_lock_irqsave(&priv->lock, flags); 161 - gpioh->inhibit = false; 162 - spin_unlock_irqrestore(&priv->lock, flags); 163 - } 164 - 165 - static void 166 - nv50_gpio_isr(struct drm_device *dev) 167 - { 168 - struct drm_nouveau_private *dev_priv = dev->dev_private; 169 - struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio; 170 - struct nv50_gpio_priv *priv = pgpio->priv; 171 - struct nv50_gpio_handler *gpioh; 172 - u32 intr0, intr1 = 0; 173 - u32 hi, lo, ch; 174 - 175 - intr0 = nv_rd32(dev, 0xe054) & nv_rd32(dev, 0xe050); 176 - if (dev_priv->chipset >= 0x90) 177 - intr1 = nv_rd32(dev, 0xe074) & nv_rd32(dev, 0xe070); 178 - 179 - hi = (intr0 & 0x0000ffff) | (intr1 << 16); 180 - lo = (intr0 >> 16) | (intr1 & 0xffff0000); 181 - ch = hi | lo; 182 - 183 - nv_wr32(dev, 0xe054, intr0); 184 - if (dev_priv->chipset >= 0x90) 185 - nv_wr32(dev, 0xe074, intr1); 186 - 187 - spin_lock(&priv->lock); 188 - list_for_each_entry(gpioh, &priv->handlers, head) { 189 - if (!(ch & (1 << gpioh->gpio->line))) 190 - continue; 191 - 192 - if (gpioh->inhibit) 193 - continue; 194 - gpioh->inhibit = true; 195 - 196 - schedule_work(&gpioh->work); 197 - } 198 - spin_unlock(&priv->lock); 199 273 }