예제 #1
0
/*!
 * Get the stride and stereo values based on the display.  This is also used
 * by the MI instructions.
 *
 * @param display Pointer to hardware device instance data
 * @param stride
 * @param stereo
 * @param flags Should the stereo be for the frontbuffer or backbuffer?
 *
 * @return stride - Stride of the display
 * @return stereo - Stereo address of the display
 */
static int mode_get_stride_stereo_plb(igd_display_context_t *display,
	unsigned long *stride,
	unsigned long *stereo,
	unsigned long flags)
{
	unsigned long pitch = PLANE(display)->fb_info->screen_pitch;
	igd_timing_info_t *timing = PIPE(display)->timing;
	unsigned long base_offset;

	base_offset = PLANE(display)->fb_info->visible_offset;

	*stride = pitch;
	*stereo = 0;

	/* For field replication, valid for interlaced modes only
	 *     set stereo = fb_base,
	 *         stride = pitch
	 */
	if (timing->mode_info_flags & IGD_SCAN_INTERLACE) {

		if(timing->mode_info_flags & IGD_LINE_DOUBLE) {
			/* Interlaced + Line double flags means field replication.
			 * same lines are sent for both fields. Program the
			 * second eye to be same as the first.
			 */
			*stereo = base_offset;
		} else {
			/* Regular interlaced. Second eye starts on line 2.
			 * Skip every other line.
			 */
			*stereo = base_offset + pitch;
			*stride = pitch * 2;
		}
	}

	return 0;
}
예제 #2
0
/*!
 *
 * @param display Pointer to hardware device instance data
 *
 * @return void
 */
static void program_pipe_vga_plb(
	igd_display_context_t *display)
{
	igd_timing_info_t *timing;
	unsigned long vga_control;
	unsigned long upscale = 0;
	int centering = 1;

	EMGD_TRACE_ENTER;

#ifdef CONFIG_MICRO
	/*
	 * We cannot set a VGA mode unless the display planes are turned off.
     * This becomes evident during a Windows BSOD.  Since neither Windows
     * nor IEGD got a chance to turn off these registers, and the VGA mode was
     * set by the VBIOS, the screen gets corrupted.  In order to fix this
     * problem, we will turn the cursor and display planes here.
     *
     * Note: Removing previous partial-fix in favor of this complete one.
	 */
    /* Cursor A */
	WRITE_MMIO_REG(display, 0x70080, 0);
	WRITE_MMIO_REG(display, 0x70084, 0);
    /* Cursor B */
	WRITE_MMIO_REG(display, 0x700C0, 0);
	WRITE_MMIO_REG(display, 0x700C4, 0);
    /* Display A */
	WRITE_MMIO_REG(display, 0x70180, 0);
	WRITE_MMIO_REG(display, 0x70184, 0);
    /* Display B */
	WRITE_MMIO_REG(display, 0x71180, 0);
	WRITE_MMIO_REG(display, 0x71184, 0);
    /* Display C */
	WRITE_MMIO_REG(display, 0x72180, 0);
	WRITE_MMIO_REG(display, 0x72184, 0);
#endif

	/*
	 * VGA Plane can attach to only one pipe at a time. LVDS can
	 * only attach to pipe B. We need to use the display passed to
	 * determine the pipe number to use. (Plba is same as Alm).
	 */

	/*
	 * We can come here with following cases:
	 *   1. magic->vga    CRT, DVI type displays
	 *   2. native->vga   int-lvds, and up-scaling lvds displays
	 *   3. pipe->vga     TV and other unscaled-lvds displays
	 */
	vga_control = READ_MMIO_REG(display, 0x71400);
	vga_control &= 0x18e3ff00;
	vga_control |= 0x8e;

	timing = PIPE(display)->timing;
	if(!timing->extn_ptr) {
		EMGD_ERROR_EXIT("No Extension pointer in program_pipe_vga_plb");
		return;
	}

	/*
	 * FIXME: For CONFIG_NEW_MATCH this should be replaced with a simple
	 *  check of fp_native_dtd. Do not query the attribute.
	 */

	/* Find UPSCALING attr value*/
	pi_pd_find_attr_and_value(PORT_OWNER(display),
			PD_ATTR_ID_PANEL_FIT,
			0,/*no PD_FLAG for UPSCALING */
			NULL, /* dont need the attr ptr*/
			&upscale);
	/* this PI func will not modify value of upscale if attr does not exist */

	/* magic->vga or native->vga cases */
	if ((timing->width == 720 && timing->height == 400) || upscale) {
		centering = 0;
	}

	/* Enable border */
	if((timing->width >= 800) && !upscale) {
		EMGD_DEBUG("Enable VGA Border");
		vga_control |= (1L<<26);
	}

	if(timing->width == 640) {
		EMGD_DEBUG("Enable Nine Dot Disable");
		vga_control |= (1L<<18);
	}

	if(centering) {
		EMGD_DEBUG("Enable VGA Center Centering");
		vga_control |= 1L<<24;

		if(timing->height >= 960) {
			if(timing->width >= 1280) {
				EMGD_DEBUG("Enable VGA 2x (Nine Dot Disable)");
				vga_control |= (1L<<30) | (1L<<18);
			}
		}
	} else {
		if(PORT_OWNER(display)->port_type == IGD_PORT_LVDS) {
			EMGD_DEBUG("Enable VGA Upper-Left Centering & Nine Dot Disable");
			vga_control |= (1L<<25 | (1L<<18));
		} else if (upscale) {
			EMGD_DEBUG("Enable VGA Center Upper-left for upscale ports");
			vga_control |= 1L<<25;
		}
	}

	if(PIPE(display)->pipe_num) {
		vga_control |= 1L<<29;
	}

	program_pipe_vga(display, (igd_timing_info_t *)timing->extn_ptr);
	WRITE_MMIO_REG(display, 0x71400, vga_control);

	EMGD_TRACE_EXIT;
	return;
}
예제 #3
0
void WriteMBRDiskSignature(FILE* mbr, FILE* out)
{
  fseek(mbr, MBR_DISK_SIGNATURE_OFFSET, SEEK_CUR);
  PIPE(mbr, out, MBR_DISK_SIGNATURE_SIZE);
}
예제 #4
0
void WriteMBRCode(FILE* mbr, FILE* out)
{
  PIPE(mbr, out, MBR_CODE_SIZE);
}
예제 #5
0
void WriteMBRPartitionTable(FILE* mbr, FILE* out)
{
  fseek(mbr, MBR_PARTITION_TABLE_OFFSET, SEEK_CUR);
  PIPE(mbr, out, MBR_PARTITION_TABLE_SIZE);
}
예제 #6
0
/*!
 *
 * @param display
 * @param port_number
 * @param status
 *
 * @return 0 on success
 * @return -IGD_ERROR_INVAL on failure
 */
static int	program_port_plb(igd_display_context_t *display,
	unsigned short port_number,
	unsigned long status)
{
	unsigned long pipe_number;
	unsigned long port_control;
	unsigned long port_control_analog = 0;
	unsigned long mult_port_control;
	unsigned long pd_powerstate = 0;
	unsigned long upscale = 0;
	pd_timing_t *timing;
	pd_timing_t local_timing;
	unsigned long port_type;
	int ret;

	/* get the pipe	number */
	pipe_number = PIPE(display)->pipe_num;

	/* get the timings */
	timing = PIPE(display)->timing;

	/* keep the port type as local as we access it frequently */
	port_type = PORT(display, port_number)->port_type;

	/* Reading the preservation	bits */
	port_control = PORT(display, port_number)->preserve &
		READ_MMIO_REG(display, PORT(display, port_number)->port_reg);

	/* Reading the preservation bits for SDVO Gang Mode */
	mult_port_control = PORT(display, port_number)->mult_preserve &
		READ_MMIO_REG(display, PORT(display, port_number)->port_reg);

	/* If status is false, quickly disable the display */
	if(status == FALSE) {
		ret = PORT(display, port_number)->pd_driver->set_power(
				PORT(display, port_number)->pd_context, PD_POWER_MODE_D3);

		if (ret) {
			EMGD_ERROR_EXIT("PD set_power() returned: 0x%x", ret);
			return -IGD_ERROR_INVAL;
		}

		if(port_type == IGD_PORT_DIGITAL) {
			WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
					port_control);

			if(PORT(display, port_number)->mult_port) {
				/* either gang mode or RGBA */
				WRITE_MMIO_REG(display,
						PORT(display, port_number)->mult_port->port_reg,
						mult_port_control);
			}
		} else if (port_type == IGD_PORT_ANALOG) {
			port_control |= (BIT11 | BIT10);	 /* put in D3 state */
			WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
				port_control);

			return 0;
		}
		return 0;
	}

	EMGD_DEBUG("status isn't false, Check port enabled");

	if(! (PORT(display, port_number)->pt_info->flags & IGD_DISPLAY_ENABLE)) {
		return 0;
	}

	/*
	 * Is this is the magic mode then turn on VGA syncs
	 */
	EMGD_DEBUG("Check vga_sync");
	if(PORT(display, port_number)->vga_sync == 1) {
		/*
		 * Is this is the magic mode then turn on VGA syncs
		 */
		EMGD_DEBUG("VGA sync true, is width x height 720 x 400?");
		if((timing->width == 720) && (timing->height == 400)) {
			EMGD_DEBUG("Modify port control and multi_port_control");
			port_control |= (1L<<15);
			mult_port_control |= (1L<<15);
		}
	}

	EMGD_DEBUG("Check analog port");
	if(port_type == IGD_PORT_ANALOG) {
		port_control |= (0x80000000 | (pipe_number<<30));
		if(timing->mode_info_flags & IGD_VSYNC_HIGH) {
			port_control |= (1L<<4);
		}
		if(timing->mode_info_flags & IGD_HSYNC_HIGH) {
			port_control |= (1L<<3);
		}
		/* To differentiate	between	analog and other ports */
		port_control_analog = port_control;
	}

	EMGD_DEBUG("Get power state");
	EMGD_DEBUG("power state = %ld ", GET_DISPLAY_POWER_STATE(display, port_number));
	switch(GET_DISPLAY_POWER_STATE(display, port_number)) {
	case IGD_POWERSTATE_D0:
		EMGD_DEBUG("Power State is D0");
		pi_pd_find_attr_and_value(PORT(display, port_number),
			PD_ATTR_ID_PANEL_FIT,
			0, /*no PD_FLAG for UPSCALING */
			NULL, /* dont need the attr ptr*/
			&upscale);
		if(port_type == IGD_PORT_DIGITAL) {
			/* Reach the end timing if upscaling is enabled */
			if (timing->extn_ptr && upscale) {
				timing = (pd_timing_t *)timing->extn_ptr;
			}

			local_timing = *timing;
			if (upscale) {
				/* For timings smaller than width 360 and height 200,
				 * double the size. This is because the active area of the mode
				 * is double the size of the resolution for these modes
				 *  - Very tricky huh */
				if (local_timing.width <= 360) {
					local_timing.width <<= 1;
				}
				if (local_timing.height <= 200) {
					local_timing.height <<= 1;
				}
			}

			ret = PORT(display, port_number)->pd_driver->set_mode(
				PORT(display, port_number)->pd_context, &local_timing, 0);
			if (ret) {
				EMGD_ERROR_EXIT("PD set_mode returned: 0x%x", ret);
				return -IGD_ERROR_INVAL;
			}

			/* in Plba B-Speecs, there are no bits, *
			 * for the polarity of the H-sync/V-sync */

			/* in Plba B-Speecs, there are no bits,	 *
			 * for data ordering/format for DVO data */
			/* Gang-Mode and RGBA models are "exclusive-or" */
			if((PORT(display, port_number)->pd_driver->flags) &
					PD_FLAG_GANG_MODE) {
				mult_port_control |= (1L<<16);
			} else if(PORT(display, port_number)->pd_type == PD_DISPLAY_RGBA) {
				mult_port_control |= (1L<<2);
			}

			timing = PIPE(display)->timing;

			if(timing->dclk > 100000) {
				/* 100MPs < pixel rate < 200MPs */
				/* SDVO clock rate multiplier = 1x */
				/*
				port_control &=	~BIT23;
				mult_port_control |= ~BIT23;
					redundant code since BIT23 is
					already 0 at this point
				*/
			} else if(timing->dclk > 50000) {
				/* 50MPs < pixel rate < 100MPs */
				/* SDVO clock rate multiplier = 2x */
				port_control |= (1L<<23);
				mult_port_control |= (1L<<23);
			} else {
				/* 25MPs < pixel rate < 50MPs */
				/* SDVO clock rate multiplier = 4x */
				port_control |= (3L<<23);
				mult_port_control |= (3L<<23);
			}

			/*
			 * BIT7 = enable the border
			 *   Do we need to disable the SDVO border for native
			 *   VGA timings(i.e.,	use	DE)?
			 * BIT22->BIT19 = setup the clock phase-9
			 * BIT29 = enable the stall
			 *   Only set stall on DVO-B for gang mode
			 * BIT30 = pipe number
			 * BIT31 = port enable
			 */
			port_control |= ( ( pipe_number<<30 ) | (BIT31) | ((0x9l) << 19) |
					(BIT29) | (BIT7) );
			mult_port_control |= ( (BIT31) | ((0x9l) << 19) | (BIT7) );

			WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
					port_control);

			if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/
				WRITE_MMIO_REG(display,
						PORT(display, port_number)->mult_port->port_reg,
						mult_port_control);
			}
			return 0;
		} else if(port_type == IGD_PORT_LVDS) {
			/*
			 * There is	a special case for LVDS	scaling. If	the	timing is
			 * the native one and the extension	points to another non-vga
			 * mode	then send the extension	pointer.
			 */
			/* Reach the end timing to get user requested mode */
			if(timing->extn_ptr) {
				timing = (pd_timing_t *)timing->extn_ptr;
			}
		}
		/* set mode	will take care of port control */
		ret = PORT(display, port_number)->pd_driver->set_mode(
			PORT(display, port_number)->pd_context, (pd_timing_t *)timing,
			1<<PIPE(display)->pipe_num);
		if (ret) {
			EMGD_ERROR_EXIT("PD set_mode returned: 0x%x",ret);
			return -IGD_INVAL;
		}
		break;
	case IGD_POWERSTATE_D1:
		port_control_analog &= ~0x80000000;
		port_control_analog |= 0x00000800 &
			~(PORT(display, port_number)->preserve);
		pd_powerstate =PD_POWER_MODE_D1;
		break;
	case IGD_POWERSTATE_D2:
		port_control_analog &= ~0x80000000;
		port_control_analog |= 0x00000400 &
			~(PORT(display, port_number)->preserve);
		pd_powerstate = PD_POWER_MODE_D2;
		break;
	case IGD_POWERSTATE_D3:
		port_control_analog &= ~0x80000000;
		port_control_analog |= 0x00003c00 &
			~(PORT(display, port_number)->preserve);
		pd_powerstate = PD_POWER_MODE_D3;
		break;
	default:
		EMGD_ERROR_EXIT("Invalid power state: 0x%lx",
			GET_DISPLAY_POWER_STATE(display, port_number));
		return -IGD_ERROR_INVAL;
	}

	ret = PORT(display, port_number)->pd_driver->set_power(
			PORT(display, port_number)->pd_context, pd_powerstate);
	if (ret) {
		EMGD_ERROR_EXIT("PD set_power returned: 0x%x", ret);
		return -IGD_ERROR_INVAL;
	}

	if(port_type == IGD_PORT_DIGITAL) {
		EMGD_DEBUG("Port_control = 0x%lx", port_control);

		WRITE_MMIO_REG(display, PORT(display, port_number)->port_reg,
				port_control);
		if(PORT(display, port_number)->mult_port) { /* gang mode or rgba*/
			WRITE_MMIO_REG(display,
					PORT(display, port_number)->mult_port->port_reg,
					mult_port_control);
		}
	}

	EMGD_TRACE_EXIT;
	return 0;
}
예제 #7
0
int main(int argc, char *argv[]) {
  
	pid_t pid, gpid = getpid();
  int pipe_dsk[2], N, K, i;
  char tekst[MAX], tmp[10];
  struct pakiet paczka;
	struct info plan;
	
	
  if (argc != 3) fatal("Użycie: %s liczba_procesów liczba_obrotów\n",argv[0]);
	
  N = atoi(argv[1]); 
  K = atoi(argv[2]);
  
	if ((N <= 0) || K < 0) fatal("Podaj dodatnie liczby!\n");
  
  PIPE(pipe_dsk);
	printf("[%d] Konfiguracja:\n", gpid);
	printf("[%d] N= %d K= %d\n", gpid, N, K);
	printf("[%d] Utworzono łącze nienazwane...(o=%d, z=%d)\n\n", gpid, pipe_dsk[0], pipe_dsk[1]);

  /* Tworzenie struktury pierścienia: */
  switch (pid = fork()) {
    case -1:
	  	ERR("fork!");
	  
    case 0: /* Proces potomny: */
	/* Nie zamykamy deskryptora do zapisu - potrzebny jest dla ostaniego procesu, *
	 * zamykając go tutaj zamykamy go również dla procesów potomnych.             */
			sprintf(tmp, "%d", pipe_dsk[0]);
      execl("./proces", "proces", tmp, 0);
      ERR("execl!");
	  
    default: /* Proces macierzysty: */
	  	printf("[%d] Tworzenie pierscienia...\n", gpid);
			printf("[%d] Utworzono proces potomny: %d\n", gpid, pid);
	  	CLOSE(pipe_dsk[0]);
  /* Pozostalo wysłać do deskryptora informacje o parametrach pierścienia: */
	  	plan.licznik = N;
	  	plan.ostatni = pipe_dsk[1];			
	  	WRITE(pipe_dsk[1], &plan, INFO_ROZ);
  /* W pętli dodajemy kolejno słowa do przetworzenia przez pierscień procesów.     *
   * Wczytanie pustej linni powoduje wyjście z pętli. Zauważmy, iż pusta wiadomość *
   * zostanie wysłana przed wyjściem z pętli stanowi ona znak dla pierścienia, iż  *
	 * po przetworzeniu wszystkich słów krążących w nim program ma sie zakończyć.    *
	 * jeśli wyślemy zadlugi tekst, zostanie on podzielony na kilka pakietów.        */
	  	while (1) {
				fgets(tekst, MAX, stdin);
				for (i = 0; i < strlen(tekst); i++) if (tekst[i] == '\n') tekst[i] = '\0';
				tekst[MAX-1]='\0';
				strncpy(paczka.tresc, tekst, MAX);
				paczka.licznik = N*K;
				
				printf("[%d] Wysyłanie danych do pierścienia...(%d)\n", gpid, strlen(paczka.tresc));
    		WRITE(pipe_dsk[1], &paczka, sizeof(paczka));
				if (strlen(paczka.tresc) == 0) break;
	  	}
			printf("[%d] Wczytano pusty wiersz, kończenie programu...\n", gpid);
			printf("[%d] Zamykanie pierścienia...\n", gpid);
  /* Czekamy na zakonczenie wykonywania się procesu potomnego: */
	  	WAIT(0);
			printf("[%d] Pierścień zamknięty.\n", gpid);
			printf("[%d] Zamykanie deskryptora...\n", gpid);
	  	CLOSE(pipe_dsk[1]);
			printf("[%d] Koniec!\n", gpid);
    	exit(0);
  } 
}
예제 #8
0
/*!
 * This function sets up planes, pipes, and ports
 * with the configuration passed in and returnes either one
 * or two display handle lists.
 *
 * @param driver_handle from igd_init_driver().
 * @param primary on return, this points to a list of displays.
 * @param primary_ptinfo incoming timing info for the primary.
 * @param primary_fbinfo incoming framebuffer info.
 * @param secondary on return, this points to a list of displays.
 * @param secondary_fbinfo incoming framebuffer info.
 * @param dc display configuration
 * @param flags modify function behavior
 *
 * @return 0 on success
 * @return -IGD_INVAL on failure
 */
int igd_alter_displays(
	igd_driver_h driver_handle,
	igd_display_h *_primary,
	igd_display_info_t *primary_pt_info,
	igd_framebuffer_info_t *primary_fb_info,
	igd_display_h *_secondary,
	igd_display_info_t *secondary_pt_info,
	igd_framebuffer_info_t *secondary_fb_info,
	unsigned long dc,
	unsigned long flags)
{
	igd_context_t *context = (igd_context_t *)driver_handle;
	igd_display_context_t **primary = (igd_display_context_t **)_primary;
	igd_display_context_t **secondary = (igd_display_context_t **)_secondary;
	igd_framebuffer_info_t *fb_info = NULL;
	igd_display_context_t *display = NULL,*tv_display=NULL;
	int p;
	int ret;
	unsigned short tv_port_num=0;
	int p_chng = 1, s_chng = 1;
	unsigned char disable_plane_pipe = 0;
	unsigned long current_dc;

#if 0 /* Ian Elliott is taking this out ... see comment below */
#ifndef CONFIG_MICRO
	igd_framebuffer_info_t *plane_fb_info = NULL;
#endif
#endif /* 0 -- Ian is taking this out */

	EMGD_TRACE_ENTER;

	/*
	 * Make sure the DC is valid
	 *
	 * vBIOS won't be able to do this every time, for now only have
	 * the drivers's do the check.
	 */
#ifndef CONFIG_MICRO
	if (dc && !dsp_valid_dc(dc, 0)) {
		EMGD_ERROR_EXIT("Invalid display configuration: 0x%08lx", dc);
		return -IGD_ERROR_INVAL;
	}
#endif


	/*
	 * Can all display_info's and fb_info's be NULL?  I.E. make this
	 * function do an alloc of display handles only?  If so, then
	 * check for that condition and return without error. Otherwise
	 * return an error.
	 */
	if (dc && (!primary_pt_info && !primary_fb_info) &&
			(!secondary_pt_info && !secondary_fb_info)) {
		EMGD_ERROR_EXIT("Invalid timing and framebuffer info");
		return -IGD_ERROR_INVAL;
	}

#ifndef CONFIG_MICRO
	/* FIXME: GDK Change this to dispatch->idle() */
	if (dsp_wait_rb(mode_context->context) != 0) {
		return -IGD_ERROR_INVAL;
	}
#endif

	/* If seamless request is NOT set , then do reset_plane_pipe_ports
	 * else delay it until we cannot support it.
	 * If seamless is requested by the user and we CAN support it
	 * then we need to make sure reset_plane_pipe_ports is NOT
	 * called. That's the whole point anyway. Not to reset anything
	 * during seamless transition
	 */
	if(mode_context->seamless != TRUE) {

		/* Reset planes/pipes/ports before doing first alter display */
		if (mode_context->first_alter) {
			mode_context->dispatch->reset_plane_pipe_ports(
									mode_context->context);
			mode_context->first_alter = FALSE;
		}
	}

	current_dc = *(context->mod_dispatch.dsp_current_dc);

#ifndef CONFIG_MICRO
	/* Check if platform needs force alter
	* 	to make sure we run tuning code. This
	* 	is for TNC-B0 workaround.*/
	if (mode_context->dispatch->dsp_is_force_alter_required){
		if (mode_context->dispatch-> dsp_is_force_alter_required(context->
						mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(current_dc)],
						current_dc, dc)){
				flags |= IGD_FORCE_ALTER;
		}
	}
#endif

	/*
	 * Turn off the planes, pipes, and ports associated with the current
	 * DC. However, limit the change to the primary if the secondary
	 * display handle is NULL or limit the change to the secondary if the
	 * the pimary display handle is NULL.
	 */
	for (p = 7; p > 0; p--) {
		if (p > 4) {
			display = NULL;
			if (DC_PORT_NUMBER(current_dc, p)) {
				display = context->mod_dispatch.
					dsp_display_list[IGD_DC_SECONDARY(current_dc)];
				s_chng = TIMING_CHANGED(display, dc, current_dc,
						secondary_pt_info, secondary_fb_info,
						(unsigned long)0xfff00000, flags);
			}

			if (s_chng && display && secondary) {
		/* if the port is TV, then don't set the power to S3 as this causes
		 * blank screen and system hang on LVDS on FSDOS, probably because the
		 * external clock needs to be on till the pipes and
		 * DPLLs are off
		 */
				if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type ==
					PD_DISPLAY_TVOUT) {
					tv_display = display;
					tv_port_num = DC_PORT_NUMBER(current_dc, p);
				} else {
					ret = mode_context->dispatch->program_port(display,
					      DC_PORT_NUMBER(current_dc, p), FALSE);
				}
				/* The secondary pipe master */
				if (p == 5) {
					disable_plane_pipe = 1;
				}
			}
		} else {
			display = NULL;
			if (DC_PORT_NUMBER(current_dc, p)) {
				display = context->mod_dispatch.
					dsp_display_list[IGD_DC_PRIMARY(current_dc)];
				p_chng = TIMING_CHANGED(display, dc, current_dc,
						primary_pt_info, primary_fb_info,
						(unsigned long)0x000ffff0, flags);
			}

			if (p_chng && display && primary) {
		/* if the port is TV, then don't set the power to S3 as this causes
		 * blank screen and system hang on LVDS on FSDOS, probably because the
		 * external clock needs to be on till the pipes and
		 * DPLLs are off
		 */
				if(PORT(display,DC_PORT_NUMBER(current_dc, p))->pd_type ==
					PD_DISPLAY_TVOUT) {
					tv_display = display;
					tv_port_num = DC_PORT_NUMBER(current_dc, p);
				} else {
					ret = mode_context->dispatch->program_port(display,
				      DC_PORT_NUMBER(current_dc, p), FALSE);
				}
				/* The primary pipe master */
				if (p == 1) {
					disable_plane_pipe = 1;
				}
			}
		}

		/* Disable plane and pipe after disabling the ports */
		if (disable_plane_pipe) {
			if(mode_context->dispatch->full) {
				mode_context->dispatch->full->program_cursor(display, FALSE);
			}
			mode_context->dispatch->program_plane(display, FALSE);
			mode_context->dispatch->program_pipe(display, FALSE);
			/*pipes and dplls are off, now turn off tv port */
			if(tv_display) {
				ret = mode_context->dispatch->program_port(tv_display,
					tv_port_num, FALSE);
				tv_display = NULL;
			}
			disable_plane_pipe = 0;
		}
	}

#ifndef CONFIG_MICRO
	/* If DC is zero, then return here. A zero dc turns everything off */
	/* This never happens for VBIOS since it only always calls *
	 * alter_displays at the same point with the same valid DC */
	if (!dc) {
		int i;
		mode_context->dispatch->reset_plane_pipe_ports(mode_context->context);
		/* Should de-allocate everything here */
		dsp_alloc(driver_handle, dc, flags);
		/*
		 * FIXME: This should be done inside dsp alloc, mode module does
		 * not own this information.
		 * When dc = 0, set all displays allocated to 0.
		 */
		for (i=0; i<IGD_MAX_PORTS+1; i++) {
			if (context->mod_dispatch.dsp_display_list[i]) {
				context->mod_dispatch.dsp_display_list[i]->allocated = 0;
			}
			context->mod_dispatch.dsp_display_list[i] = NULL;
		}

		return 0;
	}
#endif

	/*
	 * Check the DC (display configuration). If it is the same as the
	 * current configuration, then don't change any allocations, only
	 * modify the framebuffers and timings.
	 */
	if (dc != current_dc) {
		EMGD_DEBUG("Allocate display handles based on DC");

#ifndef CONFIG_MICRO
		if (swap_required(current_dc, dc, primary)) {
			swap_fb_cursor();
		}
#endif
		/*
		 * This function should never be called after VBIOS initialization *
		 * The dsp_alloc is discarded after VBIOS init and is over-  *
		 * written by font tables. Thus in VBIOS IAL, alter_displays *
		 * is never get called with a different DC from the 1st time *
		 */
		dsp_alloc(driver_handle, dc, flags);

	}

	/* Attach the displays to the caller's pointers */
	if (primary) {
		*primary = context->mod_dispatch.dsp_display_list[IGD_DC_PRIMARY(dc)];
#ifndef CONFIG_MICRO
		if (*primary && context->mod_dispatch.alloc_queues) {
			ret = context->mod_dispatch.alloc_queues(driver_handle,
				(*primary)->pipe, flags);
			if (ret) {
				EMGD_ERROR("unable to allocate command queues");
			}
		}
#endif
	}
	if (secondary) {
		EMGD_DEBUG("Attaching display 1 to secondary pointer");
		*secondary = context->mod_dispatch.
			dsp_display_list[IGD_DC_SECONDARY(dc)];
#ifndef CONFIG_MICRO
		if (*secondary && context->mod_dispatch.alloc_queues) {
			ret = context->mod_dispatch.alloc_queues(driver_handle,
				(*secondary)->pipe, flags);
			if (ret) {
				EMGD_ERROR("unable to allocate command queues");
			}
		}
#endif
	}

	/*
	 * Configure the primary display. This configures the timings and the
	 * framebuffer. Once configured, it turns everythying on.
	 */
	if(primary && *primary && (primary_pt_info || primary_fb_info) && p_chng) {
		EMGD_DEBUG("Configure primary timings");
		/* make framebuffer changes */
		if (primary_fb_info) {
			/* set up new frame buffer info */
			fb_info = primary_fb_info;
		} else {
			fb_info = PLANE(*primary)->fb_info;
		}

		ret = configure_display(driver_handle,
				(igd_display_context_t *)(*primary), primary_pt_info,
				fb_info, dc, 0, 4, flags);
		if (ret) {
			EMGD_DEBUG("Primary display disabled.");
		}
	}

	/*
	 * Configure the secondary display. This configures the timings and the
	 * framebuffer. Once configured, it turns everythying on.
	 *
	 * How close is this code to the code for the primary?  Could this
	 * be moved to a separate function?
	 */
	if (secondary != NULL) {

#ifndef CONFIG_MICRO
		/*
		 * In the case where we are in extended or clone and our pipe is not
		 * turned on, we need to turn the pipes on.
		 * We can run into this situation on pre-Cantiga Gen platforms on Linux
		 * where LVDS was the primary display and was assigned PIPE B. Then we
		 * are switching from LVDS to another display and that other display
		 * wants to take PIPE A. In this case PIPE B will be turned on, the
		 * display's new port will take PIPE A and turn on PIPE A.  The second
		 * display thinks it is still PIPE A and nothing has changed for it.
		 * In this case where our pipe is not turned on, we need to let the
		 * system know that something has changed.
		 */
		if ((IGD_DC_CLONE(dc) || IGD_DC_EXTENDED(dc))
			&& !(EMGD_READ32(MMIO(*secondary) + PIPE(*secondary)->pipe_reg)
			& 0x80000000)) {
			s_chng = 1;
		}
#endif

		EMGD_DEBUG("Starting secondary pipe programming");
		if ((*secondary != NULL) && (secondary_pt_info || secondary_fb_info) &&
				s_chng){
			/*
			 * Configure the framebuffer.  For clone, it is the same
			 * as the primary. For DIH, it is a unique fb.
			 */
			EMGD_DEBUG("configure secondary framebuffer");
			if (dc & IGD_DISPLAY_CONFIG_CLONE) {
				fb_info = PLANE(*primary)->fb_info;
			} else {
				if (secondary_fb_info) {
					fb_info = secondary_fb_info;
				} else {
					fb_info = PLANE(*secondary)->fb_info;
				}
			}

			ret = configure_display(driver_handle,
					(igd_display_context_t *)(*secondary), secondary_pt_info,
					fb_info, dc, 4, 7, flags);
			if (ret) {
				EMGD_DEBUG("Secondary display disabled.");
				EMGD_ERROR("Secondary display disabled.");
			}
		}
	} else {
		EMGD_DEBUG("Skipped secondary programming, NULL handle");
	}

	/*
	 * Workaround: wait for Vblank to avoid people accessing display
	 * plane registers before the register is updated properly.
	 */
	if (primary && *primary) {
		EMGD_DEBUG("Wait for vblank on primary display (%p)", primary);
		EMGD_DEBUG("Wait for vblank on primary display (%p)", *primary);
		mode_context->dispatch->wait_vblank(*primary);
	} else if (secondary && *secondary) {
		EMGD_DEBUG("Wait for vblank on secondary display");
		mode_context->dispatch->wait_vblank(*secondary);
	}

	EMGD_TRACE_EXIT;
	return 0;
}
예제 #9
0
/*!
 * Update internal data structures for the plane, pipe, and port as
 * requested. Allocate a new framebuffer if the new parameters do not
 * match the existing framebuffer.
 *
 * @param display
 * @param port_number
 * @param timing
 * @param pt_info User supplied timing info to check.
 * @param fb_info User supplied framebuffer info.
 * @param flags
 *
 * @return 0 on success
 * @return -IGD_ERROR_INVAL on failure
 */
static int mode_update_plane_pipe_ports(
	igd_display_context_t *display,
	unsigned short port_number,
	igd_timing_info_t *timing,
	igd_framebuffer_info_t *fb_info,
	igd_display_info_t *pt_info,
	unsigned long flags)
{
	int ret;
	int alloc_fb;
	unsigned long size = 0;
	igd_framebuffer_info_t *plane_fb_info;
	igd_display_plane_t *mirror;

	EMGD_TRACE_ENTER;

	EMGD_DEBUG("Port Number (%d)", port_number);

	EMGD_ASSERT( (fb_info || pt_info), "ERROR: fb_info & pt_info are NULL",
		-IGD_ERROR_INVAL);

	EMGD_ASSERT( PLANE(display)->fb_info, "ERROR: fb_info in plane is NULL",
		-IGD_ERROR_INVAL);

	plane_fb_info = PLANE(display)->fb_info;
	mirror = PLANE(display)->mirror;

	/*
	 * If there is a mirror plane (for Clone) and the mirror is populated
	 * then update our plane from the mirror. If the mirror is not populated
	 * then update the mirror from ours.
	 */
	if (mirror) {
		if(mirror->fb_info->flags) {
			OS_MEMCPY(plane_fb_info, mirror->fb_info,
				sizeof(igd_framebuffer_info_t));
		} else {
			OS_MEMCPY(mirror->fb_info, plane_fb_info,
				sizeof(igd_framebuffer_info_t));
		}
	}

	if (PORT(display, port_number)->pt_info == NULL) {
		if ((PORT(display, port_number)->pt_info = (igd_display_info_t *)
				OS_ALLOC(sizeof(igd_display_info_t))) == NULL) {
			EMGD_ERROR_EXIT("unable to alloc a pt_info struct in pipe.");
			return -IGD_ERROR_INVAL;
		}
	}

	/*
	 * If the fb_info was provided, and either we were asked to update
	 * the internal structures via the flags, or we are allocating a new
	 * framebuffer.
	 */
	if(fb_info && (flags & MODE_UPDATE_PLANE)) {

		/* Assume we will be allocating a FB */
		alloc_fb = 1;

		/* If the frambuffer parameters are unchanged then do not re-alloc */
		if((fb_info->width == plane_fb_info->width) &&
			(fb_info->height == plane_fb_info->height) &&
			(fb_info->pixel_format == plane_fb_info->pixel_format) &&
			(fb_info->flags == plane_fb_info->flags)) {
			alloc_fb = 0;
		}

		/* Do not re-alloc a framebuffer if the re-use flag is set. */
		if(fb_info->flags & IGD_REUSE_FB) {
			alloc_fb = 0;
			/* May need to get the MIN_PITCH flags */
			plane_fb_info->flags = (fb_info->flags & IGD_FB_FLAGS_MASK) |
				(plane_fb_info->flags & ~IGD_FB_FLAGS_MASK);
		}

		/*
		 * If we don't have a framebuffer at all then we MUST allocate
		 * one.
		 */
		if(!plane_fb_info->allocated && !fb_info->allocated) {
			alloc_fb = 1;
		}

		EMGD_DEBUG("plane_fb_info->fb_base_offset = 0x%08lx",
			plane_fb_info->fb_base_offset);
		if(alloc_fb) {
			if(plane_fb_info->allocated) {
				/* Free frame buffer memory */
				display->context->dispatch.gmm_free(
					plane_fb_info->fb_base_offset);
				plane_fb_info->allocated = 0;
			}

			fb_info->fb_base_offset = plane_fb_info->fb_base_offset;
			/*
			 * Keep the FB flags, add in Displayable flag and blank out
			 * the rest. This insures that any tiled or usage flags from an
			 * earlier call do not get reused.
			 */
			fb_info->flags = (fb_info->flags & IGD_FB_FLAGS_MASK) |
				IGD_SURFACE_DISPLAY;

			/*
			 * Framebuffer allocations must always come from a reservation
			 * if the IAL changes the address the new address must also be
			 * from a reservation.
			 */
			GMM_SET_DEBUG_NAME("Framebuffer");
			ret = display->context->dispatch.gmm_alloc_surface(
				&fb_info->fb_base_offset,
				fb_info->pixel_format,
				&fb_info->width,
				&fb_info->height,
				&fb_info->screen_pitch,
				&size,
				IGD_GMM_ALLOC_TYPE_RESERVATION,
				&fb_info->flags);
			if(ret) {
				EMGD_ERROR_EXIT("Allocation of Front buffer failed: %d", ret);
				return ret;
			}
			fb_info->allocated = 1;
			/* Set the visible offset to the newly-allocated offset: */
			fb_info->visible_offset = fb_info->fb_base_offset;
		} else {
			/* If not reallocating, use back the offset in plane_fb_info */
			fb_info->fb_base_offset = plane_fb_info->fb_base_offset;
		}

		OS_MEMCPY(plane_fb_info, fb_info, sizeof(igd_framebuffer_info_t));
		plane_fb_info->allocated = 1;
		EMGD_DEBUG("plane_fb_info->fb_base_offset = 0x%08lx",
			plane_fb_info->fb_base_offset);

	}

	if(timing && (flags & MODE_UPDATE_PIPE)) {
		EMGD_DEBUG("Updating pipe timing.");
		PIPE(display)->timing = timing;
		PIPE(display)->owner = display;
	}

	if(pt_info && (flags & MODE_UPDATE_PORT)) {
		EMGD_DEBUG("OLD_PT========NEW PT ");
		IGD_PRINTK_PTINFO_2(PORT(display, port_number)->pt_info, pt_info);
		OS_MEMCPY(PORT(display, port_number)->pt_info, pt_info,
				sizeof(igd_display_info_t));
	}

	EMGD_TRACE_EXIT;
	return 0;
} /* end mode_update_plane_pipe_ports() */
예제 #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
int query_ovl2_tnc(igd_display_h display_h,
	unsigned int flags)
{
	igd_display_context_t *display = (igd_display_context_t *)display_h;
	inter_module_dispatch_t *md;
	platform_context_tnc_t * platform;
	os_alarm_t timeout;
	int ret;
	unsigned long pipe_reg, pipe_num;

	EMGD_TRACE_ENTER;

	switch (flags) {
	case IGD_OVL_QUERY_IS_HW_SUPPORTED:
		/* This is the second overlay, so HW overlay is not supported */
		break;

	case IGD_OVL_QUERY_IS_LAST_FLIP_DONE:
		/* If there no sync to wait on, then the last flip is done, and the
		 * Register Update has occured, simply return TRUE (Flip done).
		 */
		if (!ovl_context->sync2) {
			EMGD_DEBUG("Overlay already synced");
			EMGD_TRACE_EXIT;
			return TRUE;
		}

		/* According to the PBL B-spec, there doesnt seem to exist any bit
		 * for Sprite C Flip-Pending status. Testing 0x20AC in code during
		 * virt queue's REG write shows nothing changed for Bit8. Thus, we
		 * are using state of the VBLANK ISR bit as ovl2 flip status.
		 * Assumption is that if were running 2nd overlay, its either clone
		 * display or VEXT in WinCE. In either case, were not doing full screen
		 * FB flipping, so this check should be 'statefully' accurate
		 */
		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->check_flip_pending){
			ret = OS_PTHREAD_MUTEX_LOCK(&platform->flip_mutex);
			if(md->check_flip_pending(MMIO(display), pipe_reg)){
				OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
				EMGD_DEBUG("Overlay2 Sync done but Flip not done");
				return FALSE;
			}
			OS_PTHREAD_MUTEX_UNLOCK(&platform->flip_mutex);
		}

		/* Now that we know the last flip is done and the register update is
		 * complete, set the sync to 0 and return TRUE (Flip done). */
		ovl_context->sync2 = FLIP_DONE;
		break;
	case IGD_OVL_QUERY_WAIT_LAST_FLIP_DONE:
		/* Wait for 200 milliseconds for the last flip to complete.  If not
		 * done in that time, there is likely a hardware problem so return
		 * FALSE. */
		timeout = OS_SET_ALARM(200);
		do {
			if (TRUE ==
				query_ovl2_tnc(display_h, IGD_OVL_QUERY_IS_LAST_FLIP_DONE)) {
				EMGD_TRACE_EXIT;
				return TRUE;
			}
		} while (!OS_TEST_ALARM(timeout));
		EMGD_ERROR_EXIT("Timeout waiting for last flip done");
		return FALSE;
		break;
	case IGD_OVL_QUERY_IS_GAMMA_SUPPORTED:
		return TRUE;
		break;
	case IGD_OVL_QUERY_IS_VIDEO_PARAM_SUPPORTED:
		return TRUE;
		break;
	}

	EMGD_TRACE_EXIT;
	return TRUE;
}
예제 #12
0
unsigned int ovl2_check_tnc(igd_display_context_t *display,
	igd_surface_t       *src_surf,
	igd_rect_t          *src_rect,
	igd_rect_t          *dest_rect,
	igd_ovl_info_t      *ovl_info,
	unsigned int         flags)
{
	igd_timing_info_t *timing;
	unsigned int min_w, min_h;

	EMGD_TRACE_ENTER;

	if (!display){
	    EMGD_ERROR_EXIT("display is null");
	    return -IGD_ERROR_INVAL;
	}
	if (!PIPE(display)){
	    EMGD_ERROR_EXIT("PIPE(display) is null");
	    return -IGD_ERROR_INVAL;
	}

	timing = PIPE(display)->timing;

	/* The following parameters are only valid if the overlay is on, so
	 * return success if the overlay is being turned off. */
	if ((flags & IGD_OVL_ALTER_ON) == IGD_OVL_ALTER_OFF) {
		EMGD_TRACE_EXIT;
		return IGD_SUCCESS;
	}

	timing = PIPE(display)->timing;

	if(!timing) {
	    EMGD_ERROR_EXIT("timing is null\n");
	    return -IGD_ERROR_INVAL;
	}

	/*************************************************************************
	 * Ensure the framebuffer dotclock does not exceed the board SKU
	 * max dotclock
	 *************************************************************************/
	/* Make it chipset-specific */
	/* DCT-PC99TA crashes with dotclock > 300MHz */
	if(timing->dclk >= 340000){
		EMGD_ERROR_EXIT("Cannot support dotclock > 340MHz for this SKU");
		return -IGD_ERROR_HWERROR;
	}

	/*************************************************************************
	 * Ensure the overlay surface is ok and can be properly displayed.
	 * This ensures the following is valid:
	 *    - Ensure x1, x2, y1, y2 are pixel aligned
	 *    - 2 pixels or greater in width and height
	 *    - Pixel format is supported by the overlay
	 *    - Pitch is <= 16KB
	 *    - Based on the pixel format, the width is supported
	 *************************************************************************/
	if (!src_surf){
	    EMGD_ERROR_EXIT("src_surf is null");
	    return -IGD_ERROR_INVAL;
	}
	if (!src_rect){
	    EMGD_ERROR_EXIT("src_rect is null");
	    return -IGD_ERROR_INVAL;
	}
	/* Get the minimum size of 1 pixel in width and height for y, u, and v.
	 */
	min_w = 1 << get_uv_shift_x(src_surf->pixel_format);
	min_h = 1 << get_uv_shift_y(src_surf->pixel_format);

	if (((src_rect->x2 - src_rect->x1) < min_w*2) ||
		((src_rect->y2 - src_rect->y1) < min_h*2)) {
		EMGD_ERROR_EXIT(
			"Overlay2 source width or height is < 2 pixels (%dx%d)\n",
			src_rect->x2 - src_rect->x1, src_rect->y2 - src_rect->y1);
		return -IGD_ERROR_INVAL;
	}

	if (FALSE == ovl2_check_pf_tnc(display, src_surf->pixel_format)) {
		EMGD_ERROR_EXIT("Overlay2 source pixel format unsupported (pf:0x%lx)",
			src_surf->pixel_format);
		return -IGD_ERROR_HWERROR;
	}

	if (src_surf->pitch > 16384) {
		EMGD_ERROR_EXIT("Overlay2 source pitch (%d) > 16KB",
			src_surf->pitch);
		return -IGD_ERROR_HWERROR;
	}

	/*************************************************************************
	 * Ensure the location on the framebuffer is ok and can be properly
	 * displayed
	 * This ensures the following is valid:
	 *    - Greater than 1 pixel width and height
	 *    - Will be displayed on screen (not panned off)
	 *************************************************************************/
	if (!dest_rect){
	    EMGD_ERROR_EXIT("dest_rect is null");
	    return -IGD_ERROR_INVAL;
	}
	if (((dest_rect->x2 - dest_rect->x1) <= 1) ||
		((dest_rect->y2 - dest_rect->y1) <= 1)) {
		EMGD_ERROR_EXIT(
			"Overlay2 dest width or height is single pixel (%dx%d)\n",
			dest_rect->x2 - dest_rect->x1, dest_rect->y2 - dest_rect->y1);
		return -IGD_ERROR_INVAL;
	}

	if ((dest_rect->x1 >= timing->width) ||
		(dest_rect->y1 >= timing->height)) {
		EMGD_ERROR_EXIT(
			"Overlay2 dest is panned off the screen (%d,%d)\n",
			dest_rect->x1, dest_rect->y1);
		return -IGD_ERROR_INVAL;
	}

	EMGD_TRACE_EXIT;
	return IGD_SUCCESS;
}
예제 #13
0
파일: service.c 프로젝트: tg-x/gnunet
/**
 * Detach from terminal.
 *
 * @param sctx service context
 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
 */
static int
detach_terminal (struct GNUNET_SERVICE_Context *sctx)
{
#ifndef MINGW
  pid_t pid;
  int nullfd;
  int filedes[2];

  if (0 != PIPE (filedes))
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "pipe");
    return GNUNET_SYSERR;
  }
  pid = fork ();
  if (pid < 0)
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "fork");
    return GNUNET_SYSERR;
  }
  if (0 != pid)
  {
    /* Parent */
    char c;

    GNUNET_break (0 == CLOSE (filedes[1]));
    c = 'X';
    if (1 != READ (filedes[0], &c, sizeof (char)))
      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "read");
    fflush (stdout);
    switch (c)
    {
    case '.':
      exit (0);
    case 'I':
      LOG (GNUNET_ERROR_TYPE_INFO, _("Service process failed to initialize\n"));
      break;
    case 'S':
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Service process could not initialize server function\n"));
      break;
    case 'X':
      LOG (GNUNET_ERROR_TYPE_INFO,
           _("Service process failed to report status\n"));
      break;
    }
    exit (1);                   /* child reported error */
  }
  GNUNET_break (0 == CLOSE (0));
  GNUNET_break (0 == CLOSE (1));
  GNUNET_break (0 == CLOSE (filedes[0]));
  nullfd = OPEN ("/dev/null", O_RDWR | O_APPEND);
  if (nullfd < 0)
    return GNUNET_SYSERR;
  /* set stdin/stdout to /dev/null */
  if ((dup2 (nullfd, 0) < 0) || (dup2 (nullfd, 1) < 0))
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
    (void) CLOSE (nullfd);
    return GNUNET_SYSERR;
  }
  (void) CLOSE (nullfd);
  /* Detach from controlling terminal */
  pid = setsid ();
  if (-1 == pid)
    LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "setsid");
  sctx->ready_confirm_fd = filedes[1];
#else
  /* FIXME: we probably need to do something else
   * elsewhere in order to fork the process itself... */
  FreeConsole ();
#endif
  return GNUNET_OK;
}
예제 #14
0
/* Start the js process. */
static void js_start(void)
{
	int pid;
	char *jsprog;

#if defined(DOSLIKE) && !defined(HAVE_PTHREAD_H)
	debugPrint(5,
		   "no pthread, so no communication channels for javascript");
	allowJS = false;
	return;
#endif // defined(DOSLIKE) && !defined(HAVE_PTHREAD_H)

#ifndef DOSLIKE
/* doesn't hurt to do this more than once */
	signal(SIGPIPE, SIG_IGN);
#endif // !DOSLIKE

	debugPrint(5, "setting of communication channels for javascript");

	if (PIPE(pipe_in)) {
		i_puts(MSG_JSEnginePipe);
		allowJS = false;
		return;
	}

	if (PIPE(pipe_out)) {
		i_puts(MSG_JSEnginePipe);
		allowJS = false;
		close(pipe_in[0]);
		close(pipe_in[1]);
		return;
	}
#if defined(DOSLIKE)
#if defined(HAVE_PTHREAD_H)
	/* windows implementation of fork() using pthreads */
	pid = pthread_create(&tid, NULL, child_proc, 0);
#else // !HAVE_PTHREAD_h
	pid = 1;
#endif // HAVE_PTHREAD_H y/n
	if (pid) {
		i_puts(MSG_JSEngineFork);
		allowJS = false;
		close(pipe_in[0]);
		close(pipe_in[1]);
		close(pipe_out[0]);
		close(pipe_out[1]);
		return;
	}
	js_pid = 1;
#else // !(defined(DOSLIKE) && defined(HAVE_PTHREAD_H)
	pid = fork();
	if (pid < 0) {
		i_puts(MSG_JSEngineFork);
		allowJS = false;
		close(pipe_in[0]);
		close(pipe_in[1]);
		close(pipe_out[0]);
		close(pipe_out[1]);
		return;
	}

	if (pid) {		/* parent */
		js_pid = pid;
		close(pipe_in[1]);
		close(pipe_out[0]);
		return;
	}

/* child here, exec the back end js process */
	close(pipe_in[0]);
	close(pipe_out[1]);
	sprintf(arg1, "%d", pipe_out[0]);
	sprintf(arg2, "%d", pipe_in[1]);
	debugPrint(5, "spawning edbrowse-js %s %s", arg1, arg2);
	execlp(progname, "edbrowse", "--mode", "js", arg1, arg2, NULL);

/* oops, process did not exec */
/* write a message from this child, saying js would not exec */
	head.magic = EJ_MAGIC;
	head.highstat = EJ_HIGH_PROC_FAIL;
	head.lowstat = EJ_LOW_EXEC;
	write(pipe_in[1], &head, sizeof(head));
	exit(90);
#endif // defined(DOSLIKE) && defined(HAVE_PTHREAD_H) y/n
}				/* js_start */
예제 #15
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;
}
예제 #16
0
/*!
 * Configure either the primary or secondary display. This means all the
 * timings, the framebuffer, the ports, the plane, and the pipe.
 *
 * The port range could be calculated based on primary or secondary
 * display but it seems easier at this point to pass the port range
 * in since it is used for all the for loops.
 *
 * @param driver_handle
 * @param display
 * @param pt_info
 * @param fb_info
 * @param dc
 * @param p0
 * @param pn
 * @param flags
 *
 * @return 0 on success
 * @return -IGD_ERROR_INVAL on failure
 */
static int configure_display(
	igd_driver_h driver_handle,
	igd_display_context_t *display,
	igd_display_info_t *pt_info,
	igd_framebuffer_info_t *fb_info,
	unsigned long dc,
	int p0, int pn,
	unsigned long flags)
{
	igd_context_t *context = (igd_context_t *)driver_handle;
	int p;
	igd_display_port_t *port;
	igd_timing_info_t *timing_info;
	unsigned long update_flags;
	unsigned short port_number = 0;
	int ret;
	int seamless = FALSE;

	EMGD_TRACE_ENTER;

	/* FIXME: Should this be an assert? */
	if (display == NULL) {
		EMGD_DEBUG("Trying to configure a NULL display");
		return 0;
	}

	EMGD_DEBUG("Configure timings");
	for (p = pn; p > p0; p--) {
		EMGD_DEBUG("Configure port %d", DC_PORT_NUMBER(dc, p));
		if ((port_number = DC_PORT_NUMBER(dc, p))) {
			port = context->mod_dispatch.dsp_port_list[port_number];
			if (!port) {
				EMGD_DEBUG("Port %d not found", port_number);
			} else {

				/* Put a copy of the timings in the port's structure */
				if (pt_info) {
					if (port->pt_info == NULL) {
						port->pt_info = OS_ALLOC(sizeof(igd_display_info_t));
						if (!port->pt_info) {
							EMGD_ERROR_EXIT("unable to alloc a pt_info "
								"struct in port.");
							return -IGD_ERROR_INVAL;
						}
					}
					OS_MEMCPY(port->pt_info, pt_info,
						sizeof(igd_display_info_t));
				} else {
					EMGD_ERROR("No primary timing info!");
				}
			}
		}
	}

	if(!(pt_info->flags & IGD_DISPLAY_ENABLE)) {
		EMGD_ERROR_EXIT("Ptinfo has no IGD_DISPLAY_ENABLE!");
		return 0;
	}

	display->port_number = DC_PORT_NUMBER(dc, (p0 + 1));

	/* Set mode */
	EMGD_DEBUG("Set mode, using port %ld", display->port_number);
	port = PORT(display, display->port_number);

	EMGD_DEBUG("Calling matchmode on display");
	ret = match_mode(display, port->timing_table, fb_info, pt_info,
			&timing_info);
	if(ret) {
		EMGD_DEBUG("Match Mode for display failed");
		EMGD_TRACE_EXIT;
		return -IGD_ERROR_INVAL;
	}

	/* Now b4, we program the timing_info, let's first see if seamless
     * option is requested, if it is then
	 * We need to make sure the incoming dc, timing, framebuffer
	 * info and etc match. We must respect the FORCE_ALTER flag.
	 *
	 * Seamless option buys you a one-time ticket for the seamless
	 * experience from the firmware to the driver. After the first mode set
	 * in driver, you don't get it the next time when you alter display.
	 *
	 */
#ifndef CONFIG_MICRO
	if(dc &&  !(flags & IGD_FORCE_ALTER) &&
			 (mode_context->seamless == TRUE) ) {

		/* User wants seamless */
		if(mode_context->fw_info != NULL) {

			OPT_MICRO_CALL_RET(seamless, query_seamless(dc,
				/*(p0/4),*/
				PIPE(display)->pipe_num,
			    timing_info,
				fb_info,
				0));

			EMGD_DEBUG(":Seamless = %s", seamless ?"ON" : "OFF");
			mode_context->seamless = FALSE;
			/* FIXME: For clone you get called twice. Need to
			 * Fix that corner case
			 */

		}
	}
#endif
	/* In case the seamless is FALSE, we do reset_plane_pipe_ports
	 * which is supposed to be called in alter_displays anyway.
	 * But we have to delay it since the user asked for seamless.
	 * And we don't want to switch-off the display during
	 * seamless.
	 * Now we know that even though the user asked for it, we cannot
	 * support seamless, so we call reset_plane_pipe_ports now.
	 */
	if(seamless == FALSE) {

		/* Reset planes/pipes/ports before doing first alter display */
		if (mode_context->first_alter) {
			mode_context->dispatch->reset_plane_pipe_ports(
									mode_context->context);
			mode_context->first_alter = FALSE;
		}

	}

	if(calculate_eld(port, timing_info)){
		EMGD_DEBUG("Fail to calculate ELD");
	}
	/* turn on all ports */
	EMGD_DEBUG("turn on displays plane_pipe_ports %d..%d", (p0 + 1), (pn-1));

	for (p = (p0 + 1); p <= pn; p++) {
		if (DC_PORT_NUMBER(dc, p)) {
			port = context->mod_dispatch.dsp_port_list[DC_PORT_NUMBER(dc, p)];

			display->allocated = 1;

			/* Update mode info for the port */
			if (p == (p0 + 1)) {
				update_flags = MODE_UPDATE_PLANE | MODE_UPDATE_PIPE |
						MODE_UPDATE_PORT;
			} else {
				update_flags = MODE_UPDATE_PORT;
			}
			ret = mode_update_plane_pipe_ports(display, DC_PORT_NUMBER(dc, p),
					timing_info, fb_info, pt_info, update_flags);
			if (ret) {
				/*
				 * This could happen if there was no memory for the
				 * framebuffer or the FB was an invalid format. The
				 * first is a too bad failure. The second should have
				 * been checked by the IAL.
				 */
				EMGD_ERROR_EXIT("mode_update_plane_pipe_ports returned error "
					"%d", ret);
				port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
				return ret;
			}

			/* Program the port registers */
			if(seamless == TRUE) {
				/* Don't have to program the registers, Since it's
				 * all updated. Just return 0
				 */
				ret = 0;
			} else {
				ret = mode_context->dispatch->program_port(display,
					DC_PORT_NUMBER(dc, p), TRUE);
			}
			if (ret == 0) {
				port->inuse = 1;
			} else {
				port->pt_info->flags &= ~IGD_DISPLAY_ENABLE;
			}
		}
	}
	EMGD_DEBUG("done - turn on displays plane_pipe_ports %d", p);

	/* Clear the Framebuffer after the planes, pipes and ports are
	 * disabled and before they are enabled. */
	if (flags & IGD_CLEAR_FB) {
		OPT_MICRO_VOID_CALL(full_clear_fb(mode_context, fb_info, NULL));
	}

	/* program the pipe/plane/port if seamless is FALSE */
	if(seamless == FALSE) {

		EMGD_DEBUG("Seamless is FALSE");

		ret = TRUE;

		do{
		/* turn on pipe */
		mode_context->dispatch->program_pipe(display, TRUE);

		/* turn on plane */
		mode_context->dispatch->program_plane(display, TRUE);

		/* turn on port */
		for (p = pn; p > p0; p--) {
			if (DC_PORT_NUMBER(dc, p)) {
					mode_context->dispatch->post_program_port(display,
				DC_PORT_NUMBER(dc, p), TRUE);
			}
		}

			/* Check is display working fine */
			OPT_MICRO_CALL_RET(ret, mode_context->dispatch->
					check_display(display, DC_PORT_NUMBER(dc, p),TRUE));

			if(!ret){
				/* turn off plane and pipe */
				mode_context->dispatch->program_plane(display, FALSE);
				mode_context->dispatch->program_pipe(display, FALSE);
			}
		}while(!ret);

	}
#ifndef CONFIG_MICRO
	else  { /* Seamless is TRUE */

		/* Updating the plane registers, does not require us to
		 * turn-off the pipe and we can still have seamless
		 * because the display is not turned-off
		 */

		EMGD_DEBUG(" Seamless is TRUE");
		if(mode_context->fw_info->program_plane == 1) {

			/* This means we have to update the plane registers
			 * with the new values.eg. Change in pitch size between
			 * firmware values and driver values. But we MUST also
			 * update the palette registers for this to work and
			 * palette registers are programmed when pipe is programmed.
			 * This means we program the pipe , followed by the plane.
			 */

			/* By doing this, we update the palette */
			mode_context->dispatch->program_pipe(display, TRUE);

			/* update the plane registers */
			mode_context->dispatch->program_plane(display, TRUE);
		}
	}
#endif

	EMGD_TRACE_EXIT;
	return 0;
}
예제 #17
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;
}
예제 #18
0
/*!
 * This function checks whether a frame buffer swap and cursor
 * swap is required based on given current_dc and new_dc.
 *
 * @param current_dc current_dc the system is in.
 * @param dc     new requested dc.
 * @param dsp    pointer to a display context pointer
 *
 * @return 0 if no swap is required
 * @return 1 if swap is required
 */
int swap_required(
	unsigned long current_dc,
	unsigned long dc,
	igd_display_context_t **dsp)
{

	/*
	 * Note: Preserve the order of conditions as is. Changing the order
	 * of below conditions require relook into the whole function to
	 * make sure sematics match to return right value.
	 */

	/* Do not swap if no dc or current_dc */
	if (!dc || !current_dc) {
		return 0;
	}

	/*
	 * Do NOT swap the frame buffer and cursor if dc is going
	 * from twin to extended and not all the ports are moving to the other
	 * pipe. If all the ports are moving to the other pipe, then DO swap
	 * the frame buffer and cursor.
	 * We also need to make sure we are not in the special case where our
	 * extended mode contains LVDS and we are on a platform which does not
	 * support LVDS on PIPE A. In this case we do not want to swap here because
	 * we will not be swapping later since the twin configuration will stay on
	 * PIPE A so that the LVDS can move to PIPE B.
	 */
	if (IGD_DC_TWIN(current_dc) && IGD_DC_EXTENDED(dc)) {
		if (dsp && *dsp && all_ports_moving(current_dc, dc) &&
			!(dc_contains_port_type(dc, IGD_PORT_TYPE_LVDS) &&
			!(PIPE(*dsp)->pipe_features & IGD_PORT_SHARE_LVDS))) {
			return 1;
		} else {
			return 0;
		}
	}

	/*
	 * Do NOT swap if dc is changing from Single to clone or
	 * vice versa. In this case there is only 1 fb and no swap is required
	 * and it stays with primary display.
	 */
	if ((IGD_DC_SINGLE(current_dc) && IGD_DC_CLONE(dc)) ||
		(IGD_DC_CLONE(current_dc) && IGD_DC_SINGLE(dc))) {
		return 0;
	}

	/*
	 * If secondary master port is moving to primary master or
	 * primary master is moving to secondary master, try
	 * and keep the framebuffer address and cursor the same.
	 */
	if (DC_PORT_NUMBER(current_dc, 5) == DC_PORT_NUMBER(dc, 1) ||
		(DC_PORT_NUMBER(current_dc, 1) == DC_PORT_NUMBER(dc, 5))) {
		/*
		Note: This was previosuly return 1 to indicate swap required, which will cause
		a frame buffer swap when changing display from twin to clone. If the display is
		in extended mode before changing from twin to clone, then both Plane A and Plane B
		will point to the secondary frame buffer offset adress in clone mode and cause
		blank screen (.
		*/
		return 0;
	}
	return 0;
}
예제 #19
0
/* spawn a subprocess PROGNAME and pass it the arguments ARGV[]
   ARGV must be a NULL-terminated array of strings.
   Also pass it two arrays of strings: PIPE_TO_PROC[2] and PIPE_FROM_PROC[2].
   These are going to be the arrays of fds for the communication pipes 

   This function is protected from being called by more than one
   thread at a time by a mutex: the context is passed in for error handling.
*/
static int xsb_spawn (CTXTdeclc char *progname, char *argv[], int callno,
		      int pipe_to_proc[],
		      int pipe_from_proc[],int pipe_from_stderr[],
		      FILE *toprocess_fptr, FILE *fromprocess_fptr,
		      FILE *fromproc_stderr_fptr)
{
  int pid;
  int stdin_saved, stdout_saved, stderr_saved;
  static char shell_command[MAX_CMD_LEN];

  if ( (pipe_to_proc != NULL) && PIPE(pipe_to_proc) < 0 ) {
    /* can't open pipe to process */
    xsb_warn(CTXTc "[SPAWN_PROCESS] Can't open pipe for subprocess input");
    return PIPE_TO_PROC_FAILED;
  }
  if ( (pipe_from_proc != NULL) && PIPE(pipe_from_proc) < 0 ) {
    /* can't open pipe from process */
    xsb_warn(CTXTc "[SPAWN_PROCESS] Can't open pipe for subprocess output");
    return PIPE_FROM_PROC_FAILED;
  }
  if ( (pipe_from_stderr != NULL) && PIPE(pipe_from_stderr) < 0 ) {
    /* can't open stderr pipe from process */
    xsb_warn(CTXTc "[SPAWN_PROCESS] Can't open pipe for subprocess errors");
    return PIPE_FROM_PROC_FAILED;
  }

  /* The following is due to the awkwardness of windoze process creation.
     We commit this atrocity in order to be portable between Unix and Windows.
     1. Save stdio of the parent process.
     2. Redirect main process stdio to the pipes.
     3. Spawn subprocess. The subprocess inherits the redirected I/O
     4. Restore the original stdio for the parent process.

     On the bright side, this trick allowed us to cpature the I/O streams of
     the shell commands invoked by system()
  */

  /* save I/O */
  stdin_saved  = dup(fileno(stdin));
  stdout_saved = dup(fileno(stdout));
  stderr_saved = dup(fileno(stderr));
  if ((fileno(stdin) < 0) || (stdin_saved < 0))
    xsb_warn(CTXTc "[SPAWN_PROCESS] Bad stdin=%d; stdin closed by mistake?",
	     fileno(stdin));
  if ((fileno(stdout) < 0) || (stdout_saved < 0))
    xsb_warn(CTXTc "[SPAWN_PROCESS] Bad stdout=%d; stdout closed by mistake?",
	     fileno(stdout));
  if ((fileno(stderr) < 0) || (stderr_saved < 0))
    xsb_warn(CTXTc "[SPAWN_PROCESS] Bad stderr=%d; stderr closed by mistake?",
	     fileno(stderr));

  if (pipe_to_proc != NULL) {
    /* close child stdin, bind it to the reading part of pipe_to_proc */
    if (dup2(pipe_to_proc[0], fileno(stdin)) < 0) {
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't connect pipe %d to subprocess stdin",
	       pipe_to_proc[0]);
      return PIPE_TO_PROC_FAILED;
    }
    close(pipe_to_proc[0]); /* close the parent read end of pipe */
  }
  /* if stdin must be captured in an existing I/O port -- do it */
  if (toprocess_fptr != NULL)
    if (dup2(fileno(toprocess_fptr), fileno(stdin)) < 0) {
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't connect stream %d to subprocess stdin",
	       fileno(toprocess_fptr));
      return PIPE_TO_PROC_FAILED;
    }
  
  if (pipe_from_proc != NULL) {
    /* close child stdout, bind it to the write part of pipe_from_proc */
    if (dup2(pipe_from_proc[1], fileno(stdout)) < 0) {
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't connect subprocess stdout to pipe %d",
	       pipe_from_proc[1]);
      return PIPE_TO_PROC_FAILED;
    }
    close(pipe_from_proc[1]); /* close the parent write end of pipe */
  }
  /* if stdout must be captured in an existing I/O port -- do it */
  if (fromprocess_fptr != NULL)
    if (dup2(fileno(fromprocess_fptr), fileno(stdout)) < 0) {
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't connect subprocess stdout to stream %d",
	       fileno(fromprocess_fptr));
      return PIPE_TO_PROC_FAILED;
    }

  if (pipe_from_stderr != NULL) {
    /* close child stderr, bind it to the write part of pipe_from_proc */
    if (dup2(pipe_from_stderr[1], fileno(stderr)) < 0) {
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't connect subprocess stderr to pipe %d",
	       pipe_from_stderr[1]);
      return PIPE_TO_PROC_FAILED;
    }
    close(pipe_from_stderr[1]); /* close the parent write end of pipe */
  }
  /* if stderr must be captured in an existing I/O port -- do it */
  if (fromproc_stderr_fptr != NULL)
    if (dup2(fileno(fromproc_stderr_fptr), fileno(stderr)) < 0) {
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't connect subprocess stderr to stream %d",
	       fileno(fromproc_stderr_fptr));
      return PIPE_TO_PROC_FAILED;
    }

  if (callno == SPAWN_PROCESS) {
#ifdef WIN_NT

    static char bufQuoted[MAX_CMD_LEN + 2*(MAX_SUBPROC_PARAMS + 2)];
    const char * argvQuoted[MAX_SUBPROC_PARAMS + 2];
    char *  argq = bufQuoted;
    char *  arge = bufQuoted + sizeof(bufQuoted);
    char ** argp = argv;
    size_t  len  = 0; 
    int     i;

    for (i = 0; i < MAX_SUBPROC_PARAMS + 2; ++i) {
      if (*argp && (argq + (len = strlen(*argp)) + 4 < arge)) {
         argvQuoted[i] = argq;
         *argq++ = '"';
         strncpy(argq, *argp, len);
         argq += len;
         *argq++ = '"';
         *argq++ = '\0';
         ++argp;
      } else {
         *argq = '\0';
         argvQuoted[i] = 0;
         break;
      }
    }
    // MK: make the children ignore SIGINT
    SetConsoleCtrlHandler(NULL, TRUE);
    pid = (int)_spawnvp(P_NOWAIT, progname, argvQuoted);//should pid be Integer?
    // MK: restore the normal processing of SIGINT in the parent
    SetConsoleCtrlHandler(NULL, FALSE);
#else
    pid = fork();
#endif

    if (pid < 0) {
      /* failed */
      xsb_warn(CTXTc "[SPAWN_PROCESS] Can't fork off subprocess");
      return pid;
    } else if (pid == 0) {
      /* child process */

      /* Close the writing side of child's in-pipe. Must do this or else the
	 child won't see EOF when parent closes its end of this pipe. */
      if (pipe_to_proc != NULL) close(pipe_to_proc[1]);
      /* Close the reading part of child's out-pipe and stderr-pipe */
      if (pipe_from_proc != NULL) close(pipe_from_proc[0]);
      if (pipe_from_stderr != NULL) close(pipe_from_stderr[0]);
      
#ifdef WIN_NT
      // MK: Not used. Leaving as an example for possible future use
      //  The below call isn't used. We execute SetConsoleCtrlHandler(NULL,TRUE)
      //  in the parent, which passes the handling (Ctrl-C ignore) to children.
      //  Executing SetConsoleCtrlHandler in the child DOES NOT do much.
      // SetConsoleCtrlHandler((PHANDLER_ROUTINE) ctrl_C_handler, TRUE);
#else    /* Unix: must exec */
      // don't let keyboard interrupts kill subprocesses
      signal(SIGINT, SIG_IGN);
      execvp(progname, argv);
      /* if we ever get here, this means that invocation of the process has
	 failed */
      exit(SUB_PROC_FAILED);
#endif

    }
  } else { /* SHELL command */
    /* no separator */
    concat_array(CTXTc argv, "", shell_command, MAX_CMD_LEN);
    pid = system(shell_command);
  }

  /* main process continues */

  /* duplicate saved copies of stdio fds back into main process stdio */
  if (dup2(stdin_saved, fileno(stdin)) < 0) {
    perror("SPAWN_PROCESS");
    close(stdin_saved); close(stdout_saved); close(stderr_saved);
    return PIPE_TO_PROC_FAILED;
  }
  if (dup2(stdout_saved, fileno(stdout)) < 0) {
    perror("SPAWN_PROCESS");
    close(stdin_saved); close(stdout_saved); close(stderr_saved);
    return PIPE_TO_PROC_FAILED;
  }
  if (dup2(stderr_saved, fileno(stderr)) < 0) {
    perror("SPAWN_PROCESS");
    close(stdin_saved); close(stdout_saved); close(stderr_saved);
    return PIPE_TO_PROC_FAILED;
  }

  close(stdin_saved); close(stdout_saved); close(stderr_saved);
  return pid;
}
예제 #20
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;
}