static DisplayModePtr fbdev_lcd_output_get_modes(xf86OutputPtr output) { MaliPtr fPtr = MALIPTR(output->scrn); DisplayModePtr mode_ptr; unsigned int hactive_s = fPtr->fb_lcd_var.xres; unsigned int vactive_s = fPtr->fb_lcd_var.yres; mode_ptr = xnfcalloc(1, sizeof(DisplayModeRec)); mode_ptr->HDisplay = hactive_s; mode_ptr->HSyncStart = hactive_s + 20; mode_ptr->HSyncEnd = hactive_s + 40; mode_ptr->HTotal = hactive_s + 80; mode_ptr->VDisplay = vactive_s; mode_ptr->VSyncStart = vactive_s + 20; mode_ptr->VSyncEnd = vactive_s + 40; mode_ptr->VTotal = vactive_s + 80; mode_ptr->VRefresh = 60.0; mode_ptr->Clock = (int) (mode_ptr->VRefresh * mode_ptr->VTotal * mode_ptr->HTotal / 1000.0); mode_ptr->type = M_T_DRIVER; xf86SetModeDefaultName(mode_ptr); mode_ptr->next = NULL; mode_ptr->prev = NULL; return mode_ptr; }
static int fbdev_lcd_output_mode_valid(xf86OutputPtr output, DisplayModePtr pMode) { MaliPtr fPtr = MALIPTR(output->scrn); if( (pMode->HDisplay == (int)fPtr->fb_lcd_var.xres) && (pMode->VDisplay == (int)fPtr->fb_lcd_var.yres) ) return MODE_OK; return MODE_ERROR; }
Bool maliSetupExa(ScreenPtr pScreen, ExaDriverPtr exa) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); if (NULL == exa) { return FALSE; } TRACE_ENTER(); exa->exa_major = 2; exa->exa_minor = 0; exa->memoryBase = fPtr->fbmem; exa->maxX = fPtr->fb_lcd_var.xres_virtual; exa->maxY = fPtr->fb_lcd_var.yres_virtual; exa->flags = EXA_OFFSCREEN_PIXMAPS | EXA_HANDLES_PIXMAPS | EXA_SUPPORTS_PREPARE_AUX; exa->offScreenBase = (fPtr->fb_lcd_fix.line_length * fPtr->fb_lcd_var.yres); exa->memorySize = fPtr->fb_lcd_fix.smem_len; exa->pixmapOffsetAlign = 4096; exa->pixmapPitchAlign = 8; MALI_EXA_FUNC(PrepareSolid); MALI_EXA_FUNC(Solid); MALI_EXA_FUNC(DoneSolid); MALI_EXA_FUNC(PrepareCopy); MALI_EXA_FUNC(Copy); MALI_EXA_FUNC(DoneCopy); MALI_EXA_FUNC(CheckComposite); MALI_EXA_FUNC(PrepareComposite); MALI_EXA_FUNC(Composite); MALI_EXA_FUNC(DoneComposite); MALI_EXA_FUNC(WaitMarker); MALI_EXA_FUNC(CreatePixmap); MALI_EXA_FUNC(DestroyPixmap); MALI_EXA_FUNC(ModifyPixmapHeader); MALI_EXA_FUNC(PixmapIsOffscreen); MALI_EXA_FUNC(PrepareAccess); MALI_EXA_FUNC(FinishAccess); if (UMP_OK != ump_open()) { ERROR_MSG("failed to open UMP subsystem"); TRACE_EXIT(); return FALSE; } INFO_MSG("Mali EXA driver is loaded successfully"); TRACE_EXIT(); return TRUE; }
static void maliFinishAccess(PixmapPtr pPix, int index) { PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPix); mali_mem_info *mem_info; ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); IGNORE(index); if (!privPixmap) { return; } if (!pPix) { return; } mem_info = privPixmap->mem_info; if (!privPixmap->isFrameBuffer) { int secure_id = 0; _lock_item_s item; secure_id = ump_secure_id_get(mem_info->handle); if (secure_id) { item.secure_id = secure_id; item.usage = _LOCK_ACCESS_CPU_WRITE; if (fPtr->fd_umplock > 0) { ioctl(fPtr->fd_umplock, LOCK_IOCTL_RELEASE, &item); } } if (privPixmap->refs == 1) { if (NULL != mem_info) { ump_mapped_pointer_release(mem_info->handle); } } } pPix->devPrivate.ptr = NULL; privPixmap->refs--; }
static void fbdev_lcd_output_dpms(xf86OutputPtr output, int mode) { MaliPtr fPtr = MALIPTR(output->scrn); if ( mode == DPMSModeOn ) { ioctl(fPtr->fb_lcd_fd, FBIOBLANK, FB_BLANK_UNBLANK); } else if( mode == DPMSModeOff ) { ioctl(fPtr->fb_lcd_fd, FBIOBLANK, FB_BLANK_POWERDOWN); } }
static void *maliCreatePixmap(ScreenPtr pScreen, int size, int align) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); PrivPixmap *privPixmap = calloc(1, sizeof(PrivPixmap)); if (NULL == privPixmap) { return NULL; } IGNORE(pScreen); IGNORE(size); IGNORE(align); privPixmap->isFrameBuffer = FALSE; privPixmap->bits_per_pixel = 0; privPixmap->other_buffer = NULL; return privPixmap; }
static Bool maliPrepareAccess(PixmapPtr pPix, int index) { ScreenPtr pScreen = pPix->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPix); mali_mem_info *mem_info; IGNORE(index); if (!privPixmap) { ERROR_MSG("Failed to get private pixmap data"); return FALSE; } mem_info = privPixmap->mem_info; if (NULL != mem_info) { if (privPixmap->refs == 0) { if (privPixmap->isFrameBuffer) { privPixmap->addr = (unsigned long)fPtr->fbmem; } else { privPixmap->addr = (unsigned long)ump_mapped_pointer_get(mem_info->handle); } privPixmap->addr += mem_info->offset; } } else { ERROR_MSG("No mem_info on pixmap"); return FALSE; } pPix->devPrivate.ptr = (void *)(privPixmap->addr); if (NULL == pPix->devPrivate.ptr) { ERROR_MSG("cpu address not set"); return FALSE; } privPixmap->refs++; if (!privPixmap->isFrameBuffer) { int secure_id = 0; _lock_item_s item; secure_id = ump_secure_id_get(mem_info->handle); if (secure_id) { item.secure_id = secure_id; item.usage = _LOCK_ACCESS_CPU_WRITE; if (fPtr->fd_umplock > 0) { ioctl(fPtr->fd_umplock, LOCK_IOCTL_CREATE, &item); if (ioctl(fPtr->fd_umplock, LOCK_IOCTL_PROCESS, &item) < 0) { int max_retries = 5; ERROR_MSG("Unable to process lock item with ID 0x%x - throttling\n", item.secure_id); while ((ioctl(fPtr->fd_umplock, LOCK_IOCTL_PROCESS, &item) < 0) && max_retries) { usleep(2000); max_retries--; } if (max_retries == 0) { ERROR_MSG("Warning: Max retries == 0\n"); } } } if (fPtr->use_cached_ump) { ump_cache_operations_control(UMP_CACHE_OP_START); ump_switch_hw_usage_secure_id(item.secure_id, UMP_USED_BY_CPU); ump_cache_operations_control(UMP_CACHE_OP_FINISH); } } } return TRUE; }
static Bool maliModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData) { unsigned int size; PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPixmap); mali_mem_info *mem_info; ScreenPtr pScreen = pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); if (!pPixmap) { return FALSE; } miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); if ((pPixData == fPtr->fbmem) || current_buf) { /* Wrap one of the fbdev virtual buffers */ ump_secure_id ump_id = UMP_INVALID_SECURE_ID; privPixmap->isFrameBuffer = TRUE; privPixmap->frameBufferNumber = current_buf; mem_info = privPixmap->mem_info; if (mem_info) { return TRUE; } /* create new mem_info for the on-screen buffer */ mem_info = calloc(1, sizeof(*mem_info)); if (!mem_info) { ERROR_MSG("failed to allocate for memory metadata"); return FALSE; } /* get the secure ID for the framebuffers */ if (ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF(current_buf), &ump_id) < 0 || UMP_INVALID_SECURE_ID == ump_id) { free(mem_info); privPixmap->mem_info = NULL; ERROR_MSG("UMP failed to retrieve secure id, current_buf: %d", current_buf); return FALSE; } INFO_MSG("GET_UMP_SECURE_ID_BUF(%d) returned 0x%x", current_buf, ump_id); mem_info->handle = ump_handle_create_from_secure_id(ump_id); if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle) { ERROR_MSG("UMP failed to create handle from secure id"); free(mem_info); privPixmap->mem_info = NULL; return FALSE; } size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height; mem_info->usize = size; privPixmap->mem_info = mem_info; if (bitsPerPixel != 0) { privPixmap->bits_per_pixel = bitsPerPixel; } /* When this is called directly from X to create the front buffer, current_buf is zero as expected. When this * function is called recursively to create the back buffers, current_buf is increased to the next buffer */ privPixmap->mem_info->offset = current_buf * size; if (pPixData == fPtr->fbmem) { /* This is executed only when this function is called directly from X. We need to create the other * back buffers now because we can't "wrap" existing memory in a pixmap during DRI2CreateBuffer * for the back buffer of the framebuffer. In DRI2CreateBuffer instead of allocating a new * pixmap for the back buffer like we do for non-swappable windows, we'll just use the 'current_pixmap' * to grab this pointer from the screen pixmap and return it. */ PrivPixmap *current_privPixmap = privPixmap; int i; PrivBuffer *buf_info = calloc(1, sizeof(*buf_info)); if (NULL == buf_info) { ERROR_MSG("Failed to allocate buf_info memory"); free(mem_info); privPixmap->mem_info = NULL; return FALSE; } buf_info->current_pixmap = 0; buf_info->num_pixmaps = fPtr->dri2_num_buffers; buf_info->pPixmaps[0] = pPixmap; current_privPixmap->buf_info = buf_info; for (i = 1; i < buf_info->num_pixmaps; i++) { current_buf++; buf_info->pPixmaps[i] = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0); assert(buf_info->pPixmaps[i]); current_privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(buf_info->pPixmaps[i]); current_privPixmap->buf_info = buf_info; } current_buf = 0; } INFO_MSG("Creating FRAMEBUFFER pixmap %p at offset %lu, privPixmap=%p", pPixmap, privPixmap->mem_info->offset, privPixmap); return TRUE; } if (pPixData) { /* When this happens we're being told to wrap existing pixmap data for which we don't know the UMP * handle. We can and still need to wrap it but it won't be offscreen - we can't accelerate it in any * way. */ if (privPixmap->mem_info != NULL) { return TRUE; } return FALSE; } pPixmap->devKind = ((pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel) + 7) / 8; pPixmap->devKind = MALI_ALIGN(pPixmap->devKind, 8); size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height; /* allocate pixmap data */ mem_info = privPixmap->mem_info; if (mem_info && mem_info->usize == size) { return TRUE; } if (mem_info && mem_info->usize != 0) { ump_reference_release(mem_info->handle); mem_info->handle = NULL; memset(privPixmap, 0, sizeof(*privPixmap)); return TRUE; } if (!size) { return TRUE; } if (NULL == mem_info) { mem_info = calloc(1, sizeof(*mem_info)); if (!mem_info) { ERROR_MSG("failed to allocate memory metadata"); return FALSE; } } if (fPtr->use_cached_ump) { mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR | UMP_REF_DRV_CONSTRAINT_USE_CACHE); } else { mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR); } if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle) { ERROR_MSG("failed to allocate UMP memory (%i bytes)", size); return FALSE; } mem_info->usize = size; privPixmap->mem_info = mem_info; privPixmap->mem_info->usize = size; privPixmap->bits_per_pixel = 16; return TRUE; }
static void maliCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, int width, int height) { PrivPixmap *srcPrivPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(SrcPixmap); PrivPixmap *dstPrivPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pDstPixmap); IGNORE(pDstPixmap); IGNORE(srcX); IGNORE(srcY); IGNORE(dstX); IGNORE(dstY); IGNORE(width); IGNORE(height); //ERROR_STR("%s: pDstPixmap=%p srcX=%d srcY=%d dstX=%d dstY=%d width=%d height=%d\n", // __FUNCTION__, pDstPixmap, srcX, srcY, dstX, dstY, width, height); ScreenPtr pScreen = SrcPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); struct fb_var_screeninfo var_info; int ret = ioctl(fPtr->fb_lcd_fd, FBIOGET_VSCREENINFO, &var_info); if (ret < 0) { ERROR_STR("FBIOGET_VSCREENINFO failed.\n"); } unsigned char revX = 0; unsigned char revY = 0; if (dstY > srcY) { revY = 1; } if (dstX > srcX) { revX = 1; } //if (srcPrivPixmap->frameBufferNumber != 0) //{ // srcY += (var_info.yres * srcPrivPixmap->frameBufferNumber); //} //if (dstPrivPixmap->frameBufferNumber != 0) //{ // dstY += (var_info.yres * dstPrivPixmap->frameBufferNumber); //} ump_secure_id srcID = ump_secure_id_get(srcPrivPixmap->mem_info->handle); memclient_attach_dmabuf_param_t srcParam; srcParam.handle = srcID; ret = ioctl(memclient_fd, MEMCLIENT_ATTACH_UMP, &srcParam); if (ret < 0) { ERROR_STR("srcParam MEMCLIENT_ATTACH_UMP failed.\n"); } ump_secure_id dstID = ump_secure_id_get(dstPrivPixmap->mem_info->handle); memclient_attach_dmabuf_param_t dstParam; dstParam.handle = dstID; ret = ioctl(memclient_fd, MEMCLIENT_ATTACH_UMP, &dstParam); if (ret < 0) { ERROR_STR("dstParam MEMCLIENT_ATTACH_UMP failed.\n"); } // Configure GE2D struct config_para_ex_s configex; memset(&configex, 0x00, sizeof(configex)); configex.src_para.mem_type = CANVAS_ALLOC; //CANVAS_OSD0 configex.src_para.left = 0; configex.src_para.top = 0; configex.src_para.width = var_info.xres; configex.src_para.height = var_info.yres; configex.src_para.x_rev = revX; configex.src_para.y_rev = revY; configex.src_planes[0].addr = srcParam.physical_address; configex.src_planes[0].w = configex.src_para.width; configex.src_planes[0].h = configex.src_para.height; configex.src_para.format = GE2D_FORMAT_S32_ARGB; // GE2D_FORMAT_S32_BGRA; // GE2D_FMT_S32_RGBA; configex.src2_para.mem_type = CANVAS_TYPE_INVALID; configex.dst_para.mem_type = CANVAS_ALLOC; // CANVAS_OSD0; configex.dst_para.left = 0; configex.dst_para.top = 0; configex.dst_para.width = configex.src_para.width; configex.dst_para.height = configex.src_para.height; configex.dst_para.x_rev = configex.src_para.x_rev; configex.dst_para.y_rev = configex.src_para.y_rev; configex.dst_planes[0].addr = dstParam.physical_address; configex.dst_planes[0].w = configex.dst_para.width; configex.dst_planes[0].h = configex.dst_para.height; configex.dst_para.format = GE2D_FORMAT_S32_ARGB; ret = ioctl(ge2d_fd, GE2D_CONFIG_EX, &configex); if (ret < 0) { ERROR_STR("GE2D_CONFIG_EX failed.\n"); } // Perform the blit operation struct ge2d_para_s blitRect; memset(&blitRect, 0, sizeof(blitRect)); blitRect.src1_rect.x = srcX; blitRect.src1_rect.y = srcY; blitRect.src1_rect.w = width; blitRect.src1_rect.h = height; blitRect.dst_rect.x = dstX; blitRect.dst_rect.y = dstY; if (revY) // && height > 1 { blitRect.src1_rect.y -= 1; } ret = ioctl(ge2d_fd, GE2D_BLIT, &blitRect); if (ret < 0) { ERROR_STR("GE2D_BLIT failed.\n"); } ret = ioctl(memclient_fd, MEMCLIENT_RELEASE_UMP, dstID); if (ret < 0) { ERROR_STR("dstID MEMCLIENT_RELEASE_UMP failed.\n"); } ret = ioctl(memclient_fd, MEMCLIENT_RELEASE_UMP, srcID); if (ret < 0) { ERROR_STR("srcID MEMCLIENT_RELEASE_UMP failed.\n"); } }
static Bool maliModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth, int bitsPerPixel, int devKind, pointer pPixData) { unsigned int size; PrivPixmap *privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(pPixmap); mali_mem_info *mem_info; ScreenPtr pScreen = pPixmap->drawable.pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; MaliPtr fPtr = MALIPTR(pScrn); if (!pPixmap) { return FALSE; } miModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData); if ((pPixData == fPtr->fbmem) || offset) { /* Wrap one of the fbdev virtual buffers */ ump_secure_id ump_id = UMP_INVALID_SECURE_ID; privPixmap->isFrameBuffer = TRUE; mem_info = privPixmap->mem_info; if (mem_info) { return TRUE; } /* create new mem_info for the on-screen buffer */ mem_info = calloc(1, sizeof(*mem_info)); if (!mem_info) { ERROR_MSG("failed to allocate for memory metadata"); return FALSE; } /* get the secure ID for the framebuffers */ if (!offset) { (void)ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF1, &ump_id); ERROR_MSG("GET_UMP_SECURE_ID_BUF1 returned 0x%x offset: %i virt address: %p fb_virt: %p\n", ump_id, offset, pPixData, fPtr->fbmem); } else { (void)ioctl(fPtr->fb_lcd_fd, GET_UMP_SECURE_ID_BUF2, &ump_id); ERROR_MSG("GET_UMP_SECURE_ID_BUF2 returned 0x%x offset: %i virt address: %p fb_virt: %p\n", ump_id, offset, pPixData, fPtr->fbmem); } if (UMP_INVALID_SECURE_ID == ump_id) { free(mem_info); privPixmap->mem_info = NULL; ERROR_MSG("UMP failed to retrieve secure id"); return FALSE; } mem_info->handle = ump_handle_create_from_secure_id(ump_id); if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle) { ERROR_MSG("UMP failed to create handle from secure id"); free(mem_info); privPixmap->mem_info = NULL; return FALSE; } size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height; mem_info->usize = size; privPixmap->mem_info = mem_info; if (bitsPerPixel != 0) { privPixmap->bits_per_pixel = bitsPerPixel; } /* When this is called directly from X to create the front buffer, offset is zero as expected. When this * function is called recursively to create the back buffer, offset is the offset within the fbdev to * the second buffer */ privPixmap->mem_info->offset = offset; /* Only wrap the other half if there is another half! */ if (pPixData == fPtr->fbmem) { /* This is executed only when this function is called directly from X. We need to create the * back buffer now because we can't "wrap" existing memory in a pixmap during DRI2CreateBuffer * for the back buffer of the framebuffer. In DRI2CreateBuffer instead of allocating a new * pixmap for the back buffer like we do for non-swappable windows, we'll just grab this pointer * from the screen pixmap and return it. */ PrivPixmap *other_privPixmap; offset = size; privPixmap->other_buffer = (*pScreen->CreatePixmap)(pScreen, width, height, depth, 0); /* Store a pointer to this pixmap in the one we just created. Both fbdev pixmaps are then * accessible from the screen pixmap, whichever of the fbdev pixmaps happens to be the screen * pixmap at the time */ other_privPixmap = (PrivPixmap *)exaGetPixmapDriverPrivate(privPixmap->other_buffer); other_privPixmap->other_buffer = pPixmap; offset = 0; } INFO_MSG("Creating FRAMEBUFFER pixmap %p at offset %lu, privPixmap=%p\n", pPixmap, privPixmap->mem_info->offset, privPixmap); return TRUE; } if (pPixData) { /* When this happens we're being told to wrap existing pixmap data for which we don't know the UMP * handle. We can and still need to wrap it but it won't be offscreen - we can't accelerate it in any * way. */ if (privPixmap->mem_info != NULL) { return TRUE; } return FALSE; } pPixmap->devKind = ((pPixmap->drawable.width * pPixmap->drawable.bitsPerPixel) + 7) / 8; pPixmap->devKind = MALI_ALIGN(pPixmap->devKind, 8); size = exaGetPixmapPitch(pPixmap) * pPixmap->drawable.height; /* allocate pixmap data */ mem_info = privPixmap->mem_info; if (mem_info && mem_info->usize == size) { return TRUE; } if (mem_info && mem_info->usize != 0) { ump_reference_release(mem_info->handle); mem_info->handle = NULL; memset(privPixmap, 0, sizeof(*privPixmap)); return TRUE; } if (!size) { return TRUE; } if (NULL == mem_info) { mem_info = calloc(1, sizeof(*mem_info)); if (!mem_info) { ERROR_MSG("failed to allocate memory metadata"); return FALSE; } } if (fPtr->use_cached_ump) { mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR | UMP_REF_DRV_CONSTRAINT_USE_CACHE); } else { mem_info->handle = ump_ref_drv_allocate(size, UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR); } if (UMP_INVALID_MEMORY_HANDLE == mem_info->handle) { ERROR_MSG("failed to allocate UMP memory (%i bytes)", size); return FALSE; } mem_info->usize = size; privPixmap->mem_info = mem_info; privPixmap->mem_info->usize = size; privPixmap->bits_per_pixel = 16; return TRUE; }