/*! * * @param mmio * @param pipe_reg * @param time_interval * * @return 0 on success * @return 1 on failure */ int wait_for_vblank_timeout_plb( unsigned char *mmio, unsigned long pipe_reg, unsigned long time_interval) { int ret; unsigned long pipe_status_reg = pipe_reg + PIPE_STATUS_OFFSET; unsigned long tmp; os_alarm_t timeout; unsigned long request_for; EMGD_TRACE_ENTER; EMGD_DEBUG("Parameters: MMIO = %p, pipe_reg = %lx, time_interval = %lx", mmio, pipe_reg, time_interval); /* If pipe is off then just return */ if(!((1L<<31) & EMGD_READ32(EMGD_MMIO(mmio) + pipe_reg))) { EMGD_DEBUG("Pipe disabled/Off"); EMGD_TRACE_EXIT; return 1; } /* * When VGA plane is on the normal wait for vblank won't work * so just skip it. */ if(!(EMGD_READ32(EMGD_MMIO(mmio) + 0x71400) & 0x80000000)) { EMGD_DEBUG("VGA Plane On"); EMGD_TRACE_EXIT; return 1; } /* 1. Request the interrupt handler to record the next VBlank: */ request_for = VBINT_REQUEST(VBINT_WAIT, (pipe_status_reg == PIPEA_STAT) ? VBINT_PORT2 : VBINT_PORT4); mode_context->dispatch->full->request_vblanks(request_for, mmio); /* 2. Wait & poll for the next VBlank: */ timeout = OS_SET_ALARM(time_interval); do { OS_SCHEDULE(); tmp = mode_context->dispatch->full->vblank_occured(request_for); } while ((tmp == 0x00) && (!OS_TEST_ALARM(timeout))); if (tmp == 0) { EMGD_ERROR_EXIT("Timeout waiting for VBLANK"); ret = 0; } else { ret = 1; } /* 3. End our request for the next VBlank: */ mode_context->dispatch->full->end_request(request_for, mmio); EMGD_TRACE_EXIT; return ret; } /* wait_for_vblank_timeout_plb */
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 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; }
/*! * * @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 */