xref: /netbsd-src/sys/arch/evbarm/rpi/vcprop_subr.c (revision f3cfa6f6ce31685c6c4a758bc430e69eb99f50a4)
1 /*	$NetBSD: vcprop_subr.c,v 1.5 2018/01/01 17:03:25 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 <evbarm/rpi/rpi.h>
47 
48 #include <dev/wscons/wsconsio.h>
49 
50 int
51 rpi_fb_set_video(int b)
52 {
53 	int error;
54 	uint32_t res;
55 
56 	/*
57 	 * might as well put it here since we need to re-init it every time
58 	 * and it's not like this is going to be called very often anyway
59 	 */
60 	struct __aligned(16) {
61 		struct vcprop_buffer_hdr	vb_hdr;
62 		struct vcprop_tag_blankscreen	vbt_blank;
63 		struct vcprop_tag end;
64 	} vb_setblank =
65 	{
66 		.vb_hdr = {
67 			.vpb_len = sizeof(vb_setblank),
68 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
69 		},
70 		.vbt_blank = {
71 			.tag = {
72 				.vpt_tag = VCPROPTAG_BLANK_SCREEN,
73 				.vpt_len = VCPROPTAG_LEN(vb_setblank.vbt_blank),
74 				.vpt_rcode = VCPROPTAG_REQUEST,
75 			},
76 			.state = (b != 0) ? VCPROP_BLANK_OFF : VCPROP_BLANK_ON,
77 		},
78 		.end = {
79 			.vpt_tag = VCPROPTAG_NULL,
80 		},
81 	};
82 
83 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank,
84 	    sizeof(vb_setblank), &res);
85 #ifdef RPI_IOCTL_DEBUG
86 	printf("%s: %d %d %d %08x %08x\n", __func__, b,
87 	    vb_setblank.vbt_blank.state, error, res,
88 	    vb_setblank.vbt_blank.tag.vpt_rcode);
89 #endif
90 	if (error)
91 		return error;
92 
93 	if (!vcprop_buffer_success_p(&vb_setblank.vb_hdr) ||
94 	    !vcprop_tag_success_p(&vb_setblank.vbt_blank.tag)) {
95 		return EIO;
96 	}
97 
98 	return 0;
99 }
100 
101 uint32_t
102 rpi_alloc_mem(uint32_t size, uint32_t align, uint32_t flags)
103 {
104 	int error;
105 	uint32_t res;
106 
107 	struct __aligned(16) {
108 		struct vcprop_buffer_hdr	vb_hdr;
109 		struct vcprop_tag_allocmem	vbt_am;
110 		struct vcprop_tag end;
111 	} vb_allocmem =
112 	{
113 		.vb_hdr = {
114 			.vpb_len = sizeof(vb_allocmem),
115 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
116 		},
117 		.vbt_am = {
118 			.tag = {
119 				.vpt_tag = VCPROPTAG_ALLOCMEM,
120 				.vpt_len = VCPROPTAG_LEN(vb_allocmem.vbt_am),
121 				.vpt_rcode = VCPROPTAG_REQUEST,
122 			},
123 			.size = size,
124 			.align = align,
125 			.flags = flags,
126 		},
127 		.end = {
128 			.vpt_tag = VCPROPTAG_NULL,
129 		},
130 	};
131 
132 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_allocmem,
133 	    sizeof(vb_allocmem), &res);
134 #ifdef RPI_IOCTL_DEBUG
135 	printf("%s: %d %d %08x %08x\n", __func__,
136 	    vb_allocmem.vbt_am.size, error, res,
137 	    vb_allocmem.vbt_am.tag.vpt_rcode);
138 #endif
139 	if (error)
140 		return error;
141 
142 	if (!vcprop_buffer_success_p(&vb_allocmem.vb_hdr) ||
143 	    !vcprop_tag_success_p(&vb_allocmem.vbt_am.tag)) {
144 		return EIO;
145 	}
146 
147 	/* Return the handle from the VC */
148 	return vb_allocmem.vbt_am.size;
149 }
150 
151 bus_addr_t
152 rpi_lock_mem(uint32_t handle)
153 {
154 	int error;
155 	uint32_t res;
156 
157 	struct __aligned(16) {
158 		struct vcprop_buffer_hdr	vb_hdr;
159 		struct vcprop_tag_lockmem	vbt_lm;
160 		struct vcprop_tag end;
161 	} vb_lockmem =
162 	{
163 		.vb_hdr = {
164 			.vpb_len = sizeof(vb_lockmem),
165 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
166 		},
167 		.vbt_lm = {
168 			.tag = {
169 				.vpt_tag = VCPROPTAG_LOCKMEM,
170 				.vpt_len = VCPROPTAG_LEN(vb_lockmem.vbt_lm),
171 				.vpt_rcode = VCPROPTAG_REQUEST,
172 			},
173 			.handle = handle,
174 		},
175 		.end = {
176 			.vpt_tag = VCPROPTAG_NULL,
177 		},
178 	};
179 
180 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_lockmem,
181 	    sizeof(vb_lockmem), &res);
182 #ifdef RPI_IOCTL_DEBUG
183 	printf("%s: %d %d %08x %08x\n", __func__,
184 	    vb_lockmem.vbt_lm.handle, error, res,
185 	    vb_lockmem.vbt_lm.tag.vpt_rcode);
186 #endif
187 	if (error)
188 		return 0;
189 
190 	if (!vcprop_buffer_success_p(&vb_lockmem.vb_hdr) ||
191 	    !vcprop_tag_success_p(&vb_lockmem.vbt_lm.tag)) {
192 		return 0;
193 	}
194 
195 	return vb_lockmem.vbt_lm.handle;
196 }
197 
198 int
199 rpi_unlock_mem(uint32_t handle)
200 {
201 	int error;
202 	uint32_t res;
203 
204 	struct __aligned(16) {
205 		struct vcprop_buffer_hdr	vb_hdr;
206 		struct vcprop_tag_lockmem	vbt_lm;
207 		struct vcprop_tag end;
208 	} vb_unlockmem =
209 	{
210 		.vb_hdr = {
211 			.vpb_len = sizeof(vb_unlockmem),
212 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
213 		},
214 		.vbt_lm = {
215 			.tag = {
216 				.vpt_tag = VCPROPTAG_UNLOCKMEM,
217 				.vpt_len = VCPROPTAG_LEN(vb_unlockmem.vbt_lm),
218 				.vpt_rcode = VCPROPTAG_REQUEST,
219 			},
220 			.handle = handle,
221 		},
222 		.end = {
223 			.vpt_tag = VCPROPTAG_NULL,
224 		},
225 	};
226 
227 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_unlockmem,
228 	    sizeof(vb_unlockmem), &res);
229 #ifdef RPI_IOCTL_DEBUG
230 	printf("%s: %d %d %08x %08x\n", __func__,
231 	    vb_unlockmem.vbt_lm.handle, error, res,
232 	    vb_unlockmem.vbt_lm.tag.vpt_rcode);
233 #endif
234 	if (error)
235 		return error;
236 
237 	if (!vcprop_buffer_success_p(&vb_unlockmem.vb_hdr) ||
238 	    !vcprop_tag_success_p(&vb_unlockmem.vbt_lm.tag)) {
239 		return EIO;
240 	}
241 
242 	return 0;
243 }
244 
245 int
246 rpi_release_mem(uint32_t handle)
247 {
248 	int error;
249 	uint32_t res;
250 
251 	struct __aligned(16) {
252 		struct vcprop_buffer_hdr	vb_hdr;
253 		struct vcprop_tag_lockmem	vbt_lm;
254 		struct vcprop_tag end;
255 	} vb_releasemem =
256 	{
257 		.vb_hdr = {
258 			.vpb_len = sizeof(vb_releasemem),
259 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
260 		},
261 		.vbt_lm = {
262 			.tag = {
263 				.vpt_tag = VCPROPTAG_RELEASEMEM,
264 				.vpt_len = VCPROPTAG_LEN(vb_releasemem.vbt_lm),
265 				.vpt_rcode = VCPROPTAG_REQUEST,
266 			},
267 			.handle = handle,
268 		},
269 		.end = {
270 			.vpt_tag = VCPROPTAG_NULL,
271 		},
272 	};
273 
274 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_releasemem,
275 	    sizeof(vb_releasemem), &res);
276 #ifdef RPI_IOCTL_DEBUG
277 	printf("%s: %d %d %08x %08x\n", __func__,
278 	    vb_releasemem.vbt_lm.handle, error, res,
279 	    vb_releasemem.vbt_lm.tag.vpt_rcode);
280 #endif
281 	if (error)
282 		return error;
283 
284 	if (!vcprop_buffer_success_p(&vb_releasemem.vb_hdr) ||
285 	    !vcprop_tag_success_p(&vb_releasemem.vbt_lm.tag)) {
286 		return EIO;
287 	}
288 
289 	return 0;
290 }
291 
292 int
293 rpi_fb_movecursor(int x, int y, int on)
294 {
295 	int error;
296 	uint32_t res;
297 
298 	struct __aligned(16) {
299 		struct vcprop_buffer_hdr	vb_hdr;
300 		struct vcprop_tag_cursorstate	vbt_cs;
301 		struct vcprop_tag end;
302 	} vb_cursorstate =
303 	{
304 		.vb_hdr = {
305 			.vpb_len = sizeof(vb_cursorstate),
306 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
307 		},
308 		.vbt_cs = {
309 			.tag = {
310 				.vpt_tag = VCPROPTAG_SET_CURSOR_STATE,
311 				.vpt_len = VCPROPTAG_LEN(vb_cursorstate.vbt_cs),
312 				.vpt_rcode = VCPROPTAG_REQUEST,
313 			},
314 			.enable = (on != 0) ? 1 : 0,
315 			.x = x,
316 			.y = y,
317 			.flags = 1,
318 		},
319 		.end = {
320 			.vpt_tag = VCPROPTAG_NULL,
321 		},
322 	};
323 
324 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorstate,
325 	    sizeof(vb_cursorstate), &res);
326 #ifdef RPI_IOCTL_DEBUG
327 	printf("%s: %08x %d %08x %08x\n", __func__,
328 	    vb_cursorstate.vbt_cs.enable, error, res,
329 	    vb_cursorstate.vbt_cs.tag.vpt_rcode);
330 #endif
331 	if (error)
332 		return error;
333 
334 	if (!vcprop_buffer_success_p(&vb_cursorstate.vb_hdr) ||
335 	    !vcprop_tag_success_p(&vb_cursorstate.vbt_cs.tag)) {
336 		return EIO;
337 	}
338 
339 	return 0;
340 }
341 
342 int
343 rpi_fb_initcursor(bus_addr_t pixels, int hx, int hy)
344 {
345 	int error;
346 	uint32_t res;
347 
348 
349 	struct __aligned(16) {
350 		struct vcprop_buffer_hdr	vb_hdr;
351 		struct vcprop_tag_cursorinfo	vbt_ci;
352 		struct vcprop_tag end;
353 	} vb_cursorinfo =
354 	{
355 		.vb_hdr = {
356 			.vpb_len = sizeof(vb_cursorinfo),
357 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
358 		},
359 		.vbt_ci = {
360 			.tag = {
361 				.vpt_tag = VCPROPTAG_SET_CURSOR_INFO,
362 				.vpt_len = VCPROPTAG_LEN(vb_cursorinfo.vbt_ci),
363 				.vpt_rcode = VCPROPTAG_REQUEST,
364 			},
365 			.width = 64,
366 			.height = 64,
367 			.format = 0,
368 			.pixels = pixels,
369 			.hotspot_x = hx,
370 			.hotspot_y = hy,
371 		},
372 		.end = {
373 			.vpt_tag = VCPROPTAG_NULL,
374 		},
375 	};
376 
377 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorinfo,
378 	    sizeof(vb_cursorinfo), &res);
379 #ifdef RPI_IOCTL_DEBUG
380 	printf("%s: %d %d %08x %08x\n", __func__,
381 	    vb_cursorinfo.vbt_ci.width, error, res,
382 	    vb_cursorinfo.vbt_ci.tag.vpt_rcode);
383 #endif
384 	if (error)
385 		return error;
386 
387 	if (!vcprop_buffer_success_p(&vb_cursorinfo.vb_hdr) ||
388 	    !vcprop_tag_success_p(&vb_cursorinfo.vbt_ci.tag)) {
389 		return EIO;
390 	}
391 
392 	return 0;
393 }
394