drm/nouveau/fb/ramnv50: Voltage GPIOs
authorRoy Spliet <rspliet@eclipso.eu>
Tue, 29 Sep 2015 23:23:48 +0000 (00:23 +0100)
committerBen Skeggs <bskeggs@redhat.com>
Tue, 3 Nov 2015 05:02:18 +0000 (15:02 +1000)
Does not seem to be necessary for NVA0, hence untested by me.

Signed-off-by: Roy Spliet <rspliet@eclipso.eu>
Tested-by: Pierre Moreau <pierre.morrow@free.fr>
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nvkm/subdev/bios/rammap.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c

index 74a4ab5b6ad1b87dd1e53bb474d5849346be16b1..d0ae7454764ea4097e9be1386b268414ba68a11d 100644 (file)
@@ -171,6 +171,7 @@ nvbios_rammapSp_from_perf(struct nvkm_bios *bios, u32 data, u8 size, int idx,
        p->ramcfg_DLLoff   = (nvbios_rd08(bios, data + 0x03) & 0x04) >> 2;
        p->ramcfg_00_03_08 = (nvbios_rd08(bios, data + 0x03) & 0x08) >> 3;
        p->ramcfg_RON      = (nvbios_rd08(bios, data + 0x03) & 0x10) >> 3;
+       p->ramcfg_FBVDDQ   = (nvbios_rd08(bios, data + 0x03) & 0x80) >> 7;
        p->ramcfg_00_04_02 = (nvbios_rd08(bios, data + 0x04) & 0x02) >> 1;
        p->ramcfg_00_04_04 = (nvbios_rd08(bios, data + 0x04) & 0x04) >> 2;
        p->ramcfg_00_04_20 = (nvbios_rd08(bios, data + 0x04) & 0x20) >> 5;
index 9197e0ef5cdb94fbade89d84bbd2bc284d1faa9a..ae6b0c4043d3c4fc415693bbfb1888b67449b088 100644 (file)
@@ -33,6 +33,7 @@
 #include <subdev/bios/rammap.h>
 #include <subdev/bios/timing.h>
 #include <subdev/clk/pll.h>
+#include <subdev/gpio.h>
 
 struct nv50_ramseq {
        struct hwsq base;
@@ -59,6 +60,7 @@ struct nv50_ramseq {
        struct hwsq_reg r_0x611200;
        struct hwsq_reg r_timing[9];
        struct hwsq_reg r_mr[4];
+       struct hwsq_reg r_gpio[4];
 };
 
 struct nv50_ram {
@@ -154,6 +156,33 @@ nvkm_sddr2_dll_reset(struct nv50_ramseq *hwsq)
        ram_nsec(hwsq, 24000);
 }
 
+static void
+nv50_ram_gpio(struct nv50_ramseq *hwsq, u8 tag, u32 val)
+{
+       struct nvkm_gpio *gpio = hwsq->base.subdev->device->gpio;
+       struct dcb_gpio_func func;
+       u32 reg, sh, gpio_val;
+       int ret;
+
+       if (nvkm_gpio_get(gpio, 0, tag, DCB_GPIO_UNUSED) != val) {
+               ret = nvkm_gpio_find(gpio, 0, tag, DCB_GPIO_UNUSED, &func);
+               if (ret)
+                       return;
+
+               reg = func.line >> 3;
+               sh = (func.line & 0x7) << 2;
+               gpio_val = ram_rd32(hwsq, gpio[reg]);
+
+               if (gpio_val & (8 << sh))
+                       val = !val;
+               if (!(func.log[1] & 1))
+                       val = !val;
+
+               ram_mask(hwsq, gpio[reg], (0x3 << sh), ((val | 0x2) << sh));
+               ram_nsec(hwsq, 20000);
+       }
+}
+
 static int
 nv50_ram_calc(struct nvkm_ram *base, u32 freq)
 {
@@ -250,6 +279,9 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
        ram_wait(hwsq, 0x00, 0x01); /* wait for fb disabled */
        ram_nsec(hwsq, 2000);
 
+       if (next->bios.timing_10_ODT)
+               nv50_ram_gpio(hwsq, 0x2e, 1);
+
        ram_wr32(hwsq, 0x1002d4, 0x00000001); /* precharge */
        ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */
        ram_wr32(hwsq, 0x1002d0, 0x00000001); /* refresh */
@@ -288,6 +320,7 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
        ram_mask(hwsq, 0x004008, 0x91ff0000, r004008);
        if (subdev->device->chipset >= 0x96)
                ram_wr32(hwsq, 0x100da0, r100da0);
+       nv50_ram_gpio(hwsq, 0x18, !next->bios.ramcfg_FBVDDQ);
        ram_nsec(hwsq, 64000); /*XXX*/
        ram_nsec(hwsq, 32000); /*XXX*/
 
@@ -364,6 +397,9 @@ nv50_ram_calc(struct nvkm_ram *base, u32 freq)
        }
        ram_mask(hwsq, mr[1], 0xffffffff, ram->base.mr[1]);
 
+       if (!next->bios.timing_10_ODT)
+               nv50_ram_gpio(hwsq, 0x2e, 0);
+
        /* Reset DLL */
        if (!next->bios.ramcfg_DLLoff)
                nvkm_sddr2_dll_reset(hwsq);
@@ -634,5 +670,10 @@ nv50_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram)
                ram->hwsq.r_mr[3] = hwsq_reg(0x1002e4);
        }
 
+       ram->hwsq.r_gpio[0] = hwsq_reg(0x00e104);
+       ram->hwsq.r_gpio[1] = hwsq_reg(0x00e108);
+       ram->hwsq.r_gpio[2] = hwsq_reg(0x00e120);
+       ram->hwsq.r_gpio[3] = hwsq_reg(0x00e124);
+
        return 0;
 }