xref: /netbsd-src/sys/arch/evbarm/rpi/vcprop_subr.c (revision fd9b697d9c834c84bcd0e32d1c314b466a1cd21a)
1*fd9b697dSmlelstv /*	$NetBSD: vcprop_subr.c,v 1.10 2021/03/08 13:53:08 mlelstv Exp $	*/
2b149c9dcSmacallan 
3b149c9dcSmacallan /*
4b149c9dcSmacallan  * Copyright (c) 2014 Michael Lorenz
5b149c9dcSmacallan  * All rights reserved.
6b149c9dcSmacallan  *
7b149c9dcSmacallan  * Redistribution and use in source and binary forms, with or without
8b149c9dcSmacallan  * modification, are permitted provided that the following conditions
9b149c9dcSmacallan  * are met:
10b149c9dcSmacallan  * 1. Redistributions of source code must retain the above copyright
11b149c9dcSmacallan  *    notice, this list of conditions and the following disclaimer.
12b149c9dcSmacallan  * 2. Redistributions in binary form must reproduce the above copyright
13b149c9dcSmacallan  *    notice, this list of conditions and the following disclaimer in the
14b149c9dcSmacallan  *    documentation and/or other materials provided with the distribution.
15b149c9dcSmacallan  *
16b149c9dcSmacallan  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17b149c9dcSmacallan  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18b149c9dcSmacallan  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19b149c9dcSmacallan  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20b149c9dcSmacallan  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21b149c9dcSmacallan  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22b149c9dcSmacallan  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23b149c9dcSmacallan  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24b149c9dcSmacallan  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25b149c9dcSmacallan  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b149c9dcSmacallan  */
27b149c9dcSmacallan 
28b149c9dcSmacallan /*
29b149c9dcSmacallan  * Mailbox property interface wrapper functions
30b149c9dcSmacallan  */
3194ef4e6aSrin #include <sys/cdefs.h>
32*fd9b697dSmlelstv __KERNEL_RCSID(0, "$NetBSD: vcprop_subr.c,v 1.10 2021/03/08 13:53:08 mlelstv Exp $");
33b149c9dcSmacallan 
34b149c9dcSmacallan #include <sys/param.h>
35b149c9dcSmacallan #include <sys/bus.h>
36e8b0db95Srin #include <sys/device.h>
374a4535adSrin #include <sys/endian.h>
38b149c9dcSmacallan 
39b149c9dcSmacallan #include <uvm/uvm_extern.h>
40b149c9dcSmacallan 
41b149c9dcSmacallan #include <arm/broadcom/bcm2835reg.h>
42b149c9dcSmacallan #include <arm/broadcom/bcm2835var.h>
43b149c9dcSmacallan #include <arm/broadcom/bcm2835_mbox.h>
44b149c9dcSmacallan 
45b149c9dcSmacallan #include <evbarm/rpi/vcio.h>
46b149c9dcSmacallan #include <evbarm/rpi/vcpm.h>
47b149c9dcSmacallan #include <evbarm/rpi/vcprop.h>
48b149c9dcSmacallan 
49b149c9dcSmacallan #include <dev/wscons/wsconsio.h>
50b149c9dcSmacallan 
51b149c9dcSmacallan int
rpi_fb_set_video(int b)52b149c9dcSmacallan rpi_fb_set_video(int b)
53b149c9dcSmacallan {
54b149c9dcSmacallan 	int error;
55b149c9dcSmacallan 	uint32_t res;
56b149c9dcSmacallan 
57b149c9dcSmacallan 	/*
58b149c9dcSmacallan 	 * might as well put it here since we need to re-init it every time
59b149c9dcSmacallan 	 * and it's not like this is going to be called very often anyway
60b149c9dcSmacallan 	 */
61b149c9dcSmacallan 	struct __aligned(16) {
62b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
63b149c9dcSmacallan 		struct vcprop_tag_blankscreen	vbt_blank;
64b149c9dcSmacallan 		struct vcprop_tag end;
65b149c9dcSmacallan 	} vb_setblank =
66b149c9dcSmacallan 	{
67b149c9dcSmacallan 		.vb_hdr = {
684a4535adSrin 			.vpb_len = htole32(sizeof(vb_setblank)),
694a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
70b149c9dcSmacallan 		},
71b149c9dcSmacallan 		.vbt_blank = {
72b149c9dcSmacallan 			.tag = {
734a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_BLANK_SCREEN),
744a4535adSrin 				.vpt_len = htole32(VCPROPTAG_LEN(
754a4535adSrin 				    vb_setblank.vbt_blank)),
764a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
77b149c9dcSmacallan 			},
784a4535adSrin 			.state = htole32((b != 0) ?
794a4535adSrin 			    VCPROP_BLANK_OFF : VCPROP_BLANK_ON),
80b149c9dcSmacallan 		},
81b149c9dcSmacallan 		.end = {
824a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
83b149c9dcSmacallan 		},
84b149c9dcSmacallan 	};
85b149c9dcSmacallan 
86b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setblank,
87b149c9dcSmacallan 	    sizeof(vb_setblank), &res);
88b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
89b149c9dcSmacallan 	printf("%s: %d %d %d %08x %08x\n", __func__, b,
904a4535adSrin 	    le32toh(vb_setblank.vbt_blank.state), error, res,
914a4535adSrin 	    le32toh(vb_setblank.vbt_blank.tag.vpt_rcode));
92b149c9dcSmacallan #endif
93a15ffa77Sskrll 	if (error)
94a15ffa77Sskrll 		return error;
95a15ffa77Sskrll 
96a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_setblank.vb_hdr) ||
97a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_setblank.vbt_blank.tag)) {
98a15ffa77Sskrll 		return EIO;
99a15ffa77Sskrll 	}
100a15ffa77Sskrll 
101a15ffa77Sskrll 	return 0;
102b149c9dcSmacallan }
103b149c9dcSmacallan 
104b149c9dcSmacallan uint32_t
rpi_alloc_mem(uint32_t size,uint32_t align,uint32_t flags)105b149c9dcSmacallan rpi_alloc_mem(uint32_t size, uint32_t align, uint32_t flags)
106b149c9dcSmacallan {
107b149c9dcSmacallan 	int error;
108b149c9dcSmacallan 	uint32_t res;
109b149c9dcSmacallan 
110b149c9dcSmacallan 	struct __aligned(16) {
111b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
112b149c9dcSmacallan 		struct vcprop_tag_allocmem	vbt_am;
113b149c9dcSmacallan 		struct vcprop_tag end;
114b149c9dcSmacallan 	} vb_allocmem =
115b149c9dcSmacallan 	{
116b149c9dcSmacallan 		.vb_hdr = {
1174a4535adSrin 			.vpb_len = htole32(sizeof(vb_allocmem)),
1184a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
119b149c9dcSmacallan 		},
120b149c9dcSmacallan 		.vbt_am = {
121b149c9dcSmacallan 			.tag = {
1224a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_ALLOCMEM),
1234a4535adSrin 				.vpt_len =
1244a4535adSrin 				    htole32(VCPROPTAG_LEN(vb_allocmem.vbt_am)),
1254a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
126b149c9dcSmacallan 			},
1274a4535adSrin 			.size = htole32(size),
1284a4535adSrin 			.align = htole32(align),
1294a4535adSrin 			.flags = htole32(flags),
130b149c9dcSmacallan 		},
131b149c9dcSmacallan 		.end = {
1324a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
133b149c9dcSmacallan 		},
134b149c9dcSmacallan 	};
135b149c9dcSmacallan 
136b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_allocmem,
137b149c9dcSmacallan 	    sizeof(vb_allocmem), &res);
138b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
139b149c9dcSmacallan 	printf("%s: %d %d %08x %08x\n", __func__,
1404a4535adSrin 	    le32toh(vb_allocmem.vbt_am.size), error, res,
1414a4535adSrin 	    le32toh(vb_allocmem.vbt_am.tag.vpt_rcode));
142b149c9dcSmacallan #endif
143a15ffa77Sskrll 	if (error)
144a15ffa77Sskrll 		return error;
145a15ffa77Sskrll 
146a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_allocmem.vb_hdr) ||
147a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_allocmem.vbt_am.tag)) {
148a15ffa77Sskrll 		return EIO;
149a15ffa77Sskrll 	}
150a15ffa77Sskrll 
151a15ffa77Sskrll 	/* Return the handle from the VC */
1524a4535adSrin 	return le32toh(vb_allocmem.vbt_am.size);
153b149c9dcSmacallan }
154b149c9dcSmacallan 
155b149c9dcSmacallan bus_addr_t
rpi_lock_mem(uint32_t handle)156b149c9dcSmacallan rpi_lock_mem(uint32_t handle)
157b149c9dcSmacallan {
158b149c9dcSmacallan 	int error;
159b149c9dcSmacallan 	uint32_t res;
160b149c9dcSmacallan 
161b149c9dcSmacallan 	struct __aligned(16) {
162b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
163b149c9dcSmacallan 		struct vcprop_tag_lockmem	vbt_lm;
164b149c9dcSmacallan 		struct vcprop_tag end;
165b149c9dcSmacallan 	} vb_lockmem =
166b149c9dcSmacallan 	{
167b149c9dcSmacallan 		.vb_hdr = {
1684a4535adSrin 			.vpb_len = htole32(sizeof(vb_lockmem)),
1694a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
170b149c9dcSmacallan 		},
171b149c9dcSmacallan 		.vbt_lm = {
172b149c9dcSmacallan 			.tag = {
1734a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_LOCKMEM),
1744a4535adSrin 				.vpt_len =
1754a4535adSrin 				    htole32(VCPROPTAG_LEN(vb_lockmem.vbt_lm)),
1764a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
177b149c9dcSmacallan 			},
1784a4535adSrin 			.handle = htole32(handle),
179b149c9dcSmacallan 		},
180b149c9dcSmacallan 		.end = {
1814a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
182b149c9dcSmacallan 		},
183b149c9dcSmacallan 	};
184b149c9dcSmacallan 
185b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_lockmem,
186b149c9dcSmacallan 	    sizeof(vb_lockmem), &res);
187b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
188b149c9dcSmacallan 	printf("%s: %d %d %08x %08x\n", __func__,
1894a4535adSrin 	    le32toh(vb_lockmem.vbt_lm.handle), error, res,
1904a4535adSrin 	    le32toh(vb_lockmem.vbt_lm.tag.vpt_rcode));
191b149c9dcSmacallan #endif
192a15ffa77Sskrll 	if (error)
193b149c9dcSmacallan 		return 0;
194a15ffa77Sskrll 
195a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_lockmem.vb_hdr) ||
196a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_lockmem.vbt_lm.tag)) {
197a15ffa77Sskrll 		return 0;
198a15ffa77Sskrll 	}
199a15ffa77Sskrll 
2004a4535adSrin 	return le32toh(vb_lockmem.vbt_lm.handle);
201b149c9dcSmacallan }
202b149c9dcSmacallan 
203b149c9dcSmacallan int
rpi_unlock_mem(uint32_t handle)204b149c9dcSmacallan rpi_unlock_mem(uint32_t handle)
205b149c9dcSmacallan {
206b149c9dcSmacallan 	int error;
207b149c9dcSmacallan 	uint32_t res;
208b149c9dcSmacallan 
209b149c9dcSmacallan 	struct __aligned(16) {
210b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
211b149c9dcSmacallan 		struct vcprop_tag_lockmem	vbt_lm;
212b149c9dcSmacallan 		struct vcprop_tag end;
213b149c9dcSmacallan 	} vb_unlockmem =
214b149c9dcSmacallan 	{
215b149c9dcSmacallan 		.vb_hdr = {
2164a4535adSrin 			.vpb_len = htole32(sizeof(vb_unlockmem)),
2174a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
218b149c9dcSmacallan 		},
219b149c9dcSmacallan 		.vbt_lm = {
220b149c9dcSmacallan 			.tag = {
2214a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_UNLOCKMEM),
2224a4535adSrin 				.vpt_len =
2234a4535adSrin 				    htole32(VCPROPTAG_LEN(vb_unlockmem.vbt_lm)),
2244a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
225b149c9dcSmacallan 			},
2264a4535adSrin 			.handle = htole32(handle),
227b149c9dcSmacallan 		},
228b149c9dcSmacallan 		.end = {
2294a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
230b149c9dcSmacallan 		},
231b149c9dcSmacallan 	};
232b149c9dcSmacallan 
233b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_unlockmem,
234b149c9dcSmacallan 	    sizeof(vb_unlockmem), &res);
235b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
236b149c9dcSmacallan 	printf("%s: %d %d %08x %08x\n", __func__,
2374a4535adSrin 	    le32toh(vb_unlockmem.vbt_lm.handle), error, res,
2384a4535adSrin 	    le32toh(vb_unlockmem.vbt_lm.tag.vpt_rcode));
239b149c9dcSmacallan #endif
240a15ffa77Sskrll 	if (error)
241a15ffa77Sskrll 		return error;
242a15ffa77Sskrll 
243a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_unlockmem.vb_hdr) ||
244a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_unlockmem.vbt_lm.tag)) {
245a15ffa77Sskrll 		return EIO;
246a15ffa77Sskrll 	}
247a15ffa77Sskrll 
248a15ffa77Sskrll 	return 0;
249b149c9dcSmacallan }
250b149c9dcSmacallan 
251b149c9dcSmacallan int
rpi_release_mem(uint32_t handle)252b149c9dcSmacallan rpi_release_mem(uint32_t handle)
253b149c9dcSmacallan {
254b149c9dcSmacallan 	int error;
255b149c9dcSmacallan 	uint32_t res;
256b149c9dcSmacallan 
257b149c9dcSmacallan 	struct __aligned(16) {
258b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
259b149c9dcSmacallan 		struct vcprop_tag_lockmem	vbt_lm;
260b149c9dcSmacallan 		struct vcprop_tag end;
261b149c9dcSmacallan 	} vb_releasemem =
262b149c9dcSmacallan 	{
263b149c9dcSmacallan 		.vb_hdr = {
2644a4535adSrin 			.vpb_len = htole32(sizeof(vb_releasemem)),
2654a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
266b149c9dcSmacallan 		},
267b149c9dcSmacallan 		.vbt_lm = {
268b149c9dcSmacallan 			.tag = {
2694a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_RELEASEMEM),
2704a4535adSrin 				.vpt_len = htole32(VCPROPTAG_LEN(
2714a4535adSrin 				    vb_releasemem.vbt_lm)),
2724a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
273b149c9dcSmacallan 			},
2744a4535adSrin 			.handle = htole32(handle),
275b149c9dcSmacallan 		},
276b149c9dcSmacallan 		.end = {
2774a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
278b149c9dcSmacallan 		},
279b149c9dcSmacallan 	};
280b149c9dcSmacallan 
281b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_releasemem,
282b149c9dcSmacallan 	    sizeof(vb_releasemem), &res);
283b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
284b149c9dcSmacallan 	printf("%s: %d %d %08x %08x\n", __func__,
2854a4535adSrin 	    le32toh(vb_releasemem.vbt_lm.handle), error, res,
2864a4535adSrin 	    le32toh(vb_releasemem.vbt_lm.tag.vpt_rcode));
287b149c9dcSmacallan #endif
288a15ffa77Sskrll 	if (error)
289a15ffa77Sskrll 		return error;
290a15ffa77Sskrll 
291a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_releasemem.vb_hdr) ||
292a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_releasemem.vbt_lm.tag)) {
293a15ffa77Sskrll 		return EIO;
294a15ffa77Sskrll 	}
295a15ffa77Sskrll 
296a15ffa77Sskrll 	return 0;
297b149c9dcSmacallan }
298b149c9dcSmacallan 
299b149c9dcSmacallan int
rpi_fb_movecursor(int x,int y,int on)300b149c9dcSmacallan rpi_fb_movecursor(int x, int y, int on)
301b149c9dcSmacallan {
302b149c9dcSmacallan 	int error;
303b149c9dcSmacallan 	uint32_t res;
304b149c9dcSmacallan 
305b149c9dcSmacallan 	struct __aligned(16) {
306b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
307b149c9dcSmacallan 		struct vcprop_tag_cursorstate	vbt_cs;
308b149c9dcSmacallan 		struct vcprop_tag end;
309b149c9dcSmacallan 	} vb_cursorstate =
310b149c9dcSmacallan 	{
311b149c9dcSmacallan 		.vb_hdr = {
3124a4535adSrin 			.vpb_len = htole32(sizeof(vb_cursorstate)),
3134a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
314b149c9dcSmacallan 		},
315b149c9dcSmacallan 		.vbt_cs = {
316b149c9dcSmacallan 			.tag = {
3174a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_SET_CURSOR_STATE),
3184a4535adSrin 				.vpt_len = htole32(VCPROPTAG_LEN(
3194a4535adSrin 				    vb_cursorstate.vbt_cs)),
3204a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
321b149c9dcSmacallan 			},
3224a4535adSrin 			.enable = htole32((on != 0) ? 1 : 0),
3234a4535adSrin 			.x = htole32(x),
3244a4535adSrin 			.y = htole32(y),
3254a4535adSrin 			.flags = htole32(1),
326b149c9dcSmacallan 		},
327b149c9dcSmacallan 		.end = {
3284a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
329b149c9dcSmacallan 		},
330b149c9dcSmacallan 	};
331b149c9dcSmacallan 
332b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorstate,
333b149c9dcSmacallan 	    sizeof(vb_cursorstate), &res);
334b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
335b149c9dcSmacallan 	printf("%s: %08x %d %08x %08x\n", __func__,
3364a4535adSrin 	    le32toh(vb_cursorstate.vbt_cs.enable), error, res,
3374a4535adSrin 	    le32toh(vb_cursorstate.vbt_cs.tag.vpt_rcode));
338b149c9dcSmacallan #endif
339a15ffa77Sskrll 	if (error)
340a15ffa77Sskrll 		return error;
341a15ffa77Sskrll 
342a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_cursorstate.vb_hdr) ||
343a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_cursorstate.vbt_cs.tag)) {
344a15ffa77Sskrll 		return EIO;
345a15ffa77Sskrll 	}
346a15ffa77Sskrll 
347a15ffa77Sskrll 	return 0;
348b149c9dcSmacallan }
349b149c9dcSmacallan 
350b149c9dcSmacallan int
rpi_fb_initcursor(bus_addr_t pixels,int hx,int hy)351b149c9dcSmacallan rpi_fb_initcursor(bus_addr_t pixels, int hx, int hy)
352b149c9dcSmacallan {
353b149c9dcSmacallan 	int error;
354b149c9dcSmacallan 	uint32_t res;
355b149c9dcSmacallan 
356b149c9dcSmacallan 
357b149c9dcSmacallan 	struct __aligned(16) {
358b149c9dcSmacallan 		struct vcprop_buffer_hdr	vb_hdr;
359b149c9dcSmacallan 		struct vcprop_tag_cursorinfo	vbt_ci;
360b149c9dcSmacallan 		struct vcprop_tag end;
361b149c9dcSmacallan 	} vb_cursorinfo =
362b149c9dcSmacallan 	{
363b149c9dcSmacallan 		.vb_hdr = {
3644a4535adSrin 			.vpb_len = htole32(sizeof(vb_cursorinfo)),
3654a4535adSrin 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
366b149c9dcSmacallan 		},
367b149c9dcSmacallan 		.vbt_ci = {
368b149c9dcSmacallan 			.tag = {
3694a4535adSrin 				.vpt_tag = htole32(VCPROPTAG_SET_CURSOR_INFO),
3704a4535adSrin 				.vpt_len = htole32(VCPROPTAG_LEN(
3714a4535adSrin 				    vb_cursorinfo.vbt_ci)),
3724a4535adSrin 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
373b149c9dcSmacallan 			},
3744a4535adSrin 			.width = htole32(64),
3754a4535adSrin 			.height = htole32(64),
3764a4535adSrin 			.format = htole32(0),
3774a4535adSrin 			.pixels = htole32(pixels),
3784a4535adSrin 			.hotspot_x = htole32(hx),
3794a4535adSrin 			.hotspot_y = htole32(hy),
380b149c9dcSmacallan 		},
381b149c9dcSmacallan 		.end = {
3824a4535adSrin 			.vpt_tag = htole32(VCPROPTAG_NULL),
383b149c9dcSmacallan 		},
384b149c9dcSmacallan 	};
385b149c9dcSmacallan 
386b149c9dcSmacallan 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_cursorinfo,
387b149c9dcSmacallan 	    sizeof(vb_cursorinfo), &res);
388b149c9dcSmacallan #ifdef RPI_IOCTL_DEBUG
389b149c9dcSmacallan 	printf("%s: %d %d %08x %08x\n", __func__,
3904a4535adSrin 	    le32toh(vb_cursorinfo.vbt_ci.width), error, res,
3914a4535adSrin 	    le32toh(vb_cursorinfo.vbt_ci.tag.vpt_rcode));
392b149c9dcSmacallan #endif
393a15ffa77Sskrll 	if (error)
394a15ffa77Sskrll 		return error;
395a15ffa77Sskrll 
396a15ffa77Sskrll 	if (!vcprop_buffer_success_p(&vb_cursorinfo.vb_hdr) ||
397a15ffa77Sskrll 	    !vcprop_tag_success_p(&vb_cursorinfo.vbt_ci.tag)) {
398a15ffa77Sskrll 		return EIO;
399a15ffa77Sskrll 	}
400a15ffa77Sskrll 
401a15ffa77Sskrll 	return 0;
402b149c9dcSmacallan }
403*fd9b697dSmlelstv 
404*fd9b697dSmlelstv int
rpi_fb_get_pixelorder(uint32_t * orderp)405*fd9b697dSmlelstv rpi_fb_get_pixelorder(uint32_t *orderp)
406*fd9b697dSmlelstv {
407*fd9b697dSmlelstv 	int error;
408*fd9b697dSmlelstv 	uint32_t res;
409*fd9b697dSmlelstv 
410*fd9b697dSmlelstv 
411*fd9b697dSmlelstv 	struct __aligned(16) {
412*fd9b697dSmlelstv 		struct vcprop_buffer_hdr	vb_hdr;
413*fd9b697dSmlelstv 		struct vcprop_tag_fbpixelorder	vbt_po;
414*fd9b697dSmlelstv 		struct vcprop_tag end;
415*fd9b697dSmlelstv 	} vb_pixelorder =
416*fd9b697dSmlelstv 	{
417*fd9b697dSmlelstv 		.vb_hdr = {
418*fd9b697dSmlelstv 			.vpb_len = htole32(sizeof(vb_pixelorder)),
419*fd9b697dSmlelstv 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
420*fd9b697dSmlelstv 		},
421*fd9b697dSmlelstv 		.vbt_po = {
422*fd9b697dSmlelstv 			.tag = {
423*fd9b697dSmlelstv 				.vpt_tag = htole32(VCPROPTAG_GET_FB_PIXEL_ORDER),
424*fd9b697dSmlelstv 				.vpt_len = htole32(VCPROPTAG_LEN(
425*fd9b697dSmlelstv 				    vb_pixelorder.vbt_po)),
426*fd9b697dSmlelstv 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
427*fd9b697dSmlelstv 			},
428*fd9b697dSmlelstv 		},
429*fd9b697dSmlelstv 		.end = {
430*fd9b697dSmlelstv 			.vpt_tag = htole32(VCPROPTAG_NULL),
431*fd9b697dSmlelstv 		},
432*fd9b697dSmlelstv 	};
433*fd9b697dSmlelstv 
434*fd9b697dSmlelstv 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_pixelorder,
435*fd9b697dSmlelstv 	    sizeof(vb_pixelorder), &res);
436*fd9b697dSmlelstv #ifdef RPI_IOCTL_DEBUG
437*fd9b697dSmlelstv 	printf("%s: %d %d %08x %08x\n", __func__,
438*fd9b697dSmlelstv 	    le32toh(vb_pixelorder.vbt_po.order), error, res,
439*fd9b697dSmlelstv 	    le32toh(vb_pixelorder.vbt_po.tag.vpt_rcode));
440*fd9b697dSmlelstv #endif
441*fd9b697dSmlelstv 	if (error)
442*fd9b697dSmlelstv 		return error;
443*fd9b697dSmlelstv 
444*fd9b697dSmlelstv 	if (!vcprop_buffer_success_p(&vb_pixelorder.vb_hdr) ||
445*fd9b697dSmlelstv 	    !vcprop_tag_success_p(&vb_pixelorder.vbt_po.tag)) {
446*fd9b697dSmlelstv 		return EIO;
447*fd9b697dSmlelstv 	}
448*fd9b697dSmlelstv 
449*fd9b697dSmlelstv 	*orderp = vb_pixelorder.vbt_po.order;
450*fd9b697dSmlelstv 
451*fd9b697dSmlelstv 	return 0;
452*fd9b697dSmlelstv }
453*fd9b697dSmlelstv 
454*fd9b697dSmlelstv int
rpi_fb_set_pixelorder(uint32_t order)455*fd9b697dSmlelstv rpi_fb_set_pixelorder(uint32_t order)
456*fd9b697dSmlelstv {
457*fd9b697dSmlelstv 	int error;
458*fd9b697dSmlelstv 	uint32_t res;
459*fd9b697dSmlelstv 
460*fd9b697dSmlelstv 
461*fd9b697dSmlelstv 	struct __aligned(16) {
462*fd9b697dSmlelstv 		struct vcprop_buffer_hdr	vb_hdr;
463*fd9b697dSmlelstv 		struct vcprop_tag_fbpixelorder	vbt_po;
464*fd9b697dSmlelstv 		struct vcprop_tag end;
465*fd9b697dSmlelstv 	} vb_pixelorder =
466*fd9b697dSmlelstv 	{
467*fd9b697dSmlelstv 		.vb_hdr = {
468*fd9b697dSmlelstv 			.vpb_len = htole32(sizeof(vb_pixelorder)),
469*fd9b697dSmlelstv 			.vpb_rcode = htole32(VCPROP_PROCESS_REQUEST),
470*fd9b697dSmlelstv 		},
471*fd9b697dSmlelstv 		.vbt_po = {
472*fd9b697dSmlelstv 			.tag = {
473*fd9b697dSmlelstv 				.vpt_tag = htole32(VCPROPTAG_SET_FB_PIXEL_ORDER),
474*fd9b697dSmlelstv 				.vpt_len = htole32(VCPROPTAG_LEN(
475*fd9b697dSmlelstv 				    vb_pixelorder.vbt_po)),
476*fd9b697dSmlelstv 				.vpt_rcode = htole32(VCPROPTAG_REQUEST),
477*fd9b697dSmlelstv 			},
478*fd9b697dSmlelstv 			.order = order
479*fd9b697dSmlelstv 		},
480*fd9b697dSmlelstv 		.end = {
481*fd9b697dSmlelstv 			.vpt_tag = htole32(VCPROPTAG_NULL),
482*fd9b697dSmlelstv 		},
483*fd9b697dSmlelstv 	};
484*fd9b697dSmlelstv 
485*fd9b697dSmlelstv 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_pixelorder,
486*fd9b697dSmlelstv 	    sizeof(vb_pixelorder), &res);
487*fd9b697dSmlelstv #ifdef RPI_IOCTL_DEBUG
488*fd9b697dSmlelstv 	printf("%s: %d %d %08x %08x\n", __func__,
489*fd9b697dSmlelstv 	    le32toh(vb_pixelorder.vbt_po.order), error, res,
490*fd9b697dSmlelstv 	    le32toh(vb_pixelorder.vbt_po.tag.vpt_rcode));
491*fd9b697dSmlelstv #endif
492*fd9b697dSmlelstv 	if (error)
493*fd9b697dSmlelstv 		return error;
494*fd9b697dSmlelstv 
495*fd9b697dSmlelstv 	if (!vcprop_buffer_success_p(&vb_pixelorder.vb_hdr) ||
496*fd9b697dSmlelstv 	    !vcprop_tag_success_p(&vb_pixelorder.vbt_po.tag)) {
497*fd9b697dSmlelstv 		return EIO;
498*fd9b697dSmlelstv 	}
499*fd9b697dSmlelstv 
500*fd9b697dSmlelstv 	return 0;
501*fd9b697dSmlelstv }
502*fd9b697dSmlelstv 
503*fd9b697dSmlelstv int
rpi_set_domain(uint32_t domain,uint32_t state)504*fd9b697dSmlelstv rpi_set_domain(uint32_t domain, uint32_t state)
505*fd9b697dSmlelstv {
506*fd9b697dSmlelstv 	int error;
507*fd9b697dSmlelstv 	uint32_t tag, res;
508*fd9b697dSmlelstv 
509*fd9b697dSmlelstv 	tag = VCPROPTAG_SET_DOMAIN_STATE;
510*fd9b697dSmlelstv 	if (domain == VCPROP_DOMAIN_USB) {
511*fd9b697dSmlelstv 		/* use old interface */
512*fd9b697dSmlelstv 		tag = VCPROPTAG_SET_POWERSTATE;
513*fd9b697dSmlelstv 		domain = VCPROP_POWER_USB;
514*fd9b697dSmlelstv 	}
515*fd9b697dSmlelstv 
516*fd9b697dSmlelstv 	/*
517*fd9b697dSmlelstv 	 * might as well put it here since we need to re-init it every time
518*fd9b697dSmlelstv 	 * and it's not like this is going to be called very often anyway
519*fd9b697dSmlelstv 	 */
520*fd9b697dSmlelstv 	struct __aligned(16) {
521*fd9b697dSmlelstv 		struct vcprop_buffer_hdr	vb_hdr;
522*fd9b697dSmlelstv 		struct vcprop_tag_powerstate	vbt_power;
523*fd9b697dSmlelstv 		struct vcprop_tag end;
524*fd9b697dSmlelstv 	} vb_setpower =
525*fd9b697dSmlelstv 	{
526*fd9b697dSmlelstv 		.vb_hdr = {
527*fd9b697dSmlelstv 			.vpb_len = sizeof(vb_setpower),
528*fd9b697dSmlelstv 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
529*fd9b697dSmlelstv 		},
530*fd9b697dSmlelstv 		.vbt_power = {
531*fd9b697dSmlelstv 			.tag = {
532*fd9b697dSmlelstv 				.vpt_tag = tag,
533*fd9b697dSmlelstv 				.vpt_len = VCPROPTAG_LEN(vb_setpower.vbt_power),
534*fd9b697dSmlelstv 				.vpt_rcode = VCPROPTAG_REQUEST,
535*fd9b697dSmlelstv 			},
536*fd9b697dSmlelstv 			.id = domain,
537*fd9b697dSmlelstv 			.state = state
538*fd9b697dSmlelstv 		},
539*fd9b697dSmlelstv 		.end = {
540*fd9b697dSmlelstv 			.vpt_tag = VCPROPTAG_NULL,
541*fd9b697dSmlelstv 		},
542*fd9b697dSmlelstv 	};
543*fd9b697dSmlelstv 
544*fd9b697dSmlelstv 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setpower,
545*fd9b697dSmlelstv 	    sizeof(vb_setpower), &res);
546*fd9b697dSmlelstv #ifdef RPI_IOCTL_DEBUG
547*fd9b697dSmlelstv 	printf("%s: %08x %08x %d %08x %08x %d %d %08x %08x\n", __func__,
548*fd9b697dSmlelstv 	    tag, domain, state,
549*fd9b697dSmlelstv 	    vb_setpower.vbt_power.tag.vpt_tag,
550*fd9b697dSmlelstv 	    vb_setpower.vbt_power.id,
551*fd9b697dSmlelstv 	    vb_setpower.vbt_power.state,
552*fd9b697dSmlelstv 	    error, res,
553*fd9b697dSmlelstv 	    vb_setpower.vbt_power.tag.vpt_rcode);
554*fd9b697dSmlelstv #endif
555*fd9b697dSmlelstv 	if (error)
556*fd9b697dSmlelstv 		return error;
557*fd9b697dSmlelstv 
558*fd9b697dSmlelstv 	if (!vcprop_buffer_success_p(&vb_setpower.vb_hdr) ||
559*fd9b697dSmlelstv 	    !vcprop_tag_success_p(&vb_setpower.vbt_power.tag)) {
560*fd9b697dSmlelstv 		return EIO;
561*fd9b697dSmlelstv 	}
562*fd9b697dSmlelstv 
563*fd9b697dSmlelstv 	return 0;
564*fd9b697dSmlelstv }
565*fd9b697dSmlelstv 
566*fd9b697dSmlelstv int
rpi_get_domain(uint32_t domain,uint32_t * statep)567*fd9b697dSmlelstv rpi_get_domain(uint32_t domain, uint32_t *statep)
568*fd9b697dSmlelstv {
569*fd9b697dSmlelstv 	int error;
570*fd9b697dSmlelstv 	uint32_t tag, res;
571*fd9b697dSmlelstv 
572*fd9b697dSmlelstv 	tag = VCPROPTAG_GET_DOMAIN_STATE;
573*fd9b697dSmlelstv 	if (domain == VCPROP_DOMAIN_USB) {
574*fd9b697dSmlelstv 		/* use old interface */
575*fd9b697dSmlelstv 		tag = VCPROPTAG_GET_POWERSTATE;
576*fd9b697dSmlelstv 		domain = VCPROP_POWER_USB;
577*fd9b697dSmlelstv 	}
578*fd9b697dSmlelstv 
579*fd9b697dSmlelstv 	/*
580*fd9b697dSmlelstv 	 * might as well put it here since we need to re-init it every time
581*fd9b697dSmlelstv 	 * and it's not like this is going to be called very often anyway
582*fd9b697dSmlelstv 	 */
583*fd9b697dSmlelstv 	struct __aligned(16) {
584*fd9b697dSmlelstv 		struct vcprop_buffer_hdr	vb_hdr;
585*fd9b697dSmlelstv 		struct vcprop_tag_powerstate	vbt_power;
586*fd9b697dSmlelstv 		struct vcprop_tag end;
587*fd9b697dSmlelstv 	} vb_setpower =
588*fd9b697dSmlelstv 	{
589*fd9b697dSmlelstv 		.vb_hdr = {
590*fd9b697dSmlelstv 			.vpb_len = sizeof(vb_setpower),
591*fd9b697dSmlelstv 			.vpb_rcode = VCPROP_PROCESS_REQUEST,
592*fd9b697dSmlelstv 		},
593*fd9b697dSmlelstv 		.vbt_power = {
594*fd9b697dSmlelstv 			.tag = {
595*fd9b697dSmlelstv 				.vpt_tag = tag,
596*fd9b697dSmlelstv 				.vpt_len = VCPROPTAG_LEN(vb_setpower.vbt_power),
597*fd9b697dSmlelstv 				.vpt_rcode = VCPROPTAG_REQUEST,
598*fd9b697dSmlelstv 			},
599*fd9b697dSmlelstv 			.id = domain,
600*fd9b697dSmlelstv 			.state = ~0
601*fd9b697dSmlelstv 		},
602*fd9b697dSmlelstv 		.end = {
603*fd9b697dSmlelstv 			.vpt_tag = VCPROPTAG_NULL,
604*fd9b697dSmlelstv 		},
605*fd9b697dSmlelstv 	};
606*fd9b697dSmlelstv 
607*fd9b697dSmlelstv 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb_setpower,
608*fd9b697dSmlelstv 	    sizeof(vb_setpower), &res);
609*fd9b697dSmlelstv #ifdef RPI_IOCTL_DEBUG
610*fd9b697dSmlelstv 	printf("%s: %08x %08x %d %08x %08x %d %d %08x %08x\n", __func__,
611*fd9b697dSmlelstv 	    tag, domain, *statep,
612*fd9b697dSmlelstv 	    vb_setpower.vbt_power.tag.vpt_tag,
613*fd9b697dSmlelstv 	    vb_setpower.vbt_power.id,
614*fd9b697dSmlelstv 	    vb_setpower.vbt_power.state,
615*fd9b697dSmlelstv 	    error, res,
616*fd9b697dSmlelstv 	    vb_setpower.vbt_power.tag.vpt_rcode);
617*fd9b697dSmlelstv #endif
618*fd9b697dSmlelstv 	if (error)
619*fd9b697dSmlelstv 		return error;
620*fd9b697dSmlelstv 
621*fd9b697dSmlelstv 	if (!vcprop_buffer_success_p(&vb_setpower.vb_hdr) ||
622*fd9b697dSmlelstv 	    !vcprop_tag_success_p(&vb_setpower.vbt_power.tag)) {
623*fd9b697dSmlelstv 		return EIO;
624*fd9b697dSmlelstv 	}
625*fd9b697dSmlelstv 
626*fd9b697dSmlelstv 	*statep = vb_setpower.vbt_power.state;
627*fd9b697dSmlelstv 
628*fd9b697dSmlelstv 	return 0;
629*fd9b697dSmlelstv }
630*fd9b697dSmlelstv 
631*fd9b697dSmlelstv int
rpi_vchiq_init(uint32_t * channelbasep)632*fd9b697dSmlelstv rpi_vchiq_init(uint32_t *channelbasep)
633*fd9b697dSmlelstv {
634*fd9b697dSmlelstv 	int error;
635*fd9b697dSmlelstv 	uint32_t tag, res;
636*fd9b697dSmlelstv 	struct __aligned(16) {
637*fd9b697dSmlelstv 		struct vcprop_buffer_hdr	vb_hdr;
638*fd9b697dSmlelstv 		struct vcprop_tag_vchiqinit	vbt_vchiq;
639*fd9b697dSmlelstv 		struct vcprop_tag end;
640*fd9b697dSmlelstv 	} vb;
641*fd9b697dSmlelstv 
642*fd9b697dSmlelstv 	tag = VCPROPTAG_VCHIQ_INIT;
643*fd9b697dSmlelstv 
644*fd9b697dSmlelstv 	VCPROP_INIT_REQUEST(vb);
645*fd9b697dSmlelstv 	VCPROP_INIT_TAG(vb.vbt_vchiq, tag);
646*fd9b697dSmlelstv 	vb.vbt_vchiq.base = *channelbasep;
647*fd9b697dSmlelstv 
648*fd9b697dSmlelstv 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb, sizeof(vb), &res);
649*fd9b697dSmlelstv 	if (error)
650*fd9b697dSmlelstv 		return error;
651*fd9b697dSmlelstv 
652*fd9b697dSmlelstv 	if (!vcprop_buffer_success_p(&vb.vb_hdr) ||
653*fd9b697dSmlelstv 	    !vcprop_tag_success_p(&vb.vbt_vchiq.tag)) {
654*fd9b697dSmlelstv 		return EIO;
655*fd9b697dSmlelstv 	}
656*fd9b697dSmlelstv 	*channelbasep = vb.vbt_vchiq.base;
657*fd9b697dSmlelstv 
658*fd9b697dSmlelstv 	return 0;
659*fd9b697dSmlelstv }
660*fd9b697dSmlelstv 
661*fd9b697dSmlelstv int
rpi_notify_xhci_reset(uint32_t address)662*fd9b697dSmlelstv rpi_notify_xhci_reset(uint32_t address)
663*fd9b697dSmlelstv {
664*fd9b697dSmlelstv 	int error;
665*fd9b697dSmlelstv 	uint32_t tag, res;
666*fd9b697dSmlelstv 	struct __aligned(16) {
667*fd9b697dSmlelstv 		struct vcprop_buffer_hdr	vb_hdr;
668*fd9b697dSmlelstv 		struct vcprop_tag_notifyxhcireset	vbt_nhr;
669*fd9b697dSmlelstv 		struct vcprop_tag end;
670*fd9b697dSmlelstv 	} vb;
671*fd9b697dSmlelstv 
672*fd9b697dSmlelstv 	tag = VCPROPTAG_NOTIFY_XHCI_RESET;
673*fd9b697dSmlelstv 
674*fd9b697dSmlelstv 	VCPROP_INIT_REQUEST(vb);
675*fd9b697dSmlelstv 	VCPROP_INIT_TAG(vb.vbt_nhr, tag);
676*fd9b697dSmlelstv 	vb.vbt_nhr.deviceaddress = address;
677*fd9b697dSmlelstv 
678*fd9b697dSmlelstv 	error = bcmmbox_request(BCMMBOX_CHANARM2VC, &vb, sizeof(vb), &res);
679*fd9b697dSmlelstv 	if (error)
680*fd9b697dSmlelstv 		return error;
681*fd9b697dSmlelstv 
682*fd9b697dSmlelstv 	if (!vcprop_buffer_success_p(&vb.vb_hdr) ||
683*fd9b697dSmlelstv 	    !vcprop_tag_success_p(&vb.vbt_nhr.tag)) {
684*fd9b697dSmlelstv 		return EIO;
685*fd9b697dSmlelstv 	}
686*fd9b697dSmlelstv 
687*fd9b697dSmlelstv 	return 0;
688*fd9b697dSmlelstv }
689*fd9b697dSmlelstv 
690