1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#include "head.h"
23#include "atom.h"
24#include "core.h"
25
26static void
27headc57d_or(struct nv50_head *head, struct nv50_head_atom *asyh)
28{
29 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
30 u32 *push;
31 if ((push = evo_wait(core, 2))) {
32
33
34
35 switch (asyh->or.depth) {
36 case 6: asyh->or.depth = 5; break;
37 case 5: asyh->or.depth = 4; break;
38 case 2: asyh->or.depth = 1; break;
39 case 0: asyh->or.depth = 4; break;
40 default:
41 WARN_ON(1);
42 break;
43 }
44
45 evo_mthd(push, 0x2004 + (head->base.index * 0x400), 1);
46 evo_data(push, 0xfc000001 |
47 asyh->or.depth << 4 |
48 asyh->or.nvsync << 3 |
49 asyh->or.nhsync << 2);
50 evo_kick(push, core);
51 }
52}
53
54static void
55headc57d_procamp(struct nv50_head *head, struct nv50_head_atom *asyh)
56{
57 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
58 u32 *push;
59 if ((push = evo_wait(core, 2))) {
60 evo_mthd(push, 0x2000 + (head->base.index * 0x400), 1);
61#if 0
62 evo_data(push, 0x80000000 |
63 asyh->procamp.sat.sin << 16 |
64 asyh->procamp.sat.cos << 4);
65#else
66 evo_data(push, 0);
67#endif
68 evo_kick(push, core);
69 }
70}
71
72void
73headc57d_olut_clr(struct nv50_head *head)
74{
75 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
76 u32 *push;
77 if ((push = evo_wait(core, 2))) {
78 evo_mthd(push, 0x2288 + (head->base.index * 0x400), 1);
79 evo_data(push, 0x00000000);
80 evo_kick(push, core);
81 }
82}
83
84void
85headc57d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh)
86{
87 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
88 u32 *push;
89 if ((push = evo_wait(core, 4))) {
90 evo_mthd(push, 0x2280 + (head->base.index * 0x400), 4);
91 evo_data(push, asyh->olut.size << 8 |
92 asyh->olut.mode << 2 |
93 asyh->olut.output_mode);
94 evo_data(push, 0xffffffff);
95 evo_data(push, asyh->olut.handle);
96 evo_data(push, asyh->olut.offset >> 8);
97 evo_kick(push, core);
98 }
99}
100
101static void
102headc57d_olut_load_8(struct drm_color_lut *in, int size, void __iomem *mem)
103{
104 memset_io(mem, 0x00, 0x20);
105 mem += 0x20;
106
107 while (size--) {
108 u16 r = drm_color_lut_extract(in-> red + 0, 16);
109 u16 g = drm_color_lut_extract(in->green + 0, 16);
110 u16 b = drm_color_lut_extract(in-> blue + 0, 16);
111 u16 ri = 0, gi = 0, bi = 0, i;
112
113 if (in++, size) {
114 ri = (drm_color_lut_extract(in-> red, 16) - r) / 4;
115 gi = (drm_color_lut_extract(in->green, 16) - g) / 4;
116 bi = (drm_color_lut_extract(in-> blue, 16) - b) / 4;
117 }
118
119 for (i = 0; i < 4; i++, mem += 8) {
120 writew(r + ri * i, mem + 0);
121 writew(g + gi * i, mem + 2);
122 writew(b + bi * i, mem + 4);
123 }
124 }
125
126
127
128
129 writew(readw(mem - 8), mem + 0);
130 writew(readw(mem - 6), mem + 2);
131 writew(readw(mem - 4), mem + 4);
132}
133
134static void
135headc57d_olut_load(struct drm_color_lut *in, int size, void __iomem *mem)
136{
137 memset_io(mem, 0x00, 0x20);
138 mem += 0x20;
139
140 for (; size--; in++, mem += 0x08) {
141 writew(drm_color_lut_extract(in-> red, 16), mem + 0);
142 writew(drm_color_lut_extract(in->green, 16), mem + 2);
143 writew(drm_color_lut_extract(in-> blue, 16), mem + 4);
144 }
145
146
147
148
149 writew(readw(mem - 8), mem + 0);
150 writew(readw(mem - 6), mem + 2);
151 writew(readw(mem - 4), mem + 4);
152}
153
154bool
155headc57d_olut(struct nv50_head *head, struct nv50_head_atom *asyh, int size)
156{
157 if (size != 0 && size != 256 && size != 1024)
158 return false;
159
160 asyh->olut.mode = 2;
161 asyh->olut.size = 4 + 1024 + 1 ;
162 asyh->olut.output_mode = 1;
163 if (size == 256)
164 asyh->olut.load = headc57d_olut_load_8;
165 else
166 asyh->olut.load = headc57d_olut_load;
167 return true;
168}
169
170static void
171headc57d_mode(struct nv50_head *head, struct nv50_head_atom *asyh)
172{
173 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan;
174 struct nv50_head_mode *m = &asyh->mode;
175 u32 *push;
176 if ((push = evo_wait(core, 13))) {
177 evo_mthd(push, 0x2064 + (head->base.index * 0x400), 5);
178 evo_data(push, (m->v.active << 16) | m->h.active );
179 evo_data(push, (m->v.synce << 16) | m->h.synce );
180 evo_data(push, (m->v.blanke << 16) | m->h.blanke );
181 evo_data(push, (m->v.blanks << 16) | m->h.blanks );
182 evo_data(push, (m->v.blank2e << 16) | m->v.blank2s);
183 evo_mthd(push, 0x2008 + (head->base.index * 0x400), 2);
184 evo_data(push, m->interlace);
185 evo_data(push, m->clock * 1000);
186 evo_mthd(push, 0x2028 + (head->base.index * 0x400), 1);
187 evo_data(push, m->clock * 1000);
188
189 evo_mthd(push, 0x2030 + (head->base.index * 0x400), 1);
190 evo_data(push, 0x00001014);
191 evo_kick(push, core);
192 }
193}
194
195const struct nv50_head_func
196headc57d = {
197 .view = headc37d_view,
198 .mode = headc57d_mode,
199 .olut = headc57d_olut,
200 .olut_identity = true,
201 .olut_size = 1024,
202 .olut_set = headc57d_olut_set,
203 .olut_clr = headc57d_olut_clr,
204 .curs_layout = head917d_curs_layout,
205 .curs_format = headc37d_curs_format,
206 .curs_set = headc37d_curs_set,
207 .curs_clr = headc37d_curs_clr,
208 .dither = headc37d_dither,
209 .procamp = headc57d_procamp,
210 .or = headc57d_or,
211};
212