Esempio n. 1
0
/**
 * Power off sequence for video mode MIPI panel.
 * NOTE: do NOT modify this function
 */
static int __dpi_panel_power_off(struct mdfld_dsi_config *dsi_config,
		struct panel_funcs *p_funcs)
{
	u32 val = 0;
	u32 tmp = 0;
	struct mdfld_dsi_hw_registers *regs;
	struct mdfld_dsi_hw_context *ctx;
	struct drm_device *dev;
	struct drm_psb_private *dev_priv;
	int retry;
	int i;
	int err = 0;
	u32 power_island = 0;
	int offset = 0;

	PSB_DEBUG_ENTRY("\n");

	if (!dsi_config)
		return -EINVAL;

	regs = &dsi_config->regs;
	ctx = &dsi_config->dsi_hw_context;
	dev = dsi_config->dev;
	dev_priv = dev->dev_private;

	ctx->dsparb = REG_READ(DSPARB);
	ctx->dsparb2 = REG_READ(DSPARB2);

	/* Don't reset brightness to 0.*/
	ctx->lastbrightnesslevel = psb_brightness;

	tmp = REG_READ(regs->pipeconf_reg);
        ctx->dspcntr = REG_READ(regs->dspcntr_reg);

	/*save color_coef (chrome) */
	for (i = 0; i < 6; i++)
		ctx->color_coef[i] = REG_READ(regs->color_coef_reg + (i<<2));

	/* save palette (gamma) */
	for (i = 0; i < 256; i++)
		ctx->palette[i] = REG_READ(regs->palette_reg + (i<<2));

	/*
	 * Couldn't disable the pipe until DRM_WAIT_ON signaled by last
	 * vblank event when playing video, otherwise the last vblank event
	 * will lost when pipe disabled before vblank interrupt coming
	 * sometimes.
	 */

	/*Disable panel*/
	val = ctx->dspcntr;
	REG_WRITE(regs->dspcntr_reg, (val & ~BIT31));
	/*Disable overlay & cursor panel assigned to this pipe*/
	REG_WRITE(regs->pipeconf_reg, (tmp | (0x000c0000)));

	/*Disable pipe*/
	val = REG_READ(regs->pipeconf_reg);
	ctx->pipeconf = val;
	REG_WRITE(regs->pipeconf_reg, (val & ~BIT31));

	/*wait for pipe disabling,
	  pipe synchronization plus , only avaiable when
	  timer generator is working*/
	if (REG_READ(regs->mipi_reg) & BIT31) {
		retry = 100000;
		while (--retry && (REG_READ(regs->pipeconf_reg) & BIT30))
			udelay(5);

		if (!retry) {
			DRM_ERROR("Failed to disable pipe\n");
			if (IS_MOFD(dev)) {
				/*
				 * FIXME: turn off the power island directly
				 * although failed to disable pipe.
				 */
				err = 0;
			} else
				err = -EAGAIN;
			goto power_off_err;
		}
	}

	/**
	 * Different panel may have different ways to have
	 * panel turned off. Support it!
	 */
	if (p_funcs && p_funcs->power_off) {
		if (p_funcs->power_off(dsi_config)) {
			DRM_ERROR("Failed to power off panel\n");
			err = -EAGAIN;
			goto power_off_err;
		}
	}

	/*Disable MIPI port*/
	REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));

	/*clear Low power output hold*/
	REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));

	/*Disable DSI controller*/
	REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));

	/*enter ULPS*/
	__dpi_enter_ulps_locked(dsi_config, offset);

	if (is_dual_dsi(dev)) {
		offset = 0x1000;
		/*Disable MIPI port*/
		REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));

		/*clear Low power output hold*/
		REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));
		offset = 0x800;
		/*Disable DSI controller*/
		REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));

		/*enter ULPS*/
		__dpi_enter_ulps_locked(dsi_config, offset);
		offset = 0x0;
	}

power_off_err:
	power_island = pipe_to_island(dsi_config->pipe);

	if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
		power_island |= OSPM_DISPLAY_MIO;

	if (is_dual_dsi(dev))
		power_island |= OSPM_DISPLAY_C;

	if (!power_island_put(power_island))
		return -EINVAL;

	return err;
}
void psb_RecalcAlternativeOutput(object_context_p obj_context)
{
    psb_driver_data_p driver_data = obj_context->driver_data;
    object_surface_p obj_surface = obj_context->current_render_target;
    int angle, new_rotate, i;
    int old_rotate = driver_data->msvdx_rotate_want;
    int mode = INIT_VALUE;
#ifdef TARGET_HAS_MULTIPLE_DISPLAY
    mode = psb_android_get_mds_mode((void*)driver_data->ws_priv);
#endif

    if (mode != INIT_VALUE) {
        // clear device rotation info
        if (driver_data->mipi0_rotation != VA_ROTATION_NONE) {
            driver_data->mipi0_rotation = VA_ROTATION_NONE;
            driver_data->hdmi_rotation = VA_ROTATION_NONE;
        }
        // Disable msvdx rotation if
        // WIDI video is play and meta data rotation angle is 0
        if (mode == WIDI_VIDEO_ISPLAYING) {
            if (driver_data->va_rotate == VA_ROTATION_NONE)
                driver_data->disable_msvdx_rotate = 1;
            else {
                driver_data->mipi0_rotation = 0;
                driver_data->hdmi_rotation = 0;
                driver_data->disable_msvdx_rotate = 0;
            }
        } else {
            if (IS_MOFD(driver_data))
                driver_data->disable_msvdx_rotate = 1;
            else
                driver_data->disable_msvdx_rotate = driver_data->disable_msvdx_rotate_backup;
        }
    } else if (IS_MOFD(driver_data)) {
    /* Moorefield has overlay rotaion, so decoder doesn't generate rotation
     * output according to windows manager. It is controlled by payload info
     * in which HWC signal decoder to generate rotation output
     */
        long long hwc_timestamp = 0;
        int index = -1;

        for (i = 0; i < obj_context->num_render_targets; i++) {
            object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]);
            /* traverse all surfaces' share info to find out the latest transform info */
            if (obj_surface && obj_surface->share_info) {
                if (obj_surface->share_info->hwc_timestamp > hwc_timestamp) {
                    hwc_timestamp = obj_surface->share_info->hwc_timestamp;
                    index = i;
                }
            }
        }
        if (index >= 0) {
            object_surface_p obj_surface = SURFACE(obj_context->render_targets[index]);
            if (obj_surface && obj_surface->share_info) {
                int transform = obj_surface->share_info->layer_transform;
                driver_data->mipi0_rotation = HAL2VAROTATION(transform);
                drv_debug_msg(VIDEO_DEBUG_GENERAL, "Signal from HWC to rotate %d\n", driver_data->mipi0_rotation);
            }
        }
    } else if (driver_data->native_window) {
        int display_rotate = 0;
        psb_android_surfaceflinger_rotate(driver_data->native_window, &display_rotate);
        drv_debug_msg(VIDEO_DEBUG_GENERAL, "NativeWindow(0x%x), get surface flinger rotate %d\n", driver_data->native_window, display_rotate);

        if (driver_data->mipi0_rotation != display_rotate) {
            driver_data->mipi0_rotation = display_rotate;
        }
    } else {
        long long hwc_timestamp = 0;
        int index = -1;

        for (i = 0; i < obj_context->num_render_targets; i++) {
            object_surface_p obj_surface = SURFACE(obj_context->render_targets[i]);
            /* traverse all surfaces' share info to find out the latest transform info */
            if (obj_surface && obj_surface->share_info) {
                if (obj_surface->share_info->hwc_timestamp > hwc_timestamp) {
                    hwc_timestamp = obj_surface->share_info->hwc_timestamp;
                    index = i;
                }
            }
        }
        if (index >= 0) {
            object_surface_p obj_surface = SURFACE(obj_context->render_targets[index]);
            if (obj_surface && obj_surface->share_info) {
                int transform = obj_surface->share_info->layer_transform;
                driver_data->mipi0_rotation = HAL2VAROTATION(transform);
            }
        }
    }

#ifdef PSBVIDEO_MRFL
    if ((mode == HDMI_VIDEO_ISPLAYING) && driver_data->native_window) {
        int display_rotate = 0;
        psb_android_surfaceflinger_rotate(driver_data->native_window, &display_rotate);
        drv_debug_msg(VIDEO_DEBUG_GENERAL, "NativeWindow(0x%x), get surface flinger rotate %d\n", driver_data->native_window, display_rotate);

        if (driver_data->mipi0_rotation != display_rotate && !IS_MOFD(driver_data)) {
            driver_data->mipi0_rotation = display_rotate;
        }
    }
#endif

    /* calc VA rotation and WM rotation, and assign to the final rotation degree */
    angle = Rotation2Angle(driver_data->va_rotate) + Rotation2Angle(driver_data->mipi0_rotation);
    driver_data->local_rotation = Angle2Rotation(angle);
    angle = Rotation2Angle(driver_data->va_rotate) + Rotation2Angle(driver_data->hdmi_rotation);
    driver_data->extend_rotation = Angle2Rotation(angle);

    /* On MOFD, no need to use meta rotation, just use rotation angle signal from HWC */
    if (IS_MOFD(driver_data)) {
        driver_data->local_rotation = driver_data->mipi0_rotation;
        driver_data->extend_rotation = Rotation2Angle(driver_data->hdmi_rotation);
    }

    /* for any case that local and extened rotation are not same, fallback to GPU */
    if ((driver_data->mipi1_rotation != VA_ROTATION_NONE) ||
        ((driver_data->local_rotation != VA_ROTATION_NONE) &&
         (driver_data->extend_rotation != VA_ROTATION_NONE) &&
         (driver_data->local_rotation != driver_data->extend_rotation))) {
        new_rotate = ROTATE_VA2MSVDX(driver_data->local_rotation);
        if (driver_data->is_android == 0) /*fallback to texblit path*/
            driver_data->output_method = PSB_PUTSURFACE_CTEXTURE;
    } else {
        if (driver_data->local_rotation == VA_ROTATION_NONE)
            new_rotate = driver_data->extend_rotation;
        else
            new_rotate = driver_data->local_rotation;

        if (driver_data->is_android == 0) {
            if (driver_data->output_method != PSB_PUTSURFACE_FORCE_CTEXTURE)
                driver_data->output_method = PSB_PUTSURFACE_COVERLAY;
        }
    }

    if (old_rotate != new_rotate) {
        drv_debug_msg(VIDEO_DEBUG_GENERAL, "MSVDX: new rotation %d desired\n", new_rotate);
        driver_data->msvdx_rotate_want = new_rotate;
    }

#ifdef TARGET_HAS_MULTIPLE_DISPLAY
    int scaling_buffer_width = 1920, scaling_buffer_height = 1080 ;
    int scaling_width = 0, scaling_height = 0;
    int scaling_offset_x = 0, scaling_offset_y = 0;
    int old_bufw = 0, old_bufh = 0, old_x = 0, old_y = 0, old_w = 0, old_h = 0;
    int bScaleChanged = 0, size = 0;
    unsigned char * surface_data;

    int ret = psb_android_get_mds_decoder_output_resolution(
                (void*)driver_data->ws_priv,
                &scaling_width, &scaling_height,
                &scaling_offset_x, &scaling_offset_y,
                &scaling_buffer_width, &scaling_buffer_height);

    if ((old_bufw != scaling_buffer_width) || (old_bufh != scaling_buffer_height) ||
        (old_x != scaling_offset_x) || (old_y != scaling_offset_y) ||
        (old_w != scaling_width) || (old_h != scaling_height)) {
        bScaleChanged = 1;
    }

    old_x = scaling_offset_x;
    old_y = scaling_offset_y;
    old_w = scaling_width;
    old_h = scaling_height;
    old_bufw = scaling_buffer_width;
    old_bufh = scaling_buffer_height;

    /* turn off ved downscaling if width and height are 0.
     * Besides, scaling_width and scaling_height must be a multiple of 2.
     */
    if (!ret || (!scaling_width || !scaling_height) ||
             (scaling_width & 1) || (scaling_height & 1)) {
        obj_context->msvdx_scaling = 0;
        obj_context->scaling_width = 0;
        obj_context->scaling_height = 0;
        obj_context->scaling_offset_x= 0;
        obj_context->scaling_offset_y = 0;
        obj_context->scaling_buffer_width = 0;
        obj_context->scaling_buffer_height = 0;
    } else {
        obj_context->msvdx_scaling = 1;
        obj_context->scaling_width = scaling_width;
        obj_context->scaling_height = scaling_height;
        obj_context->scaling_offset_x= scaling_offset_x;
        obj_context->scaling_offset_y = scaling_offset_y;
        obj_context->scaling_buffer_width = scaling_buffer_width;
        obj_context->scaling_buffer_height = scaling_buffer_height;
    }
    if (bScaleChanged) {
        if ((obj_surface != NULL) &&
            (obj_surface->out_loop_surface != NULL)) {
            if (psb_buffer_map(&obj_surface->out_loop_surface->buf, &surface_data)) {
                drv_debug_msg(VIDEO_DEBUG_ERROR, "Failed to map rotation buffer before clear it");
            }
            else {
                size = obj_surface->out_loop_surface->chroma_offset;
                memset(surface_data, 0, size);
                memset(surface_data + size, 0x80, obj_surface->out_loop_surface->size - size);
                psb_buffer_unmap(&obj_context->current_render_target->out_loop_surface->buf);
            }
        }
    }
#endif
}
Esempio n. 3
0
/**
 * Power off sequence for DBI interface
*/
int __dbi_power_off(struct mdfld_dsi_config *dsi_config)
{
    struct mdfld_dsi_hw_registers *regs;
    struct mdfld_dsi_hw_context *ctx;
    struct drm_device *dev;
    struct drm_psb_private *dev_priv;
    int err = 0;
    u32 power_island = 0;
    int retry,i;
    int offset = 0;
    u32 val;

    if (!dsi_config)
        return -EINVAL;

    PSB_DEBUG_ENTRY("\n");

    regs = &dsi_config->regs;
    ctx = &dsi_config->dsi_hw_context;
    dev = dsi_config->dev;
    dev_priv = dev->dev_private;

    ctx->dspcntr    = REG_READ(regs->dspcntr_reg);
    ctx->pipeconf   = REG_READ(regs->pipeconf_reg);

    ctx->dsparb = REG_READ(DSPARB);
    ctx->dsparb2 = REG_READ(DSPARB2);

    /*save color_coef (chrome) */
    for (i = 0; i < 6; i++)
        ctx->color_coef[i] = REG_READ(regs->color_coef_reg + (i<<2));

    /* save palette (gamma) */
    for (i = 0; i < 256; i++)
        ctx->palette[i] = REG_READ(regs->palette_reg + (i<<2));

    /*Disable plane*/
    val = ctx->dspcntr;
    REG_WRITE(regs->dspcntr_reg, (val & ~BIT31));

    /*Disable pipe*/
    /* Don't disable DSR mode. */
    REG_WRITE(regs->pipeconf_reg, (REG_READ(regs->pipeconf_reg) & ~BIT31));
    /*wait for pipe disabling,
      pipe synchronization plus , only avaiable when
      timer generator is working*/
    if (REG_READ(regs->mipi_reg) & BIT31) {
        retry = 100000;
        while (--retry && (REG_READ(regs->pipeconf_reg) & BIT30))
            udelay(5);

        if (!retry) {
            DRM_ERROR("Failed to disable pipe\n");
            if (IS_MOFD(dev)) {
                /*
                 * FIXME: turn off the power island directly
                 * although failed to disable pipe.
                 */
                err = 0;
            } else
                err = -EAGAIN;
            goto power_off_err;
        }
    }
    if (!is_dual_dsi(dev)) {
        /*enter ULPS*/
        __dbi_enter_ulps_locked(dsi_config, offset);
    } else {
        /*Disable MIPI port*/
        REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT31));
        /*clear Low power output hold*/
        REG_WRITE(regs->mipi_reg, (REG_READ(regs->mipi_reg) & ~BIT16));
        /*Disable DSI controller*/
        REG_WRITE(regs->device_ready_reg, (ctx->device_ready & ~BIT0));
        /*enter ULPS*/
        __dbi_enter_ulps_locked(dsi_config, offset);

        offset = 0x1000;
        /*Disable MIPI port*/
        REG_WRITE(regs->mipi_reg +offset,
                  (REG_READ(regs->mipi_reg + offset) & ~BIT31));
        /*clear Low power output hold*/
        REG_WRITE(regs->mipi_reg + offset,
                  (REG_READ(regs->mipi_reg + offset) & ~BIT16));

        offset = 0x800;
        /*Disable DSI controller*/
        REG_WRITE(regs->device_ready_reg + offset, (ctx->device_ready & ~BIT0));
        /*enter ULPS*/
        __dbi_enter_ulps_locked(dsi_config, offset);
        offset = 0x0;

    }
power_off_err:

    power_island = pipe_to_island(dsi_config->pipe);

    if (power_island & (OSPM_DISPLAY_A | OSPM_DISPLAY_C))
        power_island |= OSPM_DISPLAY_MIO;
    if (is_dual_dsi(dev))
        power_island |= OSPM_DISPLAY_C;

    if (!power_island_put(power_island))
        return -EINVAL;

    return err;
}