예제 #1
0
/*!
 *
 * @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;
}
예제 #2
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));
}
예제 #3
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;
}
예제 #4
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;
}
예제 #5
0
/*
 * 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;
	}

}
예제 #6
0
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;
}
예제 #7
0
/*!
 *
 * @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 */
예제 #8
0
/*!
 * 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;
}
예제 #9
0
/*!
 * 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;
}
예제 #10
0
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;
}
예제 #11
0
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;
}