0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include "nouveau_bo.h"
0030 #include "nouveau_dma.h"
0031 #include "nouveau_drv.h"
0032 #include "nouveau_mem.h"
0033
0034 #include <nvif/push206e.h>
0035
0036 #include <nvhw/class/cl5039.h>
0037
0038 int
0039 nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
0040 struct ttm_resource *old_reg, struct ttm_resource *new_reg)
0041 {
0042 struct nouveau_mem *mem = nouveau_mem(old_reg);
0043 struct nvif_push *push = chan->chan.push;
0044 u64 length = (new_reg->num_pages << PAGE_SHIFT);
0045 u64 src_offset = mem->vma[0].addr;
0046 u64 dst_offset = mem->vma[1].addr;
0047 int src_tiled = !!mem->kind;
0048 int dst_tiled = !!nouveau_mem(new_reg)->kind;
0049 int ret;
0050
0051 while (length) {
0052 u32 amount, stride, height;
0053
0054 ret = PUSH_WAIT(push, 18 + 6 * (src_tiled + dst_tiled));
0055 if (ret)
0056 return ret;
0057
0058 amount = min(length, (u64)(4 * 1024 * 1024));
0059 stride = 16 * 4;
0060 height = amount / stride;
0061
0062 if (src_tiled) {
0063 PUSH_MTHD(push, NV5039, SET_SRC_MEMORY_LAYOUT,
0064 NVDEF(NV5039, SET_SRC_MEMORY_LAYOUT, V, BLOCKLINEAR),
0065
0066 SET_SRC_BLOCK_SIZE,
0067 NVDEF(NV5039, SET_SRC_BLOCK_SIZE, WIDTH, ONE_GOB) |
0068 NVDEF(NV5039, SET_SRC_BLOCK_SIZE, HEIGHT, ONE_GOB) |
0069 NVDEF(NV5039, SET_SRC_BLOCK_SIZE, DEPTH, ONE_GOB),
0070
0071 SET_SRC_WIDTH, stride,
0072 SET_SRC_HEIGHT, height,
0073 SET_SRC_DEPTH, 1,
0074 SET_SRC_LAYER, 0,
0075
0076 SET_SRC_ORIGIN,
0077 NVVAL(NV5039, SET_SRC_ORIGIN, X, 0) |
0078 NVVAL(NV5039, SET_SRC_ORIGIN, Y, 0));
0079 } else {
0080 PUSH_MTHD(push, NV5039, SET_SRC_MEMORY_LAYOUT,
0081 NVDEF(NV5039, SET_SRC_MEMORY_LAYOUT, V, PITCH));
0082 }
0083
0084 if (dst_tiled) {
0085 PUSH_MTHD(push, NV5039, SET_DST_MEMORY_LAYOUT,
0086 NVDEF(NV5039, SET_DST_MEMORY_LAYOUT, V, BLOCKLINEAR),
0087
0088 SET_DST_BLOCK_SIZE,
0089 NVDEF(NV5039, SET_DST_BLOCK_SIZE, WIDTH, ONE_GOB) |
0090 NVDEF(NV5039, SET_DST_BLOCK_SIZE, HEIGHT, ONE_GOB) |
0091 NVDEF(NV5039, SET_DST_BLOCK_SIZE, DEPTH, ONE_GOB),
0092
0093 SET_DST_WIDTH, stride,
0094 SET_DST_HEIGHT, height,
0095 SET_DST_DEPTH, 1,
0096 SET_DST_LAYER, 0,
0097
0098 SET_DST_ORIGIN,
0099 NVVAL(NV5039, SET_DST_ORIGIN, X, 0) |
0100 NVVAL(NV5039, SET_DST_ORIGIN, Y, 0));
0101 } else {
0102 PUSH_MTHD(push, NV5039, SET_DST_MEMORY_LAYOUT,
0103 NVDEF(NV5039, SET_DST_MEMORY_LAYOUT, V, PITCH));
0104 }
0105
0106 PUSH_MTHD(push, NV5039, OFFSET_IN_UPPER,
0107 NVVAL(NV5039, OFFSET_IN_UPPER, VALUE, upper_32_bits(src_offset)),
0108
0109 OFFSET_OUT_UPPER,
0110 NVVAL(NV5039, OFFSET_OUT_UPPER, VALUE, upper_32_bits(dst_offset)));
0111
0112 PUSH_MTHD(push, NV5039, OFFSET_IN, lower_32_bits(src_offset),
0113 OFFSET_OUT, lower_32_bits(dst_offset),
0114 PITCH_IN, stride,
0115 PITCH_OUT, stride,
0116 LINE_LENGTH_IN, stride,
0117 LINE_COUNT, height,
0118
0119 FORMAT,
0120 NVDEF(NV5039, FORMAT, IN, ONE) |
0121 NVDEF(NV5039, FORMAT, OUT, ONE),
0122
0123 BUFFER_NOTIFY,
0124 NVDEF(NV5039, BUFFER_NOTIFY, TYPE, WRITE_ONLY));
0125
0126 PUSH_MTHD(push, NV5039, NO_OPERATION, 0x00000000);
0127
0128 length -= amount;
0129 src_offset += amount;
0130 dst_offset += amount;
0131 }
0132
0133 return 0;
0134 }
0135
0136 int
0137 nv50_bo_move_init(struct nouveau_channel *chan, u32 handle)
0138 {
0139 struct nvif_push *push = chan->chan.push;
0140 int ret;
0141
0142 ret = PUSH_WAIT(push, 6);
0143 if (ret)
0144 return ret;
0145
0146 PUSH_MTHD(push, NV5039, SET_OBJECT, handle);
0147 PUSH_MTHD(push, NV5039, SET_CONTEXT_DMA_NOTIFY, chan->drm->ntfy.handle,
0148 SET_CONTEXT_DMA_BUFFER_IN, chan->vram.handle,
0149 SET_CONTEXT_DMA_BUFFER_OUT, chan->vram.handle);
0150 return 0;
0151 }