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