Esempio n. 1
0
/*!
 * This function is directly exported.
 *
 * @param driver_handle
 * @param dsp
 * @param params
 *
 * @return 0 on success
 * @return 1 on failure
 */
int igd_module_init(igd_driver_h driver_handle,
	igd_dispatch_t **dsp,
	igd_param_t *params)
{
	igd_context_t *context = (igd_context_t *)driver_handle;
	device_context_t *device;
	int ret = 0;

	EMGD_TRACE_ENTER;

	device = &context->device_context;
	context->device_context.power_state = IGD_POWERSTATE_D0;
	context->mod_dispatch.init_params = params;
	context->dispatch.idle = empty_idle;
	context->dispatch.sync = empty_sync;
	context->mod_dispatch.in_dih_clone_mode = 0;
	context->mod_dispatch.dih_clone_display = 0;
	context->mod_dispatch.fb_blend_ovl_override = 0;

	/* Intialize IGD Modules */
	ret = init_modules(params, context);
	if (ret) {
		EMGD_ERROR_EXIT("Init Modules Failed");
		return ret;
	}

	OPT_MICRO_VOID_CALL(_init_dispatch(context));

	*dsp = &context->dispatch;

	EMGD_TRACE_EXIT;
	return 0;
}
Esempio n. 2
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;
}