drm/nouveau/kms/nv50-: use NVIDIA's headers for wndw csc_clr()
[linux-2.6-microblaze.git] / drivers / gpu / drm / nouveau / dispnv50 / base907c.c
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 "base.h"
23
24 #include <nvif/push507c.h>
25
26 #include <nvhw/class/cl907c.h>
27
28 static int
29 base907c_image_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
30 {
31         struct nvif_push *push = wndw->wndw.push;
32         int ret;
33
34         if ((ret = PUSH_WAIT(push, 10)))
35                 return ret;
36
37         PUSH_NVSQ(push, NV907C, 0x0084, asyw->image.mode << 8 |
38                                         asyw->image.interval << 4);
39         PUSH_NVSQ(push, NV907C, 0x00c0, asyw->image.handle[0]);
40         PUSH_NVSQ(push, NV907C, 0x0400, asyw->image.offset[0] >> 8,
41                                 0x0404, 0x00000000,
42                                 0x0408, asyw->image.h << 16 | asyw->image.w,
43                                 0x040c, asyw->image.layout << 24 |
44                                        (asyw->image.pitch[0] >> 8) << 8 |
45                                         asyw->image.blocks[0] << 8 |
46                                         asyw->image.blockh,
47                                 0x0410, asyw->image.format << 8);
48         return 0;
49 }
50
51 static int
52 base907c_xlut_clr(struct nv50_wndw *wndw)
53 {
54         struct nvif_push *push = wndw->wndw.push;
55         int ret;
56
57         if ((ret = PUSH_WAIT(push, 6)))
58                 return ret;
59
60         PUSH_NVSQ(push, NV907C, 0x00e0, 0x00000000);
61         PUSH_NVSQ(push, NV907C, 0x00e8, 0x00000000);
62         PUSH_NVSQ(push, NV907C, 0x00fc, 0x00000000);
63         return 0;
64 }
65
66 static int
67 base907c_xlut_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
68 {
69         struct nvif_push *push = wndw->wndw.push;
70         int ret;
71
72         if ((ret = PUSH_WAIT(push, 6)))
73                 return ret;
74
75         PUSH_NVSQ(push, NV907C, 0x00e0, asyw->xlut.i.enable << 30 |
76                                         asyw->xlut.i.mode << 24,
77                                 0x00e4, asyw->xlut.i.offset >> 8,
78                                 0x00e8, 0x40000000);
79         PUSH_NVSQ(push, NV907C, 0x00fc, asyw->xlut.handle);
80         return 0;
81 }
82
83 static bool
84 base907c_ilut(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw, int size)
85 {
86         if (size != 256 && size != 1024)
87                 return false;
88
89         asyw->xlut.i.mode = size == 1024 ? 4 : 7;
90         asyw->xlut.i.enable = 2;
91         asyw->xlut.i.load = head907d_olut_load;
92         return true;
93 }
94
95 static inline u32
96 csc_drm_to_base(u64 in)
97 {
98         /* base takes a 19-bit 2's complement value in S3.16 format */
99         bool sign = in & BIT_ULL(63);
100         u32 integer = (in >> 32) & 0x7fffffff;
101         u32 fraction = in & 0xffffffff;
102
103         if (integer >= 4) {
104                 return (1 << 18) - (sign ? 0 : 1);
105         } else {
106                 u32 ret = (integer << 16) | (fraction >> 16);
107                 if (sign)
108                         ret = -ret;
109                 return ret & GENMASK(18, 0);
110         }
111 }
112
113 void
114 base907c_csc(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw,
115              const struct drm_color_ctm *ctm)
116 {
117         int i, j;
118
119         for (j = 0; j < 3; j++) {
120                 for (i = 0; i < 4; i++) {
121                         u32 *val = &asyw->csc.matrix[j * 4 + i];
122                         /* DRM does not support constant offset, while
123                          * HW CSC does. Skip it. */
124                         if (i == 3) {
125                                 *val = 0;
126                         } else {
127                                 *val = csc_drm_to_base(ctm->matrix[j * 3 + i]);
128                         }
129                 }
130         }
131 }
132
133 static int
134 base907c_csc_clr(struct nv50_wndw *wndw)
135 {
136         struct nvif_push *push = wndw->wndw.push;
137         int ret;
138
139         if ((ret = PUSH_WAIT(push, 2)))
140                 return ret;
141
142         PUSH_MTHD(push, NV907C, SET_CSC_RED2RED,
143                   NVDEF(NV907C, SET_CSC_RED2RED, OWNER, CORE));
144         return 0;
145 }
146
147 static int
148 base907c_csc_set(struct nv50_wndw *wndw, struct nv50_wndw_atom *asyw)
149 {
150         struct nvif_push *push = wndw->wndw.push;
151         int ret;
152
153         if ((ret = PUSH_WAIT(push, 13)))
154                 return ret;
155
156         PUSH_MTHD(push, NV907C, SET_CSC_RED2RED,
157                   NVDEF(NV907C, SET_CSC_RED2RED, OWNER, BASE) |
158                   NVVAL(NV907C, SET_CSC_RED2RED, COEFF, asyw->csc.matrix[0]),
159
160                                 SET_CSC_GRN2RED, &asyw->csc.matrix[1], 11);
161         return 0;
162 }
163
164 const struct nv50_wndw_func
165 base907c = {
166         .acquire = base507c_acquire,
167         .release = base507c_release,
168         .sema_set = base507c_sema_set,
169         .sema_clr = base507c_sema_clr,
170         .ntfy_reset = base507c_ntfy_reset,
171         .ntfy_set = base507c_ntfy_set,
172         .ntfy_clr = base507c_ntfy_clr,
173         .ntfy_wait_begun = base507c_ntfy_wait_begun,
174         .ilut = base907c_ilut,
175         .csc = base907c_csc,
176         .csc_set = base907c_csc_set,
177         .csc_clr = base907c_csc_clr,
178         .olut_core = true,
179         .ilut_size = 1024,
180         .xlut_set = base907c_xlut_set,
181         .xlut_clr = base907c_xlut_clr,
182         .image_set = base907c_image_set,
183         .image_clr = base507c_image_clr,
184         .update = base507c_update,
185 };
186
187 int
188 base907c_new(struct nouveau_drm *drm, int head, s32 oclass,
189              struct nv50_wndw **pwndw)
190 {
191         return base507c_new_(&base907c, base507c_format, drm, head, oclass,
192                              0x00000002 << (head * 4), pwndw);
193 }