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