DFBResult uc_ovl_set_adjustment(CoreLayer *layer, void *driver_data, void *layer_data, DFBColorAdjustment *adj) { UcOverlayData* ucovl = (UcOverlayData*) layer_data; UcDriverData* ucdrv = (UcDriverData*) driver_data; DFBColorAdjustment* ucadj; u32 a1, a2; ucadj = &ucovl->v1.adj; if (adj->flags & DCAF_BRIGHTNESS) ucadj->brightness = adj->brightness; if (adj->flags & DCAF_CONTRAST) ucadj->contrast = adj->contrast; if (adj->flags & DCAF_HUE) ucadj->hue = adj->hue; if (adj->flags & DCAF_SATURATION) ucadj->saturation = adj->saturation; uc_ovl_map_adjustment(ucadj, &a1, &a2); VIDEO_OUT(ucdrv->hwregs, V1_ColorSpaceReg_1, a1); VIDEO_OUT(ucdrv->hwregs, V1_ColorSpaceReg_2, a2); return DFB_OK; }
static DFBResult uc_ovl_set_level(CoreLayer *layer, void *driver_data, void *layer_data, int level) { UcOverlayData* ucovl = (UcOverlayData*) layer_data; UcDriverData* ucdrv = (UcDriverData*) driver_data; if (level == 0) return DFB_INVARG; if (level < 0) { // Enable underlay mode. VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucovl->opacity_primary)); } else { // Enable overlay mode (default) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucovl->v1.opacity)); } VIDEO_OUT(ucdrv->hwregs, V_COMPOSE_MODE, V1_COMMAND_FIRE | (ucovl->v1.dstkey_enabled ? ENABLE_COLOR_KEYING : 0)); ucovl->v1.level = level; return DFB_OK; }
static void uc_spic_set_buffer( volatile u8 *hwregs, CoreSurfaceBufferLock *lock ) { if (lock) { VIDEO_OUT(hwregs, SUBP_STARTADDR, lock->offset); VIDEO_OUT(hwregs, SUBP_CONTROL_STRIDE, (VIDEO_IN(hwregs, SUBP_CONTROL_STRIDE) & ~SUBP_STRIDE_MASK) | (lock->pitch & SUBP_STRIDE_MASK) | SUBP_AI44 ); } }
static DFBResult osdSetRegion( CoreLayer *layer, void *driver_data, void *layer_data, void *region_data, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags updated, CoreSurface *surface, CorePalette *palette, CoreSurfaceBufferLock *lock ) { DFBResult ret; UcDriverData *ucdrv = (UcDriverData*) driver_data; /* call the original function */ ret = ucOldPrimaryFuncs.SetRegion( layer, ucOldPrimaryDriverData, layer_data, region_data, config, updated, surface, palette, lock ); if (ret) return ret; uc_ovl_vcmd_wait(ucdrv->hwregs); /* select pixel based or global alpha */ if (!ucdrv->ovl) // overlay not present return DFB_OK; if (config->options & DLOP_ALPHACHANNEL) ucdrv->ovl->opacity_primary = -1; // use primary alpha for overlay else if (config->options & DLOP_OPACITY) ucdrv->ovl->opacity_primary = config->opacity ^ 0xff; // use inverse for overlay else ucdrv->ovl->opacity_primary = 0x00; // primary opaque == overlay transparent if (ucdrv->ovl->v1.level < 0) // primary on top? { VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucdrv->ovl->opacity_primary)); VIDEO_OUT(ucdrv->hwregs, V_COMPOSE_MODE, VIDEO_IN(ucdrv->hwregs, V_COMPOSE_MODE) | V1_COMMAND_FIRE); } return DFB_OK; }
static DFBResult uc_ovl_set_level(CoreLayer *layer, void *driver_data, void *layer_data, int level) { UcOverlayData* ucovl = (UcOverlayData*) layer_data; UcDriverData* ucdrv = (UcDriverData*) driver_data; if (level == 0) return DFB_INVARG; if (level > 0) { // Enable underlay mode. VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(-1)); } else { // Enable overlay mode (default) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(ucovl->v1.opacity)); } ucovl->v1.level = level; return DFB_OK; }
static DFBResult osdSetRegion( CoreLayer *layer, void *driver_data, void *layer_data, void *region_data, CoreLayerRegionConfig *config, CoreLayerRegionConfigFlags updated, CoreSurface *surface, CorePalette *palette, CoreSurfaceBufferLock *lock ) { DFBResult ret; UcDriverData *ucdrv = (UcDriverData*) driver_data; /* call the original function */ ret = ucOldPrimaryFuncs.SetRegion( layer, ucOldPrimaryDriverData, layer_data, region_data, config, updated, surface, palette, lock ); if (ret) return ret; uc_ovl_vcmd_wait(ucdrv->hwregs); /* select pixel based or global alpha */ if (config->options & DLOP_ALPHACHANNEL) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(-1)); else if (config->options & DLOP_OPACITY) VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(config->opacity)); else VIDEO_OUT(ucdrv->hwregs, V_ALPHA_CONTROL, uc_ovl_map_alpha(0xff)); VIDEO_OUT(ucdrv->hwregs, V_COMPOSE_MODE, V1_COMMAND_FIRE); return DFB_OK; }
static void uc_spic_set_palette( volatile u8* hwregs, CorePalette *palette ) { int i; if (palette) { for (i = 0; i < 16; i++) { /* TODO: Check r-g-b order. */ VIDEO_OUT(hwregs, RAM_TABLE_CONTROL, (palette->entries[i].r << 24) | (palette->entries[i].g << 16) | (palette->entries[i].b << 8) | (i << 4) | RAM_TABLE_RGB_ENABLE); } } }
static DFBResult uc_ovl_remove(CoreLayer *layer, void *driver_data, void *layer_data, void *region_data) { UcDriverData* ucdrv = (UcDriverData*) driver_data; UcOverlayData* ucovl = (UcOverlayData*) layer_data; volatile u8* vio = ucdrv->hwregs; ucovl->v1.isenabled = false; uc_ovl_vcmd_wait(vio); VIDEO_OUT(vio, V_FIFO_CONTROL, UC_MAP_V1_FIFO_CONTROL(16,12,8)); // VIDEO_OUT(vio, ALPHA_V3_FIFO_CONTROL, 0x0407181f); if (ucovl->hwrev == 0x10) { VIDEO_OUT(vio, V1_ColorSpaceReg_1, ColorSpaceValue_1_3123C0); VIDEO_OUT(vio, V1_ColorSpaceReg_2, ColorSpaceValue_2_3123C0); } else { VIDEO_OUT(vio, V1_ColorSpaceReg_1, ColorSpaceValue_1); VIDEO_OUT(vio, V1_ColorSpaceReg_2, ColorSpaceValue_2); } VIDEO_OUT(vio, HQV_CONTROL, VIDEO_IN(vio, HQV_CONTROL) & ~HQV_ENABLE); VIDEO_OUT(vio, V1_CONTROL, VIDEO_IN(vio, V1_CONTROL) & ~V1_ENABLE); // VIDEO_OUT(vio, V3_CONTROL, VIDEO_IN(vio, V3_CONTROL) & ~V3_ENABLE); VIDEO_OUT(vio, V_COMPOSE_MODE, VIDEO_IN(vio, V_COMPOSE_MODE) | V1_COMMAND_FIRE); ucovl->surface = NULL; return DFB_OK; }
DFBResult uc_ovl_update(UcDriverData* ucdrv, UcOverlayData* ucovl, int action, CoreSurface* surface) { int sw, sh, sp, sfmt; // Source width, height, pitch and format int dx, dy; // Destination position int dw, dh; // Destination width and height VideoMode *videomode; DFBRectangle scr; // Screen size bool write_buffers = false; bool write_settings = false; volatile u8* vio = ucdrv->hwregs; u32 win_start, win_end; // Overlay register settings u32 zoom, mini; u32 dcount, falign, qwpitch; u32 y_start, u_start, v_start; u32 v_ctrl, fifo_ctrl; int offset = surface->front_buffer->video.offset; if (!ucovl->v1.isenabled) return DFB_OK; qwpitch = 0; // Get screen size videomode = dfb_system_current_mode(); scr.w = videomode ? videomode->xres : 720; scr.h = videomode ? videomode->yres : 576; scr.x = 0; scr.y = 0; if (ucovl->scrwidth != scr.w) { // FIXME: fix uc_ovl_setup_fifo() // uc_ovl_setup_fifo(ucovl, scr.w); action |= UC_OVL_CHANGE; } D_ASSERT(surface); sw = surface->config.size.w; sh = surface->config.size.h; sp = surface->front_buffer->video.pitch; sfmt = surface->config.format; if (ucovl->deinterlace) { /*if (ucovl->field) offset += sp;*/ sh /= 2; //sp *= 2; } if (action & UC_OVL_CHANGE) { if ((sw > 4096) || (sh > 4096) || (sw < 32) || (sh < 1) || (sp > 0x1fff)) { D_DEBUG("Layer surface size is out of bounds."); return DFB_INVAREA; } dx = ucovl->v1.win.x; dy = ucovl->v1.win.y; dw = ucovl->v1.win.w; dh = ucovl->v1.win.h; // Get image format, FIFO size, etc. uc_ovl_map_v1_control(sfmt, sw, ucovl->hwrev, ucovl->extfifo_on, &v_ctrl, &fifo_ctrl); if (ucovl->deinterlace) { v_ctrl |= /*V1_BOB_ENABLE |*/ V1_FRAME_BASE; } // Get layer window. // The parts that fall outside the screen are clipped. uc_ovl_map_window(scr.w, scr.h, &(ucovl->v1.win), sw, sh, &win_start, &win_end, &ucovl->v1.ox, &ucovl->v1.oy); // Get scaling and data-fetch parameters // Note: the *_map_?zoom() functions return false if the scaling // is out of bounds. We don't act on it for now, because it only // makes the display look strange. zoom = 0; mini = 0; uc_ovl_map_vzoom(sh, dh, &zoom, &mini); uc_ovl_map_hzoom(sw, dw, &zoom, &mini, &falign, &dcount); qwpitch = uc_ovl_map_qwpitch(falign, sfmt, sw); write_settings = true; } if (action & (UC_OVL_FIELD | UC_OVL_FLIP | UC_OVL_CHANGE)) { int field = 0; // Update the buffer pointers if (ucovl->deinterlace) { field = ucovl->field; } uc_ovl_map_buffer(sfmt, offset, ucovl->v1.ox, ucovl->v1.oy, sw, surface->config.size.h, sp, 0/*field*/, &y_start, &u_start, &v_start); if (field) { y_start |= 0x08000000; } write_buffers = true; } // Write to the hardware /* if (write_settings || write_buffers) uc_ovl_vcmd_wait(vio);*/ if (write_settings) { VIDEO_OUT(vio, V1_CONTROL, v_ctrl); VIDEO_OUT(vio, V_FIFO_CONTROL, fifo_ctrl); VIDEO_OUT(vio, V1_WIN_START_Y, win_start); VIDEO_OUT(vio, V1_WIN_END_Y, win_end); VIDEO_OUT(vio, V1_SOURCE_HEIGHT, (sh << 16) | dcount); VIDEO_OUT(vio, V12_QWORD_PER_LINE, qwpitch); VIDEO_OUT(vio, V1_STRIDE, sp | ((sp >> 1) << 16)); VIDEO_OUT(vio, V1_MINI_CONTROL, mini); VIDEO_OUT(vio, V1_ZOOM_CONTROL, zoom); } if (write_buffers) { VIDEO_OUT(vio, V1_STARTADDR_0, y_start); VIDEO_OUT(vio, V1_STARTADDR_CB0, u_start); VIDEO_OUT(vio, V1_STARTADDR_CR0, v_start); } if (write_settings || write_buffers) { VIDEO_OUT(vio, V_COMPOSE_MODE, V1_COMMAND_FIRE); } return DFB_OK; }
static void uc_spic_enable( volatile u8 *hwregs, bool enable ) { VIDEO_OUT(hwregs, SUBP_CONTROL_STRIDE, (VIDEO_IN(hwregs, SUBP_CONTROL_STRIDE) & ~SUBP_HQV_ENABLE) | (enable ? SUBP_HQV_ENABLE : 0)); }