/*! * * @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; }
/*! * 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; }
/*! * Restore the VGA Register state from the specifed state buffer. * * @param context the current device context * @param vga_buffer this is where the VGA register state is saved * @param ar_regs AR registers to save * @param cr_regs CR registers to save * @param sr_regs SR registers to save * @param gr_regs GR registers to save * * @return 0 */ static int reg_restore_vga_plb( igd_context_t *context, vga_state_plb_t *vga_buffer, unsigned char *ar_regs, unsigned char *cr_regs, unsigned char *sr_regs, unsigned char *gr_regs) { unsigned long i; unsigned char *mmio; unsigned long bit_mask; mmio = context->device_context.virt_mmadr; /* Restore the plane latches. * * BP: I don't understand what this block is doing and it doesn't * seem necessary. Should check this against the spec and figure * out what it really does. */ /* Memory Mode Register */ WRITE_VGA(mmio, SR_PORT, SR04, 0x06); /* GR05, Graphics Mode Register */ WRITE_VGA(mmio, GR_PORT, GR05, 0x00); /* GR06, Micsellaneous Register */ WRITE_VGA(mmio, GR_PORT, GR06, 0x05); /* GR08, Bit Mask Register */ WRITE_VGA(mmio, GR_PORT, GR08, 0xFF); for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1) { /* Set plane select register */ WRITE_VGA(mmio, GR_PORT, GR04, i); /* Plane/Map mask register */ WRITE_VGA(mmio, SR_PORT, SR02, bit_mask); } for (i=0, bit_mask=1; i<PLANE_LATCH_COUNT; i++, bit_mask<<= 1) { /* Plane/Map mask register again?? */ WRITE_VGA(mmio, SR_PORT, SR02, bit_mask); } /* Restore standard VGA registers. * 2) Sequence registers * 1) MSR register * 3) CRTC registers * 4) Graphics registers * 5) Attribute registers * 6) VGA Feature register * 7) Index restisters */ WRITE_VGA(mmio, SR_PORT, SR00, 01); /* Do sync reset */ for (i=0; sr_regs[i] != 0xff; i++) { WRITE_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]); } EMGD_WRITE8(vga_buffer->msr, mmio + MSR_PORT); WRITE_VGA(mmio, SR_PORT, SR00, 0x03); /* Set to normal operation */ /* Unlock CRTC */ WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] & 0x7F); for (i=0; cr_regs[i] != 0xff; i++) { WRITE_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]); } for (i=0; gr_regs[i] != 0xff; i++) { WRITE_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]); } for (i=0; ar_regs[i] != 0xff; i++) { WRITE_AR(mmio, ar_regs[i], vga_buffer->ar[i]); } EMGD_WRITE8(vga_buffer->fcr, mmio + FEATURE_CONT_REG); /* Restore index registers. Is this necessary? */ EMGD_WRITE8(vga_buffer->sr_index, mmio + SR_PORT); EMGD_WRITE8(vga_buffer->cr_index, mmio + CR_PORT); EMGD_WRITE8(vga_buffer->gr_index, mmio + GR_PORT); /* Lock CRTC */ WRITE_VGA(mmio, CR_PORT, CR11, vga_buffer->cr[0x11] | 0x80); return 0; }
/*! * Saves the current VGA register state of the video chipset into the * given state buffer. * * This function first saves the 4 plane latches, and then it saves * the SR, GR, AR, CR registers. * * @param context the current device context * @param vga_buffer this is where the VGA register state is saved * @param ar_regs AR registers to save * @param cr_regs CR registers to save * @param sr_regs SR registers to save * @param gr_regs GR registers to save * * @return 0 */ static int reg_save_vga_plb( igd_context_t *context, vga_state_plb_t *vga_buffer, unsigned char *ar_regs, unsigned char *cr_regs, unsigned char *sr_regs, unsigned char *gr_regs) { unsigned char *mmio; int i; mmio = context->device_context.virt_mmadr; /* First, save a few registers that will be modified to read the latches. * We need to use GR04 to go through all the latches. Therefore, we must * first save GR04 before continuing. However, GR04 will only behave the * way we want it to if we are not in Odd/Even mode and not in Chain 4 * mode. Therefore, we have to make sure GR05 (GFX mode reg), * and SR04 (Mem Mode reg) are set properly. * According to B-spec, we are not supposed to program GR06 via MMIO. */ READ_VGA(mmio, GR_PORT, GR04, vga_buffer->gr[0x04]); READ_VGA(mmio, SR_PORT, SR04, vga_buffer->sr[0x04]); /* Memory Mode */ READ_VGA(mmio, GR_PORT, GR05, vga_buffer->gr[0x05]); /* GFX Mode Reg */ READ_VGA(mmio, GR_PORT, GR06, vga_buffer->gr[0x06]); /* Misc Reg */ WRITE_VGA(mmio, SR_PORT, SR04, 0x06); WRITE_VGA(mmio, GR_PORT, GR05, 0x00); WRITE_VGA(mmio, GR_PORT, GR06, 0x05); /* Save Memory Latch Data latches */ for (i=0; i<PLANE_LATCH_COUNT; i++) { WRITE_VGA(mmio, GR_PORT, GR04, (unsigned char)i); READ_VGA(mmio, CR_PORT, CR22, vga_buffer->plane_latches[i]); } /* Restore the modified regs */ WRITE_VGA(mmio, GR_PORT, GR06, vga_buffer->gr[0x06]); WRITE_VGA(mmio, GR_PORT, GR05, vga_buffer->gr[0x05]); WRITE_VGA(mmio, GR_PORT, GR04, vga_buffer->gr[0x04]); WRITE_VGA(mmio, SR_PORT, SR04, vga_buffer->sr[0x04]); /* Save Feature Controller register. */ vga_buffer->fcr = EMGD_READ8(mmio + FEATURE_CONT_REG_READ); /* Save Miscellaneous Output Register. */ vga_buffer->msr = EMGD_READ8(mmio + MSR_READ_PORT); /* Save index registers. */ vga_buffer->sr_index = EMGD_READ8(mmio + SR_PORT); vga_buffer->cr_index = EMGD_READ8(mmio + CR_PORT); vga_buffer->gr_index = EMGD_READ8(mmio + GR_PORT); #if 0 /* * Save the AR index register and last write status. Not sure that * this is really necessary so skip it for now. */ READ_VGA(mmio, CR_PORT, CR24, isARData); // Next write to AR index reg isARData &= 0x80; // Save AR index and last write status vga_buffer->ar_index = EMGD_READ8(mmio + AR_PORT) | isARData; #endif /* Save CRT Controller registers. */ for (i=0; cr_regs[i] != 0xff; i++) { READ_VGA(mmio, CR_PORT, cr_regs[i], vga_buffer->cr[i]); } /* Save Attribute Controller registers. */ for (i=0; ar_regs[i] != 0xff; i++) { READ_AR(mmio, (unsigned char)i, vga_buffer->ar[i]); } /* Save Graphics Controller registers. */ for (i=0; gr_regs[i] != 0xff; i++) { READ_VGA(mmio, GR_PORT, gr_regs[i], vga_buffer->gr[i]); } /* Save Sequencer registers. */ for (i=0; sr_regs[i] != 0xff; i++) { READ_VGA(mmio, SR_PORT, sr_regs[i], vga_buffer->sr[i]); } return 0; }