vcprop_subr.c revision 1.7 1 /* $NetBSD: vcprop_subr.c,v 1.7 2020/11/23 06:29:54 rin Exp $ */
2
3 /*
4 * Copyright (c) 2014 Michael Lorenz
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 /*
29 * Mailbox property interface wrapper functions
30 */
31
32 #include <sys/param.h>
33 #include <sys/bus.h>
34 #include <sys/device.h>
35
36 #include <uvm/uvm_extern.h>
37
38 #include <arm/broadcom/bcm2835reg.h>
39 #include <arm/broadcom/bcm2835var.h>
40 #include <arm/broadcom/bcm2835_mbox.h>
41
42 #include <evbarm/rpi/vcio.h>
43 #include <evbarm/rpi/vcpm.h>
44 #include <evbarm/rpi/vcprop.h>
45
46 #include <dev/wscons/wsconsio.h>
47
48 int
49 rpi_fb_set_video(int b)
50 {
51 int error;
52 uint32_t res;
53
54 /*
55 * might as well put it here since we need to re-init it every time
56 * and it's not like this is going to be called very often anyway
57 */
58 struct __aligned(16) {
59 struct vcprop_buffer_hdr vb_hdr;
60 struct vcprop_tag_blankscreen vbt_blank;
61 struct vcprop_tag end;
62 } vb_setblank =
63 {
64 .vb_hdr = {
65 .vpb_len = sizeof(vb_setblank),
66 .vpb_rcode = VCPROP_PROCESS_REQUEST,
67 },
68 .vbt_blank = {
69 .tag = {
70 .vpt_tag = VCPROPTAG_BLANK_SCREEN,
71 .vpt_len = VCPROPTAG_LEN(vb_setblank.vbt_blank),
72 .vpt_rcode = VCPROPTAG_REQUEST,
73 },
74 .state = (b != 0) ? VCPROP_BLANK_OFF : VCPROP_BLANK_ON,
75 },
76 .end = {
77 .vpt_tag = VCPROPTAG_NULL,
78 },
79 };
80
81 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank,
82 sizeof(vb_setblank), &res);
83 #ifdef RPI_IOCTL_DEBUG
84 printf("%s: %d %d %d %08x %08x\n", __func__, b,
85 vb_setblank.vbt_blank.state, error, res,
86 vb_setblank.vbt_blank.tag.vpt_rcode);
87 #endif
88 if (error)
89 return error;
90
91 if (!vcprop_buffer_success_p(&vb_setblank.vb_hdr) ||
92 !vcprop_tag_success_p(&vb_setblank.vbt_blank.tag)) {
93 return EIO;
94 }
95
96 return 0;
97 }
98
99 uint32_t
100 rpi_alloc_mem(uint32_t size, uint32_t align, uint32_t flags)
101 {
102 int error;
103 uint32_t res;
104
105 struct __aligned(16) {
106 struct vcprop_buffer_hdr vb_hdr;
107 struct vcprop_tag_allocmem vbt_am;
108 struct vcprop_tag end;
109 } vb_allocmem =
110 {
111 .vb_hdr = {
112 .vpb_len = sizeof(vb_allocmem),
113 .vpb_rcode = VCPROP_PROCESS_REQUEST,
114 },
115 .vbt_am = {
116 .tag = {
117 .vpt_tag = VCPROPTAG_ALLOCMEM,
118 .vpt_len = VCPROPTAG_LEN(vb_allocmem.vbt_am),
119 .vpt_rcode = VCPROPTAG_REQUEST,
120 },
121 .size = size,
122 .align = align,
123 .flags = flags,
124 },
125 .end = {
126 .vpt_tag = VCPROPTAG_NULL,
127 },
128 };
129
130 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_allocmem,
131 sizeof(vb_allocmem), &res);
132 #ifdef RPI_IOCTL_DEBUG
133 printf("%s: %d %d %08x %08x\n", __func__,
134 vb_allocmem.vbt_am.size, error, res,
135 vb_allocmem.vbt_am.tag.vpt_rcode);
136 #endif
137 if (error)
138 return error;
139
140 if (!vcprop_buffer_success_p(&vb_allocmem.vb_hdr) ||
141 !vcprop_tag_success_p(&vb_allocmem.vbt_am.tag)) {
142 return EIO;
143 }
144
145 /* Return the handle from the VC */
146 return vb_allocmem.vbt_am.size;
147 }
148
149 bus_addr_t
150 rpi_lock_mem(uint32_t handle)
151 {
152 int error;
153 uint32_t res;
154
155 struct __aligned(16) {
156 struct vcprop_buffer_hdr vb_hdr;
157 struct vcprop_tag_lockmem vbt_lm;
158 struct vcprop_tag end;
159 } vb_lockmem =
160 {
161 .vb_hdr = {
162 .vpb_len = sizeof(vb_lockmem),
163 .vpb_rcode = VCPROP_PROCESS_REQUEST,
164 },
165 .vbt_lm = {
166 .tag = {
167 .vpt_tag = VCPROPTAG_LOCKMEM,
168 .vpt_len = VCPROPTAG_LEN(vb_lockmem.vbt_lm),
169 .vpt_rcode = VCPROPTAG_REQUEST,
170 },
171 .handle = handle,
172 },
173 .end = {
174 .vpt_tag = VCPROPTAG_NULL,
175 },
176 };
177
178 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_lockmem,
179 sizeof(vb_lockmem), &res);
180 #ifdef RPI_IOCTL_DEBUG
181 printf("%s: %d %d %08x %08x\n", __func__,
182 vb_lockmem.vbt_lm.handle, error, res,
183 vb_lockmem.vbt_lm.tag.vpt_rcode);
184 #endif
185 if (error)
186 return 0;
187
188 if (!vcprop_buffer_success_p(&vb_lockmem.vb_hdr) ||
189 !vcprop_tag_success_p(&vb_lockmem.vbt_lm.tag)) {
190 return 0;
191 }
192
193 return vb_lockmem.vbt_lm.handle;
194 }
195
196 int
197 rpi_unlock_mem(uint32_t handle)
198 {
199 int error;
200 uint32_t res;
201
202 struct __aligned(16) {
203 struct vcprop_buffer_hdr vb_hdr;
204 struct vcprop_tag_lockmem vbt_lm;
205 struct vcprop_tag end;
206 } vb_unlockmem =
207 {
208 .vb_hdr = {
209 .vpb_len = sizeof(vb_unlockmem),
210 .vpb_rcode = VCPROP_PROCESS_REQUEST,
211 },
212 .vbt_lm = {
213 .tag = {
214 .vpt_tag = VCPROPTAG_UNLOCKMEM,
215 .vpt_len = VCPROPTAG_LEN(vb_unlockmem.vbt_lm),
216 .vpt_rcode = VCPROPTAG_REQUEST,
217 },
218 .handle = handle,
219 },
220 .end = {
221 .vpt_tag = VCPROPTAG_NULL,
222 },
223 };
224
225 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_unlockmem,
226 sizeof(vb_unlockmem), &res);
227 #ifdef RPI_IOCTL_DEBUG
228 printf("%s: %d %d %08x %08x\n", __func__,
229 vb_unlockmem.vbt_lm.handle, error, res,
230 vb_unlockmem.vbt_lm.tag.vpt_rcode);
231 #endif
232 if (error)
233 return error;
234
235 if (!vcprop_buffer_success_p(&vb_unlockmem.vb_hdr) ||
236 !vcprop_tag_success_p(&vb_unlockmem.vbt_lm.tag)) {
237 return EIO;
238 }
239
240 return 0;
241 }
242
243 int
244 rpi_release_mem(uint32_t handle)
245 {
246 int error;
247 uint32_t res;
248
249 struct __aligned(16) {
250 struct vcprop_buffer_hdr vb_hdr;
251 struct vcprop_tag_lockmem vbt_lm;
252 struct vcprop_tag end;
253 } vb_releasemem =
254 {
255 .vb_hdr = {
256 .vpb_len = sizeof(vb_releasemem),
257 .vpb_rcode = VCPROP_PROCESS_REQUEST,
258 },
259 .vbt_lm = {
260 .tag = {
261 .vpt_tag = VCPROPTAG_RELEASEMEM,
262 .vpt_len = VCPROPTAG_LEN(vb_releasemem.vbt_lm),
263 .vpt_rcode = VCPROPTAG_REQUEST,
264 },
265 .handle = handle,
266 },
267 .end = {
268 .vpt_tag = VCPROPTAG_NULL,
269 },
270 };
271
272 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_releasemem,
273 sizeof(vb_releasemem), &res);
274 #ifdef RPI_IOCTL_DEBUG
275 printf("%s: %d %d %08x %08x\n", __func__,
276 vb_releasemem.vbt_lm.handle, error, res,
277 vb_releasemem.vbt_lm.tag.vpt_rcode);
278 #endif
279 if (error)
280 return error;
281
282 if (!vcprop_buffer_success_p(&vb_releasemem.vb_hdr) ||
283 !vcprop_tag_success_p(&vb_releasemem.vbt_lm.tag)) {
284 return EIO;
285 }
286
287 return 0;
288 }
289
290 int
291 rpi_fb_movecursor(int x, int y, int on)
292 {
293 int error;
294 uint32_t res;
295
296 struct __aligned(16) {
297 struct vcprop_buffer_hdr vb_hdr;
298 struct vcprop_tag_cursorstate vbt_cs;
299 struct vcprop_tag end;
300 } vb_cursorstate =
301 {
302 .vb_hdr = {
303 .vpb_len = sizeof(vb_cursorstate),
304 .vpb_rcode = VCPROP_PROCESS_REQUEST,
305 },
306 .vbt_cs = {
307 .tag = {
308 .vpt_tag = VCPROPTAG_SET_CURSOR_STATE,
309 .vpt_len = VCPROPTAG_LEN(vb_cursorstate.vbt_cs),
310 .vpt_rcode = VCPROPTAG_REQUEST,
311 },
312 .enable = (on != 0) ? 1 : 0,
313 .x = x,
314 .y = y,
315 .flags = 1,
316 },
317 .end = {
318 .vpt_tag = VCPROPTAG_NULL,
319 },
320 };
321
322 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorstate,
323 sizeof(vb_cursorstate), &res);
324 #ifdef RPI_IOCTL_DEBUG
325 printf("%s: %08x %d %08x %08x\n", __func__,
326 vb_cursorstate.vbt_cs.enable, error, res,
327 vb_cursorstate.vbt_cs.tag.vpt_rcode);
328 #endif
329 if (error)
330 return error;
331
332 if (!vcprop_buffer_success_p(&vb_cursorstate.vb_hdr) ||
333 !vcprop_tag_success_p(&vb_cursorstate.vbt_cs.tag)) {
334 return EIO;
335 }
336
337 return 0;
338 }
339
340 int
341 rpi_fb_initcursor(bus_addr_t pixels, int hx, int hy)
342 {
343 int error;
344 uint32_t res;
345
346
347 struct __aligned(16) {
348 struct vcprop_buffer_hdr vb_hdr;
349 struct vcprop_tag_cursorinfo vbt_ci;
350 struct vcprop_tag end;
351 } vb_cursorinfo =
352 {
353 .vb_hdr = {
354 .vpb_len = sizeof(vb_cursorinfo),
355 .vpb_rcode = VCPROP_PROCESS_REQUEST,
356 },
357 .vbt_ci = {
358 .tag = {
359 .vpt_tag = VCPROPTAG_SET_CURSOR_INFO,
360 .vpt_len = VCPROPTAG_LEN(vb_cursorinfo.vbt_ci),
361 .vpt_rcode = VCPROPTAG_REQUEST,
362 },
363 .width = 64,
364 .height = 64,
365 .format = 0,
366 .pixels = pixels,
367 .hotspot_x = hx,
368 .hotspot_y = hy,
369 },
370 .end = {
371 .vpt_tag = VCPROPTAG_NULL,
372 },
373 };
374
375 error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorinfo,
376 sizeof(vb_cursorinfo), &res);
377 #ifdef RPI_IOCTL_DEBUG
378 printf("%s: %d %d %08x %08x\n", __func__,
379 vb_cursorinfo.vbt_ci.width, error, res,
380 vb_cursorinfo.vbt_ci.tag.vpt_rcode);
381 #endif
382 if (error)
383 return error;
384
385 if (!vcprop_buffer_success_p(&vb_cursorinfo.vb_hdr) ||
386 !vcprop_tag_success_p(&vb_cursorinfo.vbt_ci.tag)) {
387 return EIO;
388 }
389
390 return 0;
391 }
392