xref: /netbsd-src/sys/arch/evbarm/rpi/vcprop_subr.c (revision 154bfe8e089c1a0a4e9ed8414f08d3da90949162)
1 /*	$NetBSD: vcprop_subr.c,v 1.6 2020/07/04 15:14:56 skrll 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/device.h>
34 #include <sys/bus.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