/**************************************************************************//** \brief Performs exchanging of entry points between application and bootloader. ******************************************************************************/ void flashExchangeEntryPoints(void) { uint32_t appLabel; uint32_t tempAddr = FLASH_START_ADDRESS; uint32_t itr; uint32_t fmrBackup; tempAddr = FLASH_END_ADDRESS + BOOT_AREA_SIZE - FLASH_PAGE_SIZE + 1; // change application entry point to boot entry point for (itr = 0; itr < FLASH_PAGE_SIZE; itr += sizeof(uint32_t)) { if ((FLASH_END_ADDRESS + BOOT_AREA_SIZE - sizeof(uint32_t) + 1) == (tempAddr + itr)) { // last flash byte for storing application entry point MMIO(tempAddr + itr) = appEntryPoint; continue; } if ((FLASH_END_ADDRESS + BOOT_AREA_SIZE - 2 * sizeof(uint32_t) + 1) == (tempAddr + itr)) { appLabel = MMIO(tempAddr + itr); appLabel |= 0xFF000000; MMIO(tempAddr + itr) = appLabel; continue; } MMIO(tempAddr + itr) = MMIO(tempAddr + itr); // copy flash page to shadow buffer } fmrBackup = EFC->EEFC_FMR; EFC->EEFC_FMR = (FWS_FOR_WRITE << 8); // Perform page erase and write. flashWritePage(LAST_PAGE, false); EFC->EEFC_FMR = fmrBackup; }
static GLboolean multipass_cliprect( struct gl_context *ctx, GLuint pass ) { sisContextPtr smesa = SIS_CONTEXT( ctx ); if (pass >= smesa->driDrawable->numClipRects) { return GL_FALSE; } else { GLint x1, y1, x2, y2; x1 = smesa->driDrawable->pClipRects[pass].x1 - smesa->driDrawable->x; y1 = smesa->driDrawable->pClipRects[pass].y1 - smesa->driDrawable->y; x2 = smesa->driDrawable->pClipRects[pass].x2 - smesa->driDrawable->x; y2 = smesa->driDrawable->pClipRects[pass].y2 - smesa->driDrawable->y; if (ctx->Scissor.Enabled) { GLint scisy1 = Y_FLIP(ctx->Scissor.Y + ctx->Scissor.Height - 1); GLint scisy2 = Y_FLIP(ctx->Scissor.Y); if (ctx->Scissor.X > x1) x1 = ctx->Scissor.X; if (scisy1 > y1) y1 = scisy1; if (ctx->Scissor.X + ctx->Scissor.Width - 1 < x2) x2 = ctx->Scissor.X + ctx->Scissor.Width - 1; if (scisy2 < y2) y2 = scisy2; } MMIO(REG_3D_ClipTopBottom, y1 << 13 | y2); MMIO(REG_3D_ClipLeftRight, x1 << 13 | x2); /* Mark that we clobbered these registers */ smesa->GlobalFlag |= GFLAG_CLIPPING; return GL_TRUE; } }
/*! * This procedure waits for the next vertical blanking (vertical retrace) * period. If the display is already in a vertical blanking period, this * procedure exits. * * Note: A timeout is included to prevent an endless loop. * * @param display_handle * * @return FALSE if timed out */ static int igd_wait_vblank_plb(igd_display_h display_handle) { return wait_for_vblank_plb(MMIO(display_handle), PIPE(display_handle)->pipe_reg); } /* wait_vblank */
/*! * * @param display_handle * @param palette_entry * @param palette_color * * @return 0 on success * @return -IGD_INVAL on failure */ static int igd_get_palette_entry_plb( igd_display_h display_handle, unsigned long palette_entry, unsigned long *palette_color) { /* Too Slow For Tracing */ /* Return if Pipe is not on */ if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) + PIPE(display_handle)->pipe_reg))) { return -IGD_INVAL; } *palette_color = 0xffffff & EMGD_READ32(MMIO(display_handle) + PIPE(display_handle)->palette_reg + palette_entry * 4); return 0; }
/*! * * @param display_handle * @param palette_entry * @param palette_color * * @return 0 on success * @return -IGD_INVAL on failure */ static int igd_set_palette_entry_plb( igd_display_h display_handle, unsigned long palette_entry, unsigned long palette_color) { /* Too Slow For Tracing */ /* Return if Pipe is not on */ if(!((1L<<31) & EMGD_READ32(MMIO(display_handle) + PIPE(display_handle)->pipe_reg))) { return -IGD_INVAL; } /* EMGD_DEBUG("%x : %ld : %lx", display_handle, palette_entry, palette_color); */ EMGD_WRITE32(palette_color, MMIO(display_handle) + PIPE(display_handle)->palette_reg + palette_entry * 4); return 0; }
/**************************************************************************//** \brief Function to do an atomic erase-write on one page in the flash. \note The maximum pageAddress must not be exceeded. The maximum number of pages can be found in the datasheet. \param[in] pageAddress Page address to the page to erase/write. ******************************************************************************/ void flashEraseWritePage(uint16_t pageAddress) { // Calculate actual start address of the page. uint32_t tableAddress = (uint32_t)pageAddress * (uint32_t)FLASH_PAGE_SIZE; uint16_t itr; uint32_t *ptr = (uint32_t *)temporaryPageBuffer; for (itr = 0; itr < FLASH_PAGE_SIZE; itr += sizeof(uint32_t), ptr++) { if ((FIRST_PAGE == pageAddress) && (sizeof(uint32_t) == (tableAddress + itr))) { appEntryPoint = *ptr; MMIO(tableAddress + itr) = MMIO(tableAddress + itr); } else { MMIO(tableAddress + itr) = *ptr; } } // Perform page erase. flashWritePage(pageAddress, false); }
/* Fires a set of vertices that have been written from AGP_StartPtr to * AGP_WritePtr, using the smesa->AGPParseSet format. */ void sisFireVertsAGP( sisContextPtr smesa ) { if (AGP_WritePtr == AGP_StartPtr) return; mWait3DCmdQueue(5); mEndPrimitive(); MMIO(REG_3D_AGPCmBase, (long)AGP_StartPtr - (long)smesa->AGPCmdBufBase + (long)smesa->AGPCmdBufAddr); MMIO(REG_3D_AGPTtDwNum, (((long)AGP_WritePtr - (long)AGP_StartPtr) >> 2) | 0x50000000); MMIO(REG_3D_ParsingSet, smesa->AGPParseSet); MMIO(REG_3D_AGPCmFire, (GLint)(-1)); mEndPrimitive(); *(smesa->pAGPCmdBufNext) = (((long)AGP_WritePtr - (long)smesa->AGPCmdBufBase) + 0xf) & ~0xf; AGP_StartPtr = AGP_WritePtr; sisUpdateAGP( smesa ); }
/*! * This function programs the Timing registers and clock registers and * other control registers for PIPE. * * @param display * @param status * * @return void */ static void program_pipe_plb(igd_display_context_t *display, unsigned long status) { unsigned long timing_reg; unsigned long pipe_conf; unsigned long hactive, vactive; igd_timing_info_t *pTimings; unsigned long temp; #ifndef CONFIG_MICRO igd_display_port_t *port; int i; #endif EMGD_TRACE_ENTER; EMGD_DEBUG("Program Pipe: %s", status?"ENABLE":"DISABLE"); EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display)); pipe_conf = device_data->pipe_preserve & EMGD_READ32(MMIO(display) + PIPE(display)->pipe_reg); /* Reset the plane of this pipe back to NULL, it will be set on the * call to program_plane, which is ok, since program_pipe occurs * before program_plane */ PIPE(display)->plane = NULL; if((status == FALSE) || (GET_DEVICE_POWER_STATE(display) == IGD_POWERSTATE_D3)) { /* Disable pipe */ EMGD_WRITE32(pipe_conf & (~0x80000000), MMIO(display) + PIPE(display)->pipe_reg); return; } pTimings = PIPE(display)->timing; /* * If the mode is VGA and the PD says it handles all VGA modes without * reprogramming then just set the mode and leave centering off. */ if(pTimings->mode_info_flags & IGD_MODE_VESA) { if (pTimings->mode_number <= VGA_MODE_NUM_MAX) { /* Pipe timings and clocks are not used but it must be on anyway */ EMGD_WRITE32(pipe_conf | 0x80000000, MMIO(display) + PIPE(display)->pipe_reg); program_pipe_vga_plb(display); return; } else { #ifdef CONFIG_MICRO set_256_palette(MMIO(display)); #endif } } /* Program dot clock divisors. */ program_clock_plb(display, PIPE(display)->clock_reg, pTimings->dclk); /* Program timing registers for the pipe */ timing_reg = PIPE(display)->timing_reg; if (pTimings->mode_info_flags & IGD_PIXEL_DOUBLE) { hactive = (unsigned long)pTimings->width*2 - 1; } else { hactive = (unsigned long)pTimings->width - 1; } if (pTimings->mode_info_flags & IGD_LINE_DOUBLE) { if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) { vactive = (unsigned long)pTimings->height - 1; } else { vactive = (unsigned long)pTimings->height*2 - 1; } } else { if (pTimings->mode_info_flags & IGD_SCAN_INTERLACE) { vactive = (unsigned long)pTimings->height/2 - 1; } else { vactive = (unsigned long)pTimings->height - 1; } } /* * DPLL should be on at this point which is required for touching * the palette. */ #ifndef CONFIG_MICRO /* reset the palette */ for (i = 0; i < 256; i++) { EMGD_WRITE32(((i<<16) | (i<<8) | i), MMIO(display) + PIPE(display)->palette_reg + i*4); } /* apply color correction */ port = PORT_OWNER(display); for( i = 0; PD_ATTR_LIST_END != port->attributes[i].id; i++ ) { if ((PD_ATTR_ID_FB_GAMMA == (port->attributes[i].id)) || (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id)) || (PD_ATTR_ID_FB_BRIGHTNESS == (port->attributes[i].id))) { mode_context->dispatch->full->set_color_correct(display); } } #endif /* * NOTE: For size reasons the timng table contains unsigned short * values. Don't shift them past 16. Use a temp instead. * All register offsets and bit shift are verified for Napa */ temp = ((unsigned long)pTimings->htotal << 16) | hactive; EMGD_WRITE32(temp, MMIO(display) + timing_reg); temp = ((unsigned long)pTimings->hblank_end << 16) | (unsigned long)pTimings->hblank_start; EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x04); temp = ((unsigned long)pTimings->hsync_end << 16) | (unsigned long)pTimings->hsync_start; EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x08); temp = ((unsigned long)pTimings->vtotal << 16) | vactive; EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x0C); temp = ((unsigned long)pTimings->vblank_end << 16) | (unsigned long)pTimings->vblank_start; EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x10); temp = ((unsigned long)pTimings->vsync_end << 16) | (unsigned long)pTimings->vsync_start; EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x14); /* * If there is a linked mode it is either the VGA or a scaled * mode. If it is scaled then we need to use it as the source size. */ if(pTimings->extn_ptr) { igd_timing_info_t *scaled_timings = (igd_timing_info_t *)pTimings->extn_ptr; if((scaled_timings->mode_info_flags & IGD_MODE_VESA) && (scaled_timings->mode_number <= VGA_MODE_NUM_MAX)) { temp = (hactive << 16) | vactive; } else { temp = (unsigned long)scaled_timings->width - 1; temp = (temp << 16) | (unsigned long)(scaled_timings->height - 1); } } else { temp = (hactive << 16) | vactive; } EMGD_WRITE32(temp, MMIO(display) + timing_reg + 0x1C); /* Set other registers */ /* * FIXME: max_dclk needs to be determined from core clock * at init time. 915 etc has several skus with different * clocks for the same device ID. * */ /* These values are derived from the Poulsbo B-Spec as * the suggested values */ WRITE_MMIO_REG (display, FW_BLC1, device_data->fw_blc1); WRITE_MMIO_REG (display, FW_BLC2, device_data->fw_blc2); WRITE_MMIO_REG (display, FW_BLC3, device_data->fw_blc3); WRITE_MMIO_REG (display, FW_BLC_SELF, device_data->fw_self); WRITE_MMIO_REG (display, DSP_ARB, device_data->dsp_arb); /* The SGX 2D engine can saturate the memory bus and starve * the display engine causing visible screen tearing. * This reduces the priority of the SGX vs. display engine */ temp = READ_MMIO_REG (display, G_DEBUG); WRITE_MMIO_REG (display, G_DEBUG, (temp | (1 << 11))); pipe_conf |= PIPE_ENABLE; WRITE_MMIO_REG(display, PIPE(display)->pipe_reg, pipe_conf); /* * Set the VGA address range to 0xa0000 so that a normal (not VGA) * mode can be accessed through 0xa0000 in a 16bit world. */ WRITE_AR(MMIO(display), 0x10, 0xb); WRITE_VGA(MMIO(display), GR_PORT, 0x06, 0x5); WRITE_VGA(MMIO(display), GR_PORT, 0x10, 0x1); if(pTimings->extn_ptr) { /* This means either internal scaling (LVDS) or centered VGA */ pTimings = pTimings->extn_ptr; if(pTimings->extn_ptr) { /* This is both the scaled and centered VGA */ pTimings = pTimings->extn_ptr; } if(pTimings->mode_info_flags & IGD_MODE_VESA) { if (pTimings->mode_number <= VGA_MODE_NUM_MAX) { program_pipe_vga_plb(display); } else { #ifdef CONFIG_MICRO set_256_palette(MMIO(display)); #endif } } } EMGD_TRACE_EXIT; return; }
/*! * Program Display Plane Values. * * @param display Pointer to hardware device instance data * @param status * * @return void */ static void program_plane_plb(igd_display_context_t *display, unsigned long status) { unsigned long stereo; unsigned long stride; unsigned long size; unsigned long plane_control; igd_timing_info_t *timing; igd_framebuffer_info_t *fb_info = PLANE(display)->fb_info; unsigned long plane_reg = PLANE(display)->plane_reg; unsigned long start_addr_reg = DSPAADDR; EMGD_TRACE_ENTER; EMGD_DEBUG("Program Plane: %s", status?"ENABLE":"DISABLE"); EMGD_DEBUG("Device power state: D%ld", GET_DEVICE_POWER_STATE(display)); igd_wait_vblank_plb((igd_display_h)display); plane_control = EMGD_READ32(MMIO(display) + plane_reg); if(PLANE(display)->plane_reg == DSPACNTR) { plane_control &= device_data->plane_a_preserve; } else { /* if it's plane b or plane c */ plane_control &= device_data->plane_b_c_preserve; start_addr_reg = 0x71184; } if((status == FALSE) || (GET_DEVICE_POWER_STATE(display) != IGD_POWERSTATE_D0)) { /* * Note: The vga programming code does not have an "off". So * when programming the plane to off we make sure VGA is off * as well. */ disable_vga_plb(MMIO(display)); /* * To turn off plane A or B, the program have to triger the plane A or B * start register. Or else, it will not work. */ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg); EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg), MMIO(display) + start_addr_reg); igd_wait_vblank_plb((igd_display_h)display); return; } /* * Note: The very first pass through this function will be with * status false and timings == NULL. Don't use the timings before * the check above. */ timing = PIPE(display)->timing; /* There is a special case code for legacy VGA modes */ while (timing->extn_ptr) { timing = (igd_timing_info_t *)timing->extn_ptr; } if(MODE_IS_VGA(timing)) { program_plane_vga(display, timing); return; } disable_vga_plb(MMIO(display)); size = (((unsigned long)timing->height - 1)<<16) | (unsigned long)(timing->width - 1); /* enable plane, select pipe, enable gamma correction logic */ plane_control |= 0x80000000 | (PIPE(display)->pipe_num<<24); PIPE(display)->plane = PLANE(display); #ifndef CONFIG_MICRO plane_control |= (1<<30); #endif /* Here the settings: * If line + pixel dbling, set 21,20 to 01b, and set Horz Multiply * If line dbling only, set 21,20 to 11b * If pixel dbling only, set 21,20 to 00b, but set Horz Multiply * If no doubling, set 21,20 to 00b (no Horz Multiply) * For pixel doubling * --> both progressive/interlaced modes * For Line doubling * --> progressive modes only */ if (!(timing->mode_info_flags & IGD_SCAN_INTERLACE)) { /* Line doubling in progressive mode requires special bits */ if (timing->mode_info_flags & IGD_LINE_DOUBLE) { /* BIT 20 for line & pixel doubling*/ plane_control |= BIT20; /* check later, if no pixel doubling, set bit 21 too*/ } } if (timing->mode_info_flags & IGD_PIXEL_DOUBLE) { /* Horz pixel multiply must be set for double */ plane_control |= BIT11; /* TODO -> Plba can more than double, It can 3X, 4X etc. These arent exposed now */ } else if(plane_control & BIT20){ /* For line ONLY doubling, set bit 21 also '1' */ plane_control |= BIT21; } mode_get_stride_stereo_plb(display, &stride, &stereo, 0); /* set color depth */ switch (IGD_PF_DEPTH(fb_info->pixel_format)) { case PF_DEPTH_8: plane_control |= BIT27 | BIT30; break; case PF_DEPTH_16: plane_control |= BIT28 | BIT26; break; default: case PF_DEPTH_32: plane_control |= BIT28 | BIT27; break; } if(fb_info->flags & IGD_ENABLE_DISPLAY_GAMMA) { plane_control |= (BIT30); } EMGD_DEBUG(" Plane Control = 0x%lx", plane_control); EMGD_DEBUG(" Plane Base = 0x%lx", fb_info->visible_offset); EMGD_DEBUG(" Plane Pitch = 0x%lx", stride); EMGD_DEBUG(" Plane Size = 0x%lx", size); EMGD_WRITE32(stride, MMIO(display) + plane_reg + DSP_STRIDE_OFFSET); /* * In reality this only exists for plane B. It doesn't seem to hurt * plane A so just do it anyway and save us another case. */ EMGD_WRITE32(size, MMIO(display) + plane_reg + DSP_SIZE_OFFSET); /*EMGD_WRITE32(stereo, MMIO(display) + plane_reg + DSP_STEREO_OFFSET); - This register is Reserved ON plba */ EMGD_WRITE32(fb_info->visible_offset, MMIO(display) + plane_reg + DSP_START_OFFSET); /* It seems we need push or trigger plane A/B to start to work * on Poulsbo, especially for sDVO port. Let's write plane control * register and start address register at last. */ EMGD_WRITE32(plane_control, MMIO(display) + plane_reg); EMGD_WRITE32(EMGD_READ32(MMIO(display) + start_addr_reg), MMIO(display) + start_addr_reg); igd_wait_vblank_plb((igd_display_h)display); EMGD_TRACE_EXIT; return; }
/*! * This function sets up planes, pipes, and ports * with the configuration passed in and returnes either one * or two display handle lists. * * @param driver_handle from igd_init_driver(). * @param primary on return, this points to a list of displays. * @param primary_ptinfo incoming timing info for the primary. * @param primary_fbinfo incoming framebuffer info. * @param secondary on return, this points to a list of displays. * @param secondary_fbinfo incoming framebuffer info. * @param dc display configuration * @param flags modify function behavior * * @return 0 on success * @return -IGD_INVAL on failure */ int igd_alter_displays( igd_driver_h driver_handle, igd_display_h *_primary, igd_display_info_t *primary_pt_info, igd_framebuffer_info_t *primary_fb_info, igd_display_h *_secondary, igd_display_info_t *secondary_pt_info, igd_framebuffer_info_t *secondary_fb_info, unsigned long dc, unsigned long flags) { igd_context_t *context = (igd_context_t *)driver_handle; igd_display_context_t **primary = (igd_display_context_t **)_primary; igd_display_context_t **secondary = (igd_display_context_t **)_secondary; igd_framebuffer_info_t *fb_info = NULL; igd_display_context_t *display = NULL,*tv_display=NULL; int p; int ret; unsigned short tv_port_num=0; int p_chng = 1, s_chng = 1; unsigned char disable_plane_pipe = 0; unsigned long current_dc; #if 0 /* Ian Elliott is taking this out ... see comment below */ #ifndef CONFIG_MICRO igd_framebuffer_info_t *plane_fb_info = NULL; #endif #endif /* 0 -- Ian is taking this out */ EMGD_TRACE_ENTER; /* * Make sure the DC is valid * * vBIOS won't be able to do this every time, for now only have * the drivers's do the check. */ #ifndef CONFIG_MICRO if (dc && !dsp_valid_dc(dc, 0)) { EMGD_ERROR_EXIT("Invalid display configuration: 0x%08lx", dc); return -IGD_ERROR_INVAL; } #endif /* * Can all display_info's and fb_info's be NULL? I.E. make this * function do an alloc of display handles only? If so, then * check for that condition and return without error. Otherwise * return an error. */ if (dc && (!primary_pt_info && !primary_fb_info) && (!secondary_pt_info && !secondary_fb_info)) { EMGD_ERROR_EXIT("Invalid timing and framebuffer info"); return -IGD_ERROR_INVAL; } #ifndef CONFIG_MICRO /* FIXME: GDK Change this to dispatch->idle() */ if (dsp_wait_rb(mode_context->context) != 0) { return -IGD_ERROR_INVAL; } #endif /* If seamless request is NOT set , then do reset_plane_pipe_ports * else delay it until we cannot support it. * If seamless is requested by the user and we CAN support it * then we need to make sure reset_plane_pipe_ports is NOT * called. That's the whole point anyway. Not to reset anything * during seamless transition */ if(mode_context->seamless != TRUE) { /* Reset planes/pipes/ports before doing first alter display */ if (mode_context->first_alter) { mode_context->dispatch->reset_plane_pipe_ports( mode_context->context); mode_context->first_alter = FALSE; } } current_dc = *(context->mod_dispatch.dsp_current_dc); #ifndef CONFIG_MICRO /* Check if platform needs force alter * to make sure we run tuning code. This * is for TNC-B0 workaround.*/ if (mode_context->dispatch->dsp_is_force_alter_required){ if (mode_context->dispatch-> dsp_is_force_alter_required(context-> mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(current_dc)], current_dc, dc)){ flags |= IGD_FORCE_ALTER; } } #endif /* * Turn off the planes, pipes, and ports associated with the current * DC. However, limit the change to the primary if the secondary * display handle is NULL or limit the change to the secondary if the * the pimary display handle is NULL. */ for (p = 7; p > 0; p--) { if (p > 4) { display = NULL; if (DC_PORT_NUMBER(current_dc, p)) { display = context->mod_dispatch. dsp_display_list[IGD_DC_SECONDARY(current_dc)]; s_chng = TIMING_CHANGED(display, dc, current_dc, secondary_pt_info, secondary_fb_info, (unsigned long)0xfff00000, flags); } if (s_chng && display && secondary) { /* if the port is TV, then don't set the power to S3 as this causes * blank screen and system hang on LVDS on FSDOS, probably because the * external clock needs to be on till the pipes and * DPLLs are off */ if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type == PD_DISPLAY_TVOUT) { tv_display = display; tv_port_num = DC_PORT_NUMBER(current_dc, p); } else { ret = mode_context->dispatch->program_port(display, DC_PORT_NUMBER(current_dc, p), FALSE); } /* The secondary pipe master */ if (p == 5) { disable_plane_pipe = 1; } } } else { display = NULL; if (DC_PORT_NUMBER(current_dc, p)) { display = context->mod_dispatch. dsp_display_list[IGD_DC_PRIMARY(current_dc)]; p_chng = TIMING_CHANGED(display, dc, current_dc, primary_pt_info, primary_fb_info, (unsigned long)0x000ffff0, flags); } if (p_chng && display && primary) { /* if the port is TV, then don't set the power to S3 as this causes * blank screen and system hang on LVDS on FSDOS, probably because the * external clock needs to be on till the pipes and * DPLLs are off */ if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type == PD_DISPLAY_TVOUT) { tv_display = display; tv_port_num = DC_PORT_NUMBER(current_dc, p); } else { ret = mode_context->dispatch->program_port(display, DC_PORT_NUMBER(current_dc, p), FALSE); } /* The primary pipe master */ if (p == 1) { disable_plane_pipe = 1; } } } /* Disable plane and pipe after disabling the ports */ if (disable_plane_pipe) { if(mode_context->dispatch->full) { mode_context->dispatch->full->program_cursor(display, FALSE); } mode_context->dispatch->program_plane(display, FALSE); mode_context->dispatch->program_pipe(display, FALSE); /*pipes and dplls are off, now turn off tv port */ if(tv_display) { ret = mode_context->dispatch->program_port(tv_display, tv_port_num, FALSE); tv_display = NULL; } disable_plane_pipe = 0; } } #ifndef CONFIG_MICRO /* If DC is zero, then return here. A zero dc turns everything off */ /* This never happens for VBIOS since it only always calls * * alter_displays at the same point with the same valid DC */ if (!dc) { int i; mode_context->dispatch->reset_plane_pipe_ports(mode_context->context); /* Should de-allocate everything here */ dsp_alloc(driver_handle, dc, flags); /* * FIXME: This should be done inside dsp alloc, mode module does * not own this information. * When dc = 0, set all displays allocated to 0. */ for (i=0; i<IGD_MAX_PORTS+1; i++) { if (context->mod_dispatch.dsp_display_list[i]) { context->mod_dispatch.dsp_display_list[i]->allocated = 0; } context->mod_dispatch.dsp_display_list[i] = NULL; } return 0; } #endif /* * Check the DC (display configuration). If it is the same as the * current configuration, then don't change any allocations, only * modify the framebuffers and timings. */ if (dc != current_dc) { EMGD_DEBUG("Allocate display handles based on DC"); #ifndef CONFIG_MICRO if (swap_required(current_dc, dc, primary)) { swap_fb_cursor(); } #endif /* * This function should never be called after VBIOS initialization * * The dsp_alloc is discarded after VBIOS init and is over- * * written by font tables. Thus in VBIOS IAL, alter_displays * * is never get called with a different DC from the 1st time * */ dsp_alloc(driver_handle, dc, flags); } /* Attach the displays to the caller's pointers */ if (primary) { *primary = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)]; #ifndef CONFIG_MICRO if (*primary && context->mod_dispatch.alloc_queues) { ret = context->mod_dispatch.alloc_queues(driver_handle, (*primary)->pipe, flags); if (ret) { EMGD_ERROR("unable to allocate command queues"); } } #endif } if (secondary) { EMGD_DEBUG("Attaching display 1 to secondary pointer"); *secondary = context->mod_dispatch. dsp_display_list[IGD_DC_SECONDARY(dc)]; #ifndef CONFIG_MICRO if (*secondary && context->mod_dispatch.alloc_queues) { ret = context->mod_dispatch.alloc_queues(driver_handle, (*secondary)->pipe, flags); if (ret) { EMGD_ERROR("unable to allocate command queues"); } } #endif } /* * Configure the primary display. This configures the timings and the * framebuffer. Once configured, it turns everythying on. */ if(primary && *primary && (primary_pt_info || primary_fb_info) && p_chng) { EMGD_DEBUG("Configure primary timings"); /* make framebuffer changes */ if (primary_fb_info) { /* set up new frame buffer info */ fb_info = primary_fb_info; } else { fb_info = PLANE(*primary)->fb_info; } ret = configure_display(driver_handle, (igd_display_context_t *)(*primary), primary_pt_info, fb_info, dc, 0, 4, flags); if (ret) { EMGD_DEBUG("Primary display disabled."); } } /* * Configure the secondary display. This configures the timings and the * framebuffer. Once configured, it turns everythying on. * * How close is this code to the code for the primary? Could this * be moved to a separate function? */ if (secondary != NULL) { #ifndef CONFIG_MICRO /* * In the case where we are in extended or clone and our pipe is not * turned on, we need to turn the pipes on. * We can run into this situation on pre-Cantiga Gen platforms on Linux * where LVDS was the primary display and was assigned PIPE B. Then we * are switching from LVDS to another display and that other display * wants to take PIPE A. In this case PIPE B will be turned on, the * display's new port will take PIPE A and turn on PIPE A. The second * display thinks it is still PIPE A and nothing has changed for it. * In this case where our pipe is not turned on, we need to let the * system know that something has changed. */ if ((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc)) && !(EMGD_READ32(MMIO(*secondary) + PIPE(*secondary)->pipe_reg) & 0x80000000)) { s_chng = 1; } #endif EMGD_DEBUG("Starting secondary pipe programming"); if ((*secondary != NULL) && (secondary_pt_info || secondary_fb_info) && s_chng){ /* * Configure the framebuffer. For clone, it is the same * as the primary. For DIH, it is a unique fb. */ EMGD_DEBUG("configure secondary framebuffer"); if (dc & IGD_DISPLAY_CONFIG_CLONE) { fb_info = PLANE(*primary)->fb_info; } else { if (secondary_fb_info) { fb_info = secondary_fb_info; } else { fb_info = PLANE(*secondary)->fb_info; } } ret = configure_display(driver_handle, (igd_display_context_t *)(*secondary), secondary_pt_info, fb_info, dc, 4, 7, flags); if (ret) { EMGD_DEBUG("Secondary display disabled."); EMGD_ERROR("Secondary display disabled."); } } } else { EMGD_DEBUG("Skipped secondary programming, NULL handle"); } /* * Workaround: wait for Vblank to avoid people accessing display * plane registers before the register is updated properly. */ if (primary && *primary) { EMGD_DEBUG("Wait for vblank on primary display (%p)", primary); EMGD_DEBUG("Wait for vblank on primary display (%p)", *primary); mode_context->dispatch->wait_vblank(*primary); } else if (secondary && *secondary) { EMGD_DEBUG("Wait for vblank on secondary display"); mode_context->dispatch->wait_vblank(*secondary); } EMGD_TRACE_EXIT; return 0; }
int query_ovl2_tnc(igd_display_h display_h, unsigned int flags) { igd_display_context_t *display = (igd_display_context_t *)display_h; inter_module_dispatch_t *md; platform_context_tnc_t * platform; os_alarm_t timeout; int ret; unsigned long pipe_reg, pipe_num; EMGD_TRACE_ENTER; switch (flags) { case IGD_OVL_QUERY_IS_HW_SUPPORTED: /* This is the second overlay, so HW overlay is not supported */ break; case IGD_OVL_QUERY_IS_LAST_FLIP_DONE: /* If there no sync to wait on, then the last flip is done, and the * Register Update has occured, simply return TRUE (Flip done). */ if (!ovl_context->sync2) { EMGD_DEBUG("Overlay already synced"); EMGD_TRACE_EXIT; return TRUE; } /* According to the PBL B-spec, there doesnt seem to exist any bit * for Sprite C Flip-Pending status. Testing 0x20AC in code during * virt queue's REG write shows nothing changed for Bit8. Thus, we * are using state of the VBLANK ISR bit as ovl2 flip status. * Assumption is that if were running 2nd overlay, its either clone * display or VEXT in WinCE. In either case, were not doing full screen * FB flipping, so this check should be 'statefully' accurate */ md = &display->context->mod_dispatch; platform = (platform_context_tnc_t *)display->context-> platform_context; pipe_num = PIPE(display)->pipe_num; if(pipe_num){ pipe_reg = PIPEB_STAT; } else { pipe_reg = PIPEA_STAT; } if(md && md->check_flip_pending){ ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex); if(md->check_flip_pending(MMIO(display), pipe_reg)){ OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex); EMGD_DEBUG("Overlay2 Sync done but Flip not done"); return FALSE; } OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex); } /* Now that we know the last flip is done and the register update is * complete, set the sync to 0 and return TRUE (Flip done). */ ovl_context->sync2 = FLIP_DONE; break; case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE: /* Wait for 200 milliseconds for the last flip to complete. If not * done in that time, there is likely a hardware problem so return * FALSE. */ timeout = OS_SET_ALARM(200); do { if (TRUE == query_ovl2_tnc(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) { EMGD_TRACE_EXIT; return TRUE; } } while (!OS_TEST_ALARM(timeout)); EMGD_ERROR_EXIT("Timeout waiting for last flip done"); return FALSE; break; case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED: return TRUE; break; case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED: return TRUE; break; } EMGD_TRACE_EXIT; return TRUE; }
unsigned int ovl2_send_instr_tnc( igd_display_context_t *display, ovl2_reg_tnc_t *spritec_regs_tnc, unsigned int flags) { unsigned char *mmio = MMIO(display); unsigned long tmp, pipe_reg, pipe_num; inter_module_dispatch_t *md; platform_context_tnc_t * platform; EMGD_TRACE_ENTER; /* We dont need the CMD_WAIT_OVL2_TNC instruction coz * our alter_ovl code already querried status * for last flip completion before getting here. See * micro_prepare_ovl2_tnc called by alter_ovl2_tnc. * It calls query overlay before the next flip */ /*If Overlay+FB Blend is requested and the FB is xRGB *turn on the ARGB format. */ if(ovl_context->fb_blend_ovl) { if((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_ON) { tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg); if((tmp & 0x3c000000) == 0x18000000) { tmp = tmp & 0xc3FFFFFF; EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg); EMGD_READ32(mmio + PLANE(display)->plane_reg); tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c); EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c); } } else { tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg); if((tmp & 0x3c000000) == 0x1c000000) { tmp = tmp & 0xc3FFFFFF; EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg); EMGD_READ32(mmio + PLANE(display)->plane_reg); tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 0x1c); EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 0x1c); OS_SLEEP(100); } } } /* Send a load register instruction to write the Plane C sprite address * which is the trigger register. * This is an instruction, so it happens after blend, and since it * is an instruction, we do not have to poll waiting for it. */ EMGD_WRITE32(spritec_regs_tnc->start, mmio + 0x7219C); /* Since the ISR bit 0x100 actually doesnt work, * we need to setup a trigger for a VBLANK event * on Pipe-B to guarantee that the Sprite-C had * actually completed its last flip. * (ISR bit was tested on Poulsbo D2 by capturing * timestamps of quick successive alter_overlays.. * checked ISR bit directly after the write to Sprite * C Address register in process_vqueue handling.. * the ISR bit never changed */ md = &display->context->mod_dispatch; platform = (platform_context_tnc_t *)display->context-> platform_context; pipe_num = PIPE(display)->pipe_num; if(pipe_num){ pipe_reg = PIPEB_STAT; } else { pipe_reg = PIPEA_STAT; } if(md && md->set_flip_pending){ OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex); md->set_flip_pending(MMIO(display), pipe_reg); OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex); } ovl_context->sync2 = WAIT_FOR_FLIP; EMGD_TRACE_EXIT; return IGD_SUCCESS; }
void sis_update_texture_state (sisContextPtr smesa) { __GLSiSHardware *prev = &smesa->prev; mWait3DCmdQueue (55); if (smesa->clearTexCache || (smesa->GlobalFlag & GFLAG_TEXTUREADDRESS)) { MMIO(REG_3D_TEnable, prev->hwCapEnable | MASK_TextureCacheClear); MMIO(REG_3D_TEnable, prev->hwCapEnable); smesa->clearTexCache = GL_FALSE; } /* Texture Setting */ if (smesa->GlobalFlag & CFLAG_TEXTURERESET) MMIO(REG_3D_TextureSet, prev->texture[0].hwTextureSet); if (smesa->GlobalFlag & GFLAG_TEXTUREMIPMAP) MMIO(REG_3D_TextureMip, prev->texture[0].hwTextureMip); /* MMIO(REG_3D_TextureTransparencyColorHigh, prev->texture[0].hwTextureClrHigh); MMIO(REG_3D_TextureTransparencyColorLow, prev->texture[0].hwTextureClrLow); */ if (smesa->GlobalFlag & GFLAG_TEXBORDERCOLOR) MMIO(REG_3D_TextureBorderColor, prev->texture[0].hwTextureBorderColor); if (smesa->GlobalFlag & GFLAG_TEXTUREADDRESS) { switch ((prev->texture[0].hwTextureSet & MASK_TextureLevel) >> 8) { case 11: MMIO(REG_3D_TextureAddress11, prev->texture[0].texOffset11); case 10: MMIO(REG_3D_TextureAddress10, prev->texture[0].texOffset10); MMIO(REG_3D_TexturePitch10, prev->texture[0].texPitch10); case 9: MMIO(REG_3D_TextureAddress9, prev->texture[0].texOffset9); case 8: MMIO(REG_3D_TextureAddress8, prev->texture[0].texOffset8); MMIO(REG_3D_TexturePitch8, prev->texture[0].texPitch89); case 7: MMIO(REG_3D_TextureAddress7, prev->texture[0].texOffset7); case 6: MMIO(REG_3D_TextureAddress6, prev->texture[0].texOffset6); MMIO(REG_3D_TexturePitch6, prev->texture[0].texPitch67); case 5: MMIO(REG_3D_TextureAddress5, prev->texture[0].texOffset5); case 4: MMIO(REG_3D_TextureAddress4, prev->texture[0].texOffset4); MMIO(REG_3D_TexturePitch4, prev->texture[0].texPitch45); case 3: MMIO(REG_3D_TextureAddress3, prev->texture[0].texOffset3); case 2: MMIO(REG_3D_TextureAddress2, prev->texture[0].texOffset2); MMIO(REG_3D_TexturePitch2, prev->texture[0].texPitch23); case 1: MMIO(REG_3D_TextureAddress1, prev->texture[0].texOffset1); case 0: MMIO(REG_3D_TextureAddress0, prev->texture[0].texOffset0); MMIO(REG_3D_TexturePitch0, prev->texture[0].texPitch01); } } if (smesa->GlobalFlag & CFLAG_TEXTURERESET_1) MMIO(REG_3D_Texture1Set, prev->texture[1].hwTextureSet); if (smesa->GlobalFlag & GFLAG_TEXTUREMIPMAP_1) MMIO(REG_3D_Texture1Mip, prev->texture[1].hwTextureMip); if (smesa->GlobalFlag & GFLAG_TEXBORDERCOLOR_1) { MMIO(REG_3D_Texture1BorderColor, prev->texture[1].hwTextureBorderColor); } if (smesa->GlobalFlag & GFLAG_TEXTUREADDRESS_1) { switch ((prev->texture[1].hwTextureSet & MASK_TextureLevel) >> 8) { case 11: MMIO(REG_3D_Texture1Address11, prev->texture[1].texOffset11); case 10: MMIO(REG_3D_Texture1Address10, prev->texture[1].texOffset10); MMIO(REG_3D_Texture1Pitch10, prev->texture[1].texPitch10); case 9: MMIO(REG_3D_Texture1Address9, prev->texture[1].texOffset9); case 8: MMIO(REG_3D_Texture1Address8, prev->texture[1].texOffset8); MMIO(REG_3D_Texture1Pitch8, prev->texture[1].texPitch89); case 7: MMIO(REG_3D_Texture1Address7, prev->texture[1].texOffset7); case 6: MMIO(REG_3D_Texture1Address6, prev->texture[1].texOffset6); MMIO(REG_3D_Texture1Pitch6, prev->texture[1].texPitch67); case 5: MMIO(REG_3D_Texture1Address5, prev->texture[1].texOffset5); case 4: MMIO(REG_3D_Texture1Address4, prev->texture[1].texOffset4); MMIO(REG_3D_Texture1Pitch4, prev->texture[1].texPitch45); case 3: MMIO(REG_3D_Texture1Address3, prev->texture[1].texOffset3); case 2: MMIO(REG_3D_Texture1Address2, prev->texture[1].texOffset2); MMIO(REG_3D_Texture1Pitch2, prev->texture[1].texPitch23); case 1: MMIO(REG_3D_Texture1Address1, prev->texture[1].texOffset1); case 0: MMIO(REG_3D_Texture1Address0, prev->texture[1].texOffset0); MMIO(REG_3D_Texture1Pitch0, prev->texture[1].texPitch01); } } /* texture environment */ if (smesa->GlobalFlag & GFLAG_TEXTUREENV) { MMIO(REG_3D_TextureBlendFactor, prev->hwTexEnvColor); MMIO(REG_3D_TextureColorBlendSet0, prev->hwTexBlendColor0); MMIO(REG_3D_TextureAlphaBlendSet0, prev->hwTexBlendAlpha0); } if (smesa->GlobalFlag & GFLAG_TEXTUREENV_1) { MMIO(REG_3D_TextureBlendFactor, prev->hwTexEnvColor); MMIO(REG_3D_TextureColorBlendSet1, prev->hwTexBlendColor1); MMIO(REG_3D_TextureAlphaBlendSet1, prev->hwTexBlendAlpha1); } smesa->GlobalFlag &= ~GFLAG_TEXTURE_STATES; }
void sis_update_render_state( sisContextPtr smesa ) { __GLSiSHardware *prev = &smesa->prev; mWait3DCmdQueue (45); if (smesa->GlobalFlag & GFLAG_ENABLESETTING) { if (!smesa->clearTexCache) { MMIO(REG_3D_TEnable, prev->hwCapEnable); } else { MMIO(REG_3D_TEnable, prev->hwCapEnable | MASK_TextureCacheClear); MMIO(REG_3D_TEnable, prev->hwCapEnable); smesa->clearTexCache = GL_FALSE; } } if (smesa->GlobalFlag & GFLAG_ENABLESETTING2) MMIO(REG_3D_TEnable2, prev->hwCapEnable2); /* Z Setting */ if (smesa->GlobalFlag & GFLAG_ZSETTING) { MMIO(REG_3D_ZSet, prev->hwZ); MMIO(REG_3D_ZStWriteMask, prev->hwZMask); MMIO(REG_3D_ZAddress, prev->hwOffsetZ); } /* Alpha Setting */ if (smesa->GlobalFlag & GFLAG_ALPHASETTING) MMIO(REG_3D_AlphaSet, prev->hwAlpha); if (smesa->GlobalFlag & GFLAG_DESTSETTING) { MMIO(REG_3D_DstSet, prev->hwDstSet); MMIO(REG_3D_DstAlphaWriteMask, prev->hwDstMask); MMIO(REG_3D_DstAddress, prev->hwOffsetDest); } /* Line Setting */ #if 0 if (smesa->GlobalFlag & GFLAG_LINESETTING) MMIO(REG_3D_LinePattern, prev->hwLinePattern); #endif /* Fog Setting */ if (smesa->GlobalFlag & GFLAG_FOGSETTING) { MMIO(REG_3D_FogSet, prev->hwFog); MMIO(REG_3D_FogInverseDistance, prev->hwFogInverse); MMIO(REG_3D_FogFarDistance, prev->hwFogFar); MMIO(REG_3D_FogFactorDensity, prev->hwFogDensity); } /* Stencil Setting */ if (smesa->GlobalFlag & GFLAG_STENCILSETTING) { MMIO(REG_3D_StencilSet, prev->hwStSetting); MMIO(REG_3D_StencilSet2, prev->hwStSetting2); } /* Miscellaneous Setting */ if (smesa->GlobalFlag & GFLAG_DSTBLEND) MMIO(REG_3D_DstBlendMode, prev->hwDstSrcBlend); if (smesa->GlobalFlag & GFLAG_CLIPPING) { MMIO(REG_3D_ClipTopBottom, prev->clipTopBottom); MMIO(REG_3D_ClipLeftRight, prev->clipLeftRight); } smesa->GlobalFlag &= ~GFLAG_RENDER_STATES; }
unsigned int ovl2_send_instr_plb( igd_display_context_t *display, ovl2_reg_plb_t *spritec_regs_plb, unsigned int flags) { unsigned char * mmio = MMIO(display); unsigned long tmp; inter_module_dispatch_t *md; platform_context_plb_t * platform; unsigned int pipe_num; unsigned long pipe_reg; int ret; EMGD_TRACE_ENTER; /* We dont need the CMD_WAIT_OVL2_PLB instruction coz * our alter_ovl code already querried status * for last flip completion before getting here. See * micro_prepare_ovl2_plb called by alter_ovl2_plb. * It calls query overlay before the next flip */ /* * If Overlay + FB Blend is requested and the FB is xRGB * turn on the ARGB format. */ if(ovl_context->fb_blend_ovl) { if ((flags & IGD_OVL_ALTER_ON) != IGD_OVL_ALTER_ON) { tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg); if((tmp & 0x3c000000) == 0x1c000000) { tmp = tmp & 0xc3FFFFFF; EMGD_WRITE32(tmp | 0x18000000, mmio + PLANE(display)->plane_reg); tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4); EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4); OS_SLEEP(100); } } else { tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg); if((tmp & 0x3c000000) == 0x18000000) { EMGD_WRITE32(tmp | 0x1c000000, mmio + PLANE(display)->plane_reg); tmp = EMGD_READ32(mmio + PLANE(display)->plane_reg + 4); EMGD_WRITE32(tmp, mmio + PLANE(display)->plane_reg + 4); } } } /* Send a load register instruction to write the Plane C sprite address * which is the trigger register. * This is an instruction, so it happens after blend, and since it * is an instruction, we do not have to poll waiting for it. */ EMGD_WRITE32(spritec_regs_plb->start, mmio + 0x72184); md = &display->context->mod_dispatch; platform = (platform_context_plb_t *)display->context-> platform_context; pipe_num = PIPE(display)->pipe_num; if(pipe_num){ pipe_reg = 0x71024; } else { pipe_reg = 0x70024; } if(md && md->set_flip_pending){ /* For second overlay, Poulsbo has no ISR bit * to reflect the flip pending for Display * Sprite C. So we use Pipe-B vblank status * as a substitute */ ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex); md->set_flip_pending(MMIO(display), pipe_reg); OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex); } ovl_context->sync2 = 0; display->context->dispatch.sync(display, IGD_PRIORITY_NORMAL, &ovl_context->sync2, IGD_SYNC_NONBLOCK); EMGD_TRACE_EXIT; return IGD_SUCCESS; }