/*! * * @param context * * @return 0 */ static int pwr_init_plb(igd_context_t *context) { unsigned char *mmio; mmio = context->device_context.virt_mmadr; /* Reset CLKGATECTL and CLKGATECTLOVR */ EMGD_WRITE32(0x1111111, mmio + PSB_CR_CLKGATECTL); EMGD_WRITE32(0, mmio + PSB_CR_CLKGATECTL + 8); return 0; }
void dsp_control_plane_format_tnc(igd_context_t *context, int enable, int plane, igd_plane_t *plane_override) { igd_plane_t * pl = NULL; unsigned char *mmio = EMGD_MMIO(context->device_context.virt_mmadr); unsigned long tmp; if (plane_override == NULL) { pl = (plane == 0) ? &planea_tnc : &planeb_tnc; } else { pl = plane_override; } tmp = EMGD_READ32(mmio + pl->plane_reg); /* * Pixel format bits (29:26) are in plane control register 0x70180 for * Plane A and 0x71180 for Plane B * 0110 = XRGB pixel format * 0111 = ARGB pixel format * Note that the plane control register is double buffered and will be * updated on the next VBLANK operation so there is no need to sync with * an explicit VSYNC. */ if(enable) { if((tmp & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_RGB_8888) { tmp = tmp & (~(DSPxCNTR_SRC_FMT_MASK)); EMGD_WRITE32(tmp | DSPxCNTR_ARGB_8888, mmio + pl->plane_reg); EMGD_READ32(mmio + pl->plane_reg); tmp = EMGD_READ32(mmio + pl->plane_reg + 0x1c); EMGD_WRITE32(tmp, mmio + pl->plane_reg + 0x1c); EMGD_DEBUG("Changed pixel format from XRGB to ARGB\n"); } } else { if((tmp & DSPxCNTR_SRC_FMT_MASK) == DSPxCNTR_ARGB_8888) { tmp = tmp & (~(DSPxCNTR_SRC_FMT_MASK)); EMGD_WRITE32(tmp | DSPxCNTR_RGB_8888, mmio + pl->plane_reg); EMGD_READ32(mmio + pl->plane_reg); tmp = EMGD_READ32(mmio + pl->plane_reg + 0x1c); EMGD_WRITE32(tmp, mmio + pl->plane_reg + 0x1c); OS_SLEEP(100); EMGD_DEBUG("Changed pixel format from ARGB to XRGB\n"); } } EMGD_DEBUG("Plane register 0x%lX has value of 0x%X\n", pl->plane_reg, EMGD_READ32(mmio + pl->plane_reg)); }
/*! * * @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; }
/*! * * @param mmio * * @return void */ static void disable_vga_plb (unsigned char *mmio) { unsigned long temp; unsigned char sr01; EMGD_TRACE_ENTER; /* Disable VGA plane if it is enabled. */ temp = EMGD_READ32(EMGD_MMIO(mmio) + VGACNTRL); if ((temp & BIT31) == 0) { /* Read SR01 */ READ_VGA(mmio, SR_PORT, 0x01, sr01); /* Turn on SR01 bit 5 */ WRITE_VGA(mmio, SR_PORT, 0x01, sr01|BIT(5)); /* Wait for 30us */ OS_SLEEP(30); temp |= BIT31; /* set bit 31 to disable */ temp &= ~BIT30; /* clear bit 30 to get VGA display in normal size */ EMGD_WRITE32(temp, EMGD_MMIO(mmio) + VGACNTRL); } /* * When turing off the VGA plane the palette sometimes gets stuck. * if we do a couple reads to the palette it will unstuck. */ if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEA_CONF )) { EMGD_DEBUG("VGA Palette workaround"); EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A); EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_A); } if((1L<<31) & EMGD_READ32( EMGD_MMIO(mmio) + PIPEB_CONF )) { EMGD_DEBUG("VGA Palette workaround"); EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B); EMGD_READ32(EMGD_MMIO(mmio) + DPALETTE_B); } EMGD_TRACE_EXIT; }
/* * HHP: FIXME: * This should also be called when GMM/GTT is re-initialized, i.e. when * the Xorg server stops. The PVR backed memory is invalid when this happens, * so if we call this function from msvdx_driver_unload() when the module is * removed, the "fw_mem_info" and "dev_mem_context" are invalid. */ void msvdx_pvr_deinit(void) { drm_emgd_priv_t *priv; igd_context_t *context; platform_context_plb_t *platform; struct msvdx_pvr_info *pvr; IMG_BOOL mem_destroyed; int pid=0; unsigned char *mmio; priv = gpDrmDevice->dev_private; context = priv->context; platform = (platform_context_plb_t *)context->platform_context; mmio = context->device_context.virt_mmadr; pvr = platform->msvdx_pvr; //Reset MTX before unloading firmware EMGD_WRITE32(0x00000001, mmio + PSB_MSVDX_MTX_SOFT_RESET); if (pvr) { kthread_stop(pvr->kthread); if (pvr->fw_mem_info) PVRSRVFreeDeviceMemKM(pvr->sgx_cookie, pvr->fw_mem_info); PVRSRVDestroyDeviceMemContextKM(pvr->sgx_cookie, pvr->dev_mem_context, &mem_destroyed); // PVRSRVPerProcessDataDisconnect((IMG_UINT32)pvr->kthread->pid); PVRSRVPerProcessDataDisconnect((IMG_UINT32)pvr->pid); pid = pvr->pid; kfree(pvr); platform->msvdx_pvr = NULL; } }
static void reg_crtc_lut_set_plb( igd_context_t *context, emgd_crtc_t *emgd_crtc) { int i; unsigned long pal_reg; unsigned char *mmio; EMGD_TRACE_ENTER; mmio = context->device_context.virt_mmadr; if (emgd_crtc->crtc_id == 0) { /* If Pipe is enabled, restore Palette */ if ((emgd_crtc->crtc_id == 0 && ((EMGD_READ32(mmio + PIPEA_CONF) & PIPE_ENABLE) && (EMGD_READ32(mmio + PIPEASRC)))) || (emgd_crtc->crtc_id == 1 && ((EMGD_READ32(mmio + PIPEB_CONF) & PIPE_ENABLE) && (EMGD_READ32(mmio + PIPEBSRC))))) { pal_reg = (unsigned long)(mmio + DPALETTE_A + (emgd_crtc->crtc_id * (DPALETTE_B - DPALETTE_A))); /* Restore Pipe A Palette */ for (i=0; i<DAC_DATA_COUNT; i++) { EMGD_WRITE32((emgd_crtc->lut_r[i] << 16) | (emgd_crtc->lut_g[i] << 8) | emgd_crtc->lut_b[i], pal_reg + i*4); } } } EMGD_TRACE_EXIT; }
/*! * * @param context * * @return void */ static void reset_plane_pipe_ports_plb(igd_context_t *context) { igd_plane_t *plane; igd_display_pipe_t *pipe; igd_display_port_t *port,*tv_port=NULL; unsigned long temp; unsigned long i; unsigned char *mmio; inter_module_dispatch_t *md; EMGD_TRACE_ENTER; /* * Disable all plane, pipe and port registers because the * bios may have been using a different set. Only unset the * enable bit. */ mmio = EMGD_MMIO(context->device_context.virt_mmadr); md = &context->mod_dispatch; disable_vga_plb(EMGD_MMIO(mmio)); /* Turn off ports */ port = NULL; while((port = md->dsp_get_next_port(context, port, 0)) != NULL) { /* if the port is TV, then don't set the power to S3 as this causes * blank screen on analog port after killx or cosole mode, * probably because the external clock needs to be on till the pipes and * DPLLs are off */ if (port->pd_driver) { #ifndef CONFIG_FASTBOOT if(port->pd_type == PD_DISPLAY_TVOUT) { tv_port = port; }else { port->pd_driver->set_power(port->pd_context, IGD_POWERSTATE_D3); } #endif } /* Disable WRITE protection on PIPE B for parts with Int-LVDS*/ /* This should never happen as the panel power was set to D3 above */ if (port->port_reg == LVDSCNTR) { if(EMGD_READ32(EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL) & 0x1) { EMGD_WRITE32(0xABCD0000, EMGD_MMIO(mmio) + LVDS_PNL_PWR_CTL); i=0; while(i++ < 0x10) { OS_SLEEP(10); if((EMGD_READ32(EMGD_MMIO(mmio)+LVDS_PNL_PWR_STS)&BIT(31))==0) { break; } } } } temp = EMGD_READ32(EMGD_MMIO(mmio) + port->port_reg); EMGD_WRITE32((temp & ~BIT31), EMGD_MMIO(mmio) + port->port_reg); } plane = NULL; while ((plane = md->dsp_get_next_plane(context, plane, 1)) != NULL) { /* Only display display planes. * Leave cursor, VGA, overlay, sprite planes alone since they will * need a different disable bit/sequence. */ temp = EMGD_READ32(EMGD_MMIO(mmio) + plane->plane_reg); if ((plane->plane_features & IGD_PLANE_DISPLAY)) { if ( temp & BIT31 ) { if(plane->plane_reg == DSPACNTR) { EMGD_WRITE32((temp & device_data->plane_a_preserve), EMGD_MMIO(mmio) + plane->plane_reg); } else { /* if it's plane b or plane c */ EMGD_WRITE32((temp & device_data->plane_b_c_preserve), EMGD_MMIO(mmio) + plane->plane_reg); } EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4); } } else if ((plane->plane_features & IGD_PLANE_CURSOR)) { EMGD_WRITE32((temp & 0xffffffe8), EMGD_MMIO(mmio) + plane->plane_reg); EMGD_WRITE32(0, EMGD_MMIO(mmio) + plane->plane_reg+4); } } /* Turn off pipes */ pipe = NULL; while ((pipe = md->dsp_get_next_pipe(context, pipe, 0))) { wait_for_vblank_plb(EMGD_MMIO(mmio), pipe->pipe_reg); temp = EMGD_READ32(EMGD_MMIO(mmio) + pipe->pipe_reg); if ( temp & BIT31 ) { EMGD_WRITE32((temp & device_data->pipe_preserve), EMGD_MMIO(mmio) + pipe->pipe_reg); } } /* pipes and DPLLs are off, now set the power for TV */ if(tv_port && tv_port->pd_driver) { tv_port->pd_driver->set_power(tv_port->pd_context, IGD_POWERSTATE_D3); } EMGD_TRACE_EXIT; } /* end reset_plane_pipe_ports */
/*! * 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; }
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; }
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; }