dmacgv100.c (2918B)
1/* 2 * Copyright 2018 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#include "channv50.h" 23 24#include <core/ramht.h> 25#include <subdev/timer.h> 26 27static int 28gv100_disp_dmac_idle(struct nv50_disp_chan *chan) 29{ 30 struct nvkm_device *device = chan->disp->base.engine.subdev.device; 31 const u32 soff = (chan->chid.ctrl - 1) * 0x04; 32 nvkm_msec(device, 2000, 33 u32 stat = nvkm_rd32(device, 0x610664 + soff); 34 if ((stat & 0x000f0000) == 0x00040000) 35 return 0; 36 ); 37 return -EBUSY; 38} 39 40int 41gv100_disp_dmac_bind(struct nv50_disp_chan *chan, 42 struct nvkm_object *object, u32 handle) 43{ 44 return nvkm_ramht_insert(chan->disp->ramht, object, 45 chan->chid.user, -9, handle, 46 chan->chid.user << 25 | 0x00000040); 47} 48 49void 50gv100_disp_dmac_fini(struct nv50_disp_chan *chan) 51{ 52 struct nvkm_device *device = chan->disp->base.engine.subdev.device; 53 const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; 54 const u32 coff = chan->chid.ctrl * 0x04; 55 nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); 56 gv100_disp_dmac_idle(chan); 57 nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); 58 chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); 59} 60 61int 62gv100_disp_dmac_init(struct nv50_disp_chan *chan) 63{ 64 struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; 65 struct nvkm_device *device = subdev->device; 66 const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; 67 const u32 poff = chan->chid.ctrl * 0x10; 68 const u32 coff = chan->chid.ctrl * 0x04; 69 70 nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); 71 nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); 72 nvkm_wr32(device, 0x610b28 + poff, 0x00000001); 73 nvkm_wr32(device, 0x610b2c + poff, 0x00000040); 74 75 nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); 76 nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); 77 nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); 78 return gv100_disp_dmac_idle(chan); 79}