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