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 "head.h" 23 #include "atom.h" 24 #include "core.h" 25 26 static void 27 headc37d_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 /*XXX: This is a dirty hack until OR depth handling is 33 * improved later for deep colour etc. 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, 0x00000001 | 47 asyh->or.depth << 4 | 48 asyh->or.nvsync << 3 | 49 asyh->or.nhsync << 2); 50 evo_kick(push, core); 51 } 52 } 53 54 static void 55 headc37d_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 evo_data(push, 0x80000000 | 62 asyh->procamp.sat.sin << 16 | 63 asyh->procamp.sat.cos << 4); 64 evo_kick(push, core); 65 } 66 } 67 68 static void 69 headc37d_dither(struct nv50_head *head, struct nv50_head_atom *asyh) 70 { 71 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 72 u32 *push; 73 if ((push = evo_wait(core, 2))) { 74 evo_mthd(push, 0x2018 + (head->base.index * 0x0400), 1); 75 evo_data(push, asyh->dither.mode << 8 | 76 asyh->dither.bits << 4 | 77 asyh->dither.enable); 78 evo_kick(push, core); 79 } 80 } 81 82 static void 83 headc37d_curs_clr(struct nv50_head *head) 84 { 85 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 86 u32 *push; 87 if ((push = evo_wait(core, 4))) { 88 evo_mthd(push, 0x209c + head->base.index * 0x400, 1); 89 evo_data(push, 0x000000cf); 90 evo_mthd(push, 0x2088 + head->base.index * 0x400, 1); 91 evo_data(push, 0x00000000); 92 evo_kick(push, core); 93 } 94 } 95 96 static void 97 headc37d_curs_set(struct nv50_head *head, struct nv50_head_atom *asyh) 98 { 99 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 100 u32 *push; 101 if ((push = evo_wait(core, 7))) { 102 evo_mthd(push, 0x209c + head->base.index * 0x400, 2); 103 evo_data(push, 0x80000000 | 104 asyh->curs.layout << 8 | 105 asyh->curs.format << 0); 106 evo_data(push, 0x000072ff); 107 evo_mthd(push, 0x2088 + head->base.index * 0x400, 1); 108 evo_data(push, asyh->curs.handle); 109 evo_mthd(push, 0x2090 + head->base.index * 0x400, 1); 110 evo_data(push, asyh->curs.offset >> 8); 111 evo_kick(push, core); 112 } 113 } 114 115 static int 116 headc37d_curs_format(struct nv50_head *head, struct nv50_wndw_atom *asyw, 117 struct nv50_head_atom *asyh) 118 { 119 asyh->curs.format = asyw->image.format; 120 return 0; 121 } 122 123 static void 124 headc37d_olut_clr(struct nv50_head *head) 125 { 126 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 127 u32 *push; 128 if ((push = evo_wait(core, 2))) { 129 evo_mthd(push, 0x20ac + (head->base.index * 0x400), 1); 130 evo_data(push, 0x00000000); 131 evo_kick(push, core); 132 } 133 } 134 135 static void 136 headc37d_olut_set(struct nv50_head *head, struct nv50_head_atom *asyh) 137 { 138 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 139 u32 *push; 140 if ((push = evo_wait(core, 4))) { 141 evo_mthd(push, 0x20a4 + (head->base.index * 0x400), 3); 142 evo_data(push, asyh->olut.output_mode << 8 | 143 asyh->olut.range << 4 | 144 asyh->olut.size); 145 evo_data(push, asyh->olut.offset >> 8); 146 evo_data(push, asyh->olut.handle); 147 evo_kick(push, core); 148 } 149 } 150 151 static void 152 headc37d_olut(struct nv50_head *head, struct nv50_head_atom *asyh) 153 { 154 asyh->olut.mode = 2; 155 asyh->olut.size = 0; 156 asyh->olut.range = 0; 157 asyh->olut.output_mode = 1; 158 } 159 160 static void 161 headc37d_mode(struct nv50_head *head, struct nv50_head_atom *asyh) 162 { 163 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 164 struct nv50_head_mode *m = &asyh->mode; 165 u32 *push; 166 if ((push = evo_wait(core, 12))) { 167 evo_mthd(push, 0x2064 + (head->base.index * 0x400), 5); 168 evo_data(push, (m->v.active << 16) | m->h.active ); 169 evo_data(push, (m->v.synce << 16) | m->h.synce ); 170 evo_data(push, (m->v.blanke << 16) | m->h.blanke ); 171 evo_data(push, (m->v.blanks << 16) | m->h.blanks ); 172 evo_data(push, (m->v.blank2e << 16) | m->v.blank2s); 173 evo_mthd(push, 0x200c + (head->base.index * 0x400), 1); 174 evo_data(push, m->clock * 1000); 175 evo_mthd(push, 0x2028 + (head->base.index * 0x400), 1); 176 evo_data(push, m->clock * 1000); 177 /*XXX: HEAD_USAGE_BOUNDS, doesn't belong here. */ 178 evo_mthd(push, 0x2030 + (head->base.index * 0x400), 1); 179 evo_data(push, 0x00000124); 180 evo_kick(push, core); 181 } 182 } 183 184 static void 185 headc37d_view(struct nv50_head *head, struct nv50_head_atom *asyh) 186 { 187 struct nv50_dmac *core = &nv50_disp(head->base.base.dev)->core->chan; 188 u32 *push; 189 if ((push = evo_wait(core, 4))) { 190 evo_mthd(push, 0x204c + (head->base.index * 0x400), 1); 191 evo_data(push, (asyh->view.iH << 16) | asyh->view.iW); 192 evo_mthd(push, 0x2058 + (head->base.index * 0x400), 1); 193 evo_data(push, (asyh->view.oH << 16) | asyh->view.oW); 194 evo_kick(push, core); 195 } 196 } 197 198 const struct nv50_head_func 199 headc37d = { 200 .view = headc37d_view, 201 .mode = headc37d_mode, 202 .olut = headc37d_olut, 203 .olut_set = headc37d_olut_set, 204 .olut_clr = headc37d_olut_clr, 205 .curs_layout = head917d_curs_layout, 206 .curs_format = headc37d_curs_format, 207 .curs_set = headc37d_curs_set, 208 .curs_clr = headc37d_curs_clr, 209 .dither = headc37d_dither, 210 .procamp = headc37d_procamp, 211 .or = headc37d_or, 212 }; 213