2 * Copyright 2018 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
25 #include <drm/drm_atomic_helper.h>
26 #include <drm/drm_plane_helper.h>
27 #include <nouveau_bo.h>
29 #include <nvif/clc37e.h>
30 #include <nvif/pushc37b.h>
32 #include <nvhw/class/clc57e.h>
35 wndwc57e_image_set(struct nv50_wndw
*wndw
, struct nv50_wndw_atom
*asyw
)
37 struct nvif_push
*push
= wndw
->wndw
.push
;
40 if ((ret
= PUSH_WAIT(push
, 17)))
43 PUSH_MTHD(push
, NVC57E
, SET_PRESENT_CONTROL
,
44 NVVAL(NVC57E
, SET_PRESENT_CONTROL
, MIN_PRESENT_INTERVAL
, asyw
->image
.interval
) |
45 NVVAL(NVC57E
, SET_PRESENT_CONTROL
, BEGIN_MODE
, asyw
->image
.mode
) |
46 NVDEF(NVC57E
, SET_PRESENT_CONTROL
, TIMESTAMP_MODE
, DISABLE
));
48 PUSH_MTHD(push
, NVC57E
, SET_SIZE
,
49 NVVAL(NVC57E
, SET_SIZE
, WIDTH
, asyw
->image
.w
) |
50 NVVAL(NVC57E
, SET_SIZE
, HEIGHT
, asyw
->image
.h
),
53 NVVAL(NVC57E
, SET_STORAGE
, BLOCK_HEIGHT
, asyw
->image
.blockh
) |
54 NVVAL(NVC57E
, SET_STORAGE
, MEMORY_LAYOUT
, asyw
->image
.layout
),
57 NVVAL(NVC57E
, SET_PARAMS
, FORMAT
, asyw
->image
.format
) |
58 NVDEF(NVC57E
, SET_PARAMS
, CLAMP_BEFORE_BLEND
, DISABLE
) |
59 NVDEF(NVC57E
, SET_PARAMS
, SWAP_UV
, DISABLE
) |
60 NVDEF(NVC57E
, SET_PARAMS
, FMT_ROUNDING_MODE
, ROUND_TO_NEAREST
),
62 SET_PLANAR_STORAGE(0),
63 NVVAL(NVC57E
, SET_PLANAR_STORAGE
, PITCH
, asyw
->image
.blocks
[0]) |
64 NVVAL(NVC57E
, SET_PLANAR_STORAGE
, PITCH
, asyw
->image
.pitch
[0] >> 6));
66 PUSH_MTHD(push
, NVC57E
, SET_CONTEXT_DMA_ISO(0), asyw
->image
.handle
, 1);
67 PUSH_MTHD(push
, NVC57E
, SET_OFFSET(0), asyw
->image
.offset
[0] >> 8);
69 PUSH_MTHD(push
, NVC57E
, SET_POINT_IN(0),
70 NVVAL(NVC57E
, SET_POINT_IN
, X
, asyw
->state
.src_x
>> 16) |
71 NVVAL(NVC57E
, SET_POINT_IN
, Y
, asyw
->state
.src_y
>> 16));
73 PUSH_MTHD(push
, NVC57E
, SET_SIZE_IN
,
74 NVVAL(NVC57E
, SET_SIZE_IN
, WIDTH
, asyw
->state
.src_w
>> 16) |
75 NVVAL(NVC57E
, SET_SIZE_IN
, HEIGHT
, asyw
->state
.src_h
>> 16));
77 PUSH_MTHD(push
, NVC57E
, SET_SIZE_OUT
,
78 NVVAL(NVC57E
, SET_SIZE_OUT
, WIDTH
, asyw
->state
.crtc_w
) |
79 NVVAL(NVC57E
, SET_SIZE_OUT
, HEIGHT
, asyw
->state
.crtc_h
));
84 wndwc57e_csc_clr(struct nv50_wndw
*wndw
)
86 struct nvif_push
*push
= wndw
->wndw
.push
;
87 const u32 identity
[12] = {
88 0x00010000, 0x00000000, 0x00000000, 0x00000000,
89 0x00000000, 0x00010000, 0x00000000, 0x00000000,
90 0x00000000, 0x00000000, 0x00010000, 0x00000000,
94 if ((ret
= PUSH_WAIT(push
, 1 + ARRAY_SIZE(identity
))))
97 PUSH_MTHD(push
, NVC57E
, SET_FMT_COEFFICIENT_C00
, identity
, ARRAY_SIZE(identity
));
102 wndwc57e_csc_set(struct nv50_wndw
*wndw
, struct nv50_wndw_atom
*asyw
)
104 struct nvif_push
*push
= wndw
->wndw
.push
;
107 if ((ret
= PUSH_WAIT(push
, 13)))
110 PUSH_MTHD(push
, NVC57E
, SET_FMT_COEFFICIENT_C00
, asyw
->csc
.matrix
, 12);
115 wndwc57e_ilut_clr(struct nv50_wndw
*wndw
)
117 struct nvif_push
*push
= wndw
->wndw
.push
;
120 if ((ret
= PUSH_WAIT(push
, 2)))
123 PUSH_MTHD(push
, NVC57E
, SET_CONTEXT_DMA_ILUT
, 0x00000000);
128 wndwc57e_ilut_set(struct nv50_wndw
*wndw
, struct nv50_wndw_atom
*asyw
)
130 struct nvif_push
*push
= wndw
->wndw
.push
;
133 if ((ret
= PUSH_WAIT(push
, 4)))
136 PUSH_MTHD(push
, NVC57E
, SET_ILUT_CONTROL
,
137 NVVAL(NVC57E
, SET_ILUT_CONTROL
, SIZE
, asyw
->xlut
.i
.size
) |
138 NVVAL(NVC57E
, SET_ILUT_CONTROL
, MODE
, asyw
->xlut
.i
.mode
) |
139 NVVAL(NVC57E
, SET_ILUT_CONTROL
, INTERPOLATE
, asyw
->xlut
.i
.output_mode
),
141 SET_CONTEXT_DMA_ILUT
, asyw
->xlut
.handle
,
142 SET_OFFSET_ILUT
, asyw
->xlut
.i
.offset
>> 8);
147 fixedU0_16_FP16(u16 fixed
)
149 int sign
= 0, exp
= 0, man
= 0;
151 while (--exp
&& !(fixed
& 0x8000))
153 man
= ((fixed
<< 1) & 0xffc0) >> 6;
156 return (sign
<< 15) | (exp
<< 10) | man
;
160 wndwc57e_ilut_load(struct drm_color_lut
*in
, int size
, void __iomem
*mem
)
162 memset_io(mem
, 0x00, 0x20); /* VSS header. */
165 for (; size
--; in
++, mem
+= 0x08) {
166 u16 r
= fixedU0_16_FP16(drm_color_lut_extract(in
-> red
, 16));
167 u16 g
= fixedU0_16_FP16(drm_color_lut_extract(in
->green
, 16));
168 u16 b
= fixedU0_16_FP16(drm_color_lut_extract(in
-> blue
, 16));
174 /* INTERPOLATE modes require a "next" entry to interpolate with,
175 * so we replicate the last entry to deal with this for now.
177 writew(readw(mem
- 8), mem
+ 0);
178 writew(readw(mem
- 6), mem
+ 2);
179 writew(readw(mem
- 4), mem
+ 4);
183 wndwc57e_ilut(struct nv50_wndw
*wndw
, struct nv50_wndw_atom
*asyw
, int size
)
185 if (size
= size
? size
: 1024, size
!= 256 && size
!= 1024)
189 asyw
->xlut
.i
.mode
= NVC57E_SET_ILUT_CONTROL_MODE_DIRECT8
;
191 asyw
->xlut
.i
.mode
= NVC57E_SET_ILUT_CONTROL_MODE_DIRECT10
;
193 asyw
->xlut
.i
.size
= 4 /* VSS header. */ + size
+ 1 /* Entries. */;
194 asyw
->xlut
.i
.output_mode
= NVC57E_SET_ILUT_CONTROL_INTERPOLATE_DISABLE
;
195 asyw
->xlut
.i
.load
= wndwc57e_ilut_load
;
199 /****************************************************************
200 * Log2(block height) ----------------------------+ *
201 * Page Kind ----------------------------------+ | *
202 * Gob Height/Page Kind Generation ------+ | | *
203 * Sector layout -------+ | | | *
204 * Compression ------+ | | | | */
205 const u64 wndwc57e_modifiers
[] = { /* | | | | | */
206 DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 0),
207 DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 1),
208 DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 2),
209 DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 3),
210 DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 4),
211 DRM_FORMAT_MOD_NVIDIA_BLOCK_LINEAR_2D(0, 1, 2, 0x06, 5),
212 DRM_FORMAT_MOD_LINEAR
,
213 DRM_FORMAT_MOD_INVALID
216 static const struct nv50_wndw_func
218 .acquire
= wndwc37e_acquire
,
219 .release
= wndwc37e_release
,
220 .sema_set
= wndwc37e_sema_set
,
221 .sema_clr
= wndwc37e_sema_clr
,
222 .ntfy_set
= wndwc37e_ntfy_set
,
223 .ntfy_clr
= wndwc37e_ntfy_clr
,
224 .ntfy_reset
= corec37d_ntfy_init
,
225 .ntfy_wait_begun
= base507c_ntfy_wait_begun
,
226 .ilut
= wndwc57e_ilut
,
227 .ilut_identity
= true,
229 .xlut_set
= wndwc57e_ilut_set
,
230 .xlut_clr
= wndwc57e_ilut_clr
,
232 .csc_set
= wndwc57e_csc_set
,
233 .csc_clr
= wndwc57e_csc_clr
,
234 .image_set
= wndwc57e_image_set
,
235 .image_clr
= wndwc37e_image_clr
,
236 .blend_set
= wndwc37e_blend_set
,
237 .update
= wndwc37e_update
,
241 wndwc57e_new(struct nouveau_drm
*drm
, enum drm_plane_type type
, int index
,
242 s32 oclass
, struct nv50_wndw
**pwndw
)
244 return wndwc37e_new_(&wndwc57e
, drm
, type
, index
, oclass
,
245 BIT(index
>> 1), pwndw
);