/*! * 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; }