diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nvkm/falcon/v1.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nvkm/falcon/v1.c | 124 |
1 files changed, 104 insertions, 20 deletions
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index b537f111f39c..669c24028470 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -40,8 +40,8 @@ nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, for (i = 0; i < size / 4; i++) { /* write new tag every 256B */ if ((i & 0x3f) == 0) - nvkm_falcon_wr32(falcon, 0x188, tag++); - nvkm_falcon_wr32(falcon, 0x184, ((u32 *)data)[i]); + nvkm_falcon_wr32(falcon, 0x188 + (port * 16), tag++); + nvkm_falcon_wr32(falcon, 0x184 + (port * 16), ((u32 *)data)[i]); } /* @@ -53,37 +53,98 @@ nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start, /* write new tag every 256B */ if ((i & 0x3f) == 0) - nvkm_falcon_wr32(falcon, 0x188, tag++); - nvkm_falcon_wr32(falcon, 0x184, extra & (BIT(rem * 8) - 1)); + nvkm_falcon_wr32(falcon, 0x188 + (port * 16), tag++); + nvkm_falcon_wr32(falcon, 0x184 + (port * 16), + extra & (BIT(rem * 8) - 1)); ++i; } /* code must be padded to 0x40 words */ for (; i & 0x3f; i++) - nvkm_falcon_wr32(falcon, 0x184, 0); + nvkm_falcon_wr32(falcon, 0x184 + (port * 16), 0); } static void +nvkm_falcon_v1_load_emem(struct nvkm_falcon *falcon, void *data, u32 start, + u32 size, u8 port) +{ + u8 rem = size % 4; + int i; + + size -= rem; + + nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 24)); + for (i = 0; i < size / 4; i++) + nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), ((u32 *)data)[i]); + + /* + * If size is not a multiple of 4, mask the last word to ensure garbage + * does not get written + */ + if (rem) { + u32 extra = ((u32 *)data)[i]; + + nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), + extra & (BIT(rem * 8) - 1)); + } +} + +static const u32 EMEM_START_ADDR = 0x1000000; + +static void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start, u32 size, u8 port) { u8 rem = size % 4; int i; + if (start >= EMEM_START_ADDR && falcon->has_emem) + return nvkm_falcon_v1_load_emem(falcon, data, + start - EMEM_START_ADDR, size, + port); + size -= rem; - nvkm_falcon_wr32(falcon, 0x1c0 + (port * 16), start | (0x1 << 24)); + nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 24)); for (i = 0; i < size / 4; i++) - nvkm_falcon_wr32(falcon, 0x1c4, ((u32 *)data)[i]); + nvkm_falcon_wr32(falcon, 0x1c4 + (port * 8), ((u32 *)data)[i]); /* - * If size is not a multiple of 4, mask the last work to ensure garbage - * does not get read + * If size is not a multiple of 4, mask the last word to ensure garbage + * does not get written */ if (rem) { u32 extra = ((u32 *)data)[i]; - nvkm_falcon_wr32(falcon, 0x1c4, extra & (BIT(rem * 8) - 1)); + nvkm_falcon_wr32(falcon, 0x1c4 + (port * 8), + extra & (BIT(rem * 8) - 1)); + } +} + +static void +nvkm_falcon_v1_read_emem(struct nvkm_falcon *falcon, u32 start, u32 size, + u8 port, void *data) +{ + u8 rem = size % 4; + int i; + + size -= rem; + + nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 25)); + for (i = 0; i < size / 4; i++) + ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8)); + + /* + * If size is not a multiple of 4, mask the last word to ensure garbage + * does not get read + */ + if (rem) { + u32 extra = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8)); + + for (i = size; i < size + rem; i++) { + ((u8 *)data)[i] = (u8)(extra & 0xff); + extra >>= 8; + } } } @@ -94,18 +155,22 @@ nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 rem = size % 4; int i; + if (start >= EMEM_START_ADDR && falcon->has_emem) + return nvkm_falcon_v1_read_emem(falcon, start - EMEM_START_ADDR, + size, port, data); + size -= rem; - nvkm_falcon_wr32(falcon, 0x1c0 + (port * 16), start | (0x1 << 25)); + nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 25)); for (i = 0; i < size / 4; i++) - ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0x1c4); + ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8)); /* - * If size is not a multiple of 4, mask the last work to ensure garbage + * If size is not a multiple of 4, mask the last word to ensure garbage * does not get read */ if (rem) { - u32 extra = nvkm_falcon_rd32(falcon, 0x1c4); + u32 extra = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8)); for (i = size; i < size + rem; i++) { ((u8 *)data)[i] = (u8)(extra & 0xff); @@ -118,6 +183,7 @@ static void nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) { u32 inst_loc; + u32 fbif; /* disable instance block binding */ if (ctx == NULL) { @@ -125,19 +191,34 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) return; } + switch (falcon->owner->index) { + case NVKM_ENGINE_NVENC0: + case NVKM_ENGINE_NVENC1: + case NVKM_ENGINE_NVENC2: + fbif = 0x800; + break; + case NVKM_SUBDEV_PMU: + fbif = 0xe00; + break; + default: + fbif = 0x600; + break; + } + nvkm_falcon_wr32(falcon, 0x10c, 0x1); /* setup apertures - virtual */ - nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_UCODE, 0x4); - nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_VIRT, 0x0); + nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_UCODE, 0x4); + nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_VIRT, 0x0); /* setup apertures - physical */ - nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_VID, 0x4); - nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_SYS_COH, 0x5); - nvkm_falcon_wr32(falcon, 0xe00 + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); + nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_VID, 0x4); + nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_COH, 0x5); + nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); /* Set context */ switch (nvkm_memory_target(ctx->memory)) { case NVKM_MEM_TARGET_VRAM: inst_loc = 0; break; + case NVKM_MEM_TARGET_HOST: inst_loc = 2; break; case NVKM_MEM_TARGET_NCOH: inst_loc = 3; break; default: WARN_ON(1); @@ -146,9 +227,12 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) /* Enable context */ nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1); - nvkm_falcon_wr32(falcon, 0x480, + nvkm_falcon_wr32(falcon, 0x054, ((ctx->addr >> 12) & 0xfffffff) | (inst_loc << 28) | (1 << 30)); + + nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000); + nvkm_falcon_mask(falcon, 0x0a4, 0x8, 0x8); } static void |