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