Ejemplo n.º 1
0
static int omap_connector_mode_valid(struct drm_connector *connector,
				 struct drm_display_mode *mode)
{
	struct omap_connector *omap_connector = to_omap_connector(connector);
	struct omap_dss_device *dssdev = omap_connector->dssdev;
	struct omap_dss_driver *dssdrv = dssdev->driver;
	struct omap_video_timings timings = {0};
	struct drm_device *dev = connector->dev;
	struct drm_display_mode *new_mode;
	int ret = MODE_BAD;

	copy_timings_drm_to_omap(&timings, mode);
	mode->vrefresh = drm_mode_vrefresh(mode);

	if (!dssdrv->check_timings(dssdev, &timings)) {
		/* check if vrefresh is still valid */
		new_mode = drm_mode_duplicate(dev, mode);
		new_mode->clock = timings.pixel_clock;
		new_mode->vrefresh = 0;
		if (mode->vrefresh == drm_mode_vrefresh(new_mode))
			ret = MODE_OK;
		drm_mode_destroy(dev, new_mode);
	}

	DBG("connector: mode %s: "
			"%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
			(ret == MODE_OK) ? "valid" : "invalid",
			mode->base.id, mode->name, mode->vrefresh, mode->clock,
			mode->hdisplay, mode->hsync_start,
			mode->hsync_end, mode->htotal,
			mode->vdisplay, mode->vsync_start,
			mode->vsync_end, mode->vtotal, mode->type, mode->flags);

	return ret;
}
Ejemplo n.º 2
0
static int omap_connector_mode_valid(struct drm_connector *connector,
				 struct drm_display_mode *mode)
{
	struct omap_connector *omap_connector = to_omap_connector(connector);
	struct omap_dss_device *dssdev = omap_connector->dssdev;
	struct omap_dss_driver *dssdrv = dssdev->driver;
	struct videomode vm = {0};
	struct drm_device *dev = connector->dev;
	struct drm_display_mode *new_mode;
	int r, ret = MODE_BAD;

	drm_display_mode_to_videomode(mode, &vm);
	vm.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE |
		    DISPLAY_FLAGS_SYNC_NEGEDGE;
	mode->vrefresh = drm_mode_vrefresh(mode);

	/*
	 * if the panel driver doesn't have a check_timings, it's most likely
	 * a fixed resolution panel, check if the timings match with the
	 * panel's timings
	 */
	if (dssdrv->check_timings) {
		r = dssdrv->check_timings(dssdev, &vm);
	} else {
		struct videomode t = {0};

		dssdrv->get_timings(dssdev, &t);

		if (memcmp(&vm, &t, sizeof(struct videomode)))
			r = -EINVAL;
		else
			r = 0;
	}

	if (!r) {
		/* check if vrefresh is still valid */
		new_mode = drm_mode_duplicate(dev, mode);
		new_mode->clock = vm.pixelclock / 1000;
		new_mode->vrefresh = 0;
		if (mode->vrefresh == drm_mode_vrefresh(new_mode))
			ret = MODE_OK;
		drm_mode_destroy(dev, new_mode);
	}

	DBG("connector: mode %s: "
			"%d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
			(ret == MODE_OK) ? "valid" : "invalid",
			mode->base.id, mode->name, mode->vrefresh, mode->clock,
			mode->hdisplay, mode->hsync_start,
			mode->hsync_end, mode->htotal,
			mode->vdisplay, mode->vsync_start,
			mode->vsync_end, mode->vtotal, mode->type, mode->flags);

	return ret;
}
Ejemplo n.º 3
0
/* convert drm_display_mode to exynos_video_timings */
static inline void
convert_to_video_timing(struct fb_videomode *timing,
			struct drm_display_mode *mode)
{
	DRM_DEBUG_KMS("%s\n", __FILE__);

	memset(timing, 0, sizeof(*timing));

	timing->pixclock = mode->clock * 1000;
	timing->refresh = drm_mode_vrefresh(mode);

	timing->xres = mode->hdisplay;
	timing->left_margin = mode->hsync_start - mode->hdisplay;
	timing->hsync_len = mode->hsync_end - mode->hsync_start;
	timing->right_margin = mode->htotal - mode->hsync_end;

	timing->yres = mode->vdisplay;
	timing->upper_margin = mode->vsync_start - mode->vdisplay;
	timing->vsync_len = mode->vsync_end - mode->vsync_start;
	timing->lower_margin = mode->vtotal - mode->vsync_end;

	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		timing->vmode = FB_VMODE_INTERLACED;
	else
		timing->vmode = FB_VMODE_NONINTERLACED;

	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
		timing->vmode |= FB_VMODE_DOUBLE;
}
Ejemplo n.º 4
0
static void evdi_painter_send_mode_changed(struct evdi_painter *painter,
					   int32_t bits_per_pixel,
					   uint32_t pixel_format)
{
	struct evdi_event_mode_changed_pending *event;

	if (painter->drm_filp) {
		event = kzalloc(sizeof(*event), GFP_KERNEL);
		event->mode_changed.base.type = DRM_EVDI_EVENT_MODE_CHANGED;
		event->mode_changed.base.length = sizeof(event->mode_changed);

		event->mode_changed.hdisplay = painter->current_mode.hdisplay;
		event->mode_changed.vdisplay = painter->current_mode.vdisplay;
		event->mode_changed.vrefresh =
			drm_mode_vrefresh(&painter->current_mode);
		event->mode_changed.bits_per_pixel = bits_per_pixel;
		event->mode_changed.pixel_format = pixel_format;

		event->base.event = &event->mode_changed.base;
		event->base.file_priv = painter->drm_filp;
#if KERNEL_VERSION(4, 8, 0) > LINUX_VERSION_CODE
		event->base.destroy =
		    (void (*)(struct drm_pending_event *))kfree;
#endif
		evdi_painter_send_event(painter->drm_filp, &event->base.link);
	} else {
		 EVDI_WARN("Painter is not connected!");
	}
}
Ejemplo n.º 5
0
static enum drm_connector_status meson_connector_detect(struct drm_connector *connector, bool force)
{
	struct meson_connector *meson_connector = to_meson_connector(connector);
	int vrefresh = drm_mode_vrefresh(meson_connector->mode);
	enum meson_cvbs_switch_state s = meson_cvbs_get_switch_state();
	struct device *d = connector->dev->dev;

	if (!meson_connector->enabled)
		return connector_status_disconnected;

	/* PAL connector */
	if (vrefresh == 100 && s != MESON_CVBS_SWITCH_PAL) {
		dev_info(d, "CVBS/NTSC selected from switch\n");
		return connector_status_disconnected;
	}

	/* NTSC connector */
	if (vrefresh == 120 && s != MESON_CVBS_SWITCH_NTSC) {
		dev_info(d, "CVBS/PAL selected from switch\n");
		return connector_status_disconnected;
	}

	/* use the opposite from HPD -- HDMI connected means composite disconnected,
	 * HDMI disconnected means composite connected. */
	return read_hpd_gpio() ? connector_status_disconnected : connector_status_connected;
}
Ejemplo n.º 6
0
static int pingpong_tearcheck_setup(struct drm_encoder *encoder,
				    struct drm_display_mode *mode)
{
	struct mdp5_kms *mdp5_kms = get_kms(encoder);
	struct device *dev = encoder->dev->dev;
	u32 total_lines_x100, vclks_line, cfg;
	long vsync_clk_speed;
	struct mdp5_hw_mixer *mixer = mdp5_crtc_get_mixer(encoder->crtc);
	int pp_id = mixer->pp;

	if (IS_ERR_OR_NULL(mdp5_kms->vsync_clk)) {
		DRM_DEV_ERROR(dev, "vsync_clk is not initialized\n");
		return -EINVAL;
	}

	total_lines_x100 = mode->vtotal * drm_mode_vrefresh(mode);
	if (!total_lines_x100) {
		DRM_DEV_ERROR(dev, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
			      __func__, mode->vtotal, drm_mode_vrefresh(mode));
		return -EINVAL;
	}

	vsync_clk_speed = clk_round_rate(mdp5_kms->vsync_clk, VSYNC_CLK_RATE);
	if (vsync_clk_speed <= 0) {
		DRM_DEV_ERROR(dev, "vsync_clk round rate failed %ld\n",
							vsync_clk_speed);
		return -EINVAL;
	}
	vclks_line = vsync_clk_speed * 100 / total_lines_x100;

	cfg = MDP5_PP_SYNC_CONFIG_VSYNC_COUNTER_EN
		| MDP5_PP_SYNC_CONFIG_VSYNC_IN_EN;
	cfg |= MDP5_PP_SYNC_CONFIG_VSYNC_COUNT(vclks_line);

	mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_CONFIG_VSYNC(pp_id), cfg);
	mdp5_write(mdp5_kms,
		REG_MDP5_PP_SYNC_CONFIG_HEIGHT(pp_id), 0xfff0);
	mdp5_write(mdp5_kms,
		REG_MDP5_PP_VSYNC_INIT_VAL(pp_id), mode->vdisplay);
	mdp5_write(mdp5_kms, REG_MDP5_PP_RD_PTR_IRQ(pp_id), mode->vdisplay + 1);
	mdp5_write(mdp5_kms, REG_MDP5_PP_START_POS(pp_id), mode->vdisplay);
	mdp5_write(mdp5_kms, REG_MDP5_PP_SYNC_THRESH(pp_id),
			MDP5_PP_SYNC_THRESH_START(4) |
			MDP5_PP_SYNC_THRESH_CONTINUE(4));

	return 0;
}
Ejemplo n.º 7
0
/*
 * The controller should generate 2 frames before
 * preparing the peripheral.
 */
static void dw_mipi_dsi_wait_for_two_frames(struct drm_display_mode *mode)
{
	int refresh, two_frames;

	refresh = drm_mode_vrefresh(mode);
	two_frames = DIV_ROUND_UP(MSEC_PER_SEC, refresh) * 2;
	msleep(two_frames);
}
Ejemplo n.º 8
0
static int CRTConnectorHelperModeValid(struct drm_connector *psConnector, struct drm_display_mode *psMode)
{
	PVRPSB_DEVINFO *psDevInfo		= (PVRPSB_DEVINFO *)psConnector->dev->dev_private;
	const PVRPSB_PLL_RANGE *psPllRange	= NULL;
	int iModeStatus				= MODE_BAD;

	switch (psDevInfo->eDevice)
	{
		case PSB_CEDARVIEW:
			psPllRange = &sCdvNonLvds27PllRange;
			break;
		case PSB_POULSBO:
			psPllRange = &sPsbNonLvdsPllRange;
			break;
		case PSB_UNKNOWN:
			return iModeStatus;
	}

	if (psMode->flags & DRM_MODE_FLAG_INTERLACE)
	{
		iModeStatus = MODE_NO_INTERLACE;
	}
	else if (psMode->flags & DRM_MODE_FLAG_DBLSCAN)
	{
		iModeStatus = MODE_NO_DBLESCAN;
	}
	else if (psMode->clock < psPllRange->ui32DotClockMin)
	{
		iModeStatus = MODE_CLOCK_LOW;
	}
	else if (psMode->clock > psPllRange->ui32DotClockMax)
	{
		iModeStatus = MODE_CLOCK_HIGH;
	}
#if defined(PVRPSB_WIDTH) && defined(PVRPSB_HEIGHT)
	else if (drm_mode_width(psMode) != PVRPSB_WIDTH || drm_mode_height(psMode) != PVRPSB_HEIGHT)
	{
		iModeStatus = MODE_ONE_SIZE;
	}
#endif
#if defined(PVRPSB_VREFRESH)
	else if (drm_mode_vrefresh(psMode) != PVRPSB_VREFRESH)
	{
		iModeStatus = MODE_VSYNC;
	}
#endif
	else
	{
		iModeStatus = MODE_OK;
	}

	return iModeStatus;
}
Ejemplo n.º 9
0
void evdi_painter_mode_changed_notify(struct evdi_device *evdi,
				      struct drm_framebuffer *fb,
				      struct drm_display_mode *new_mode)
{
	struct evdi_painter *painter = evdi->painter;

	if (evdi_painter_replace_mode(painter, new_mode)) {
		EVDI_DEBUG(
		"(dev=%d) Notifying mode changed: %dx%d@%d; bpp %d; ",
		     evdi->dev_index, new_mode->hdisplay, new_mode->vdisplay,
		     drm_mode_vrefresh(new_mode), fb->bits_per_pixel);
		EVDI_DEBUG("pixel format %d\n", fb->pixel_format);

		evdi_painter_send_mode_changed(painter,
					       fb->bits_per_pixel,
					       fb->pixel_format);
	} else {
		EVDI_WARN("(dev=%d) Change mode duplicated - ignoring\n",
			  evdi->dev_index);
	}
}
Ejemplo n.º 10
0
static void rs780_get_pm_mode_parameters(struct radeon_device *rdev)
{
	struct igp_power_info *pi = rs780_get_pi(rdev);
	struct radeon_mode_info *minfo = &rdev->mode_info;
	struct drm_crtc *crtc;
	struct radeon_crtc *radeon_crtc;
	int i;

	/* defaults */
	pi->crtc_id = 0;
	pi->refresh_rate = 60;

	for (i = 0; i < rdev->num_crtc; i++) {
		crtc = (struct drm_crtc *)minfo->crtcs[i];
		if (crtc && crtc->enabled) {
			radeon_crtc = to_radeon_crtc(crtc);
			pi->crtc_id = radeon_crtc->crtc_id;
			if (crtc->mode.htotal && crtc->mode.vtotal)
				pi->refresh_rate = drm_mode_vrefresh(&crtc->mode);
			break;
		}
	}
}
Ejemplo n.º 11
0
static bool ast_get_vbios_mode_info(struct drm_crtc *crtc, struct drm_display_mode *mode,
                                    struct drm_display_mode *adjusted_mode,
                                    struct ast_vbios_mode_info *vbios_mode)
{
    struct ast_private *ast = crtc->dev->dev_private;
    u32 refresh_rate_index = 0, mode_id, color_index, refresh_rate;
    u32 hborder, vborder;
    bool check_sync;
    struct ast_vbios_enhtable *best = NULL;

    switch (crtc->primary->fb->bits_per_pixel) {
    case 8:
        vbios_mode->std_table = &vbios_stdtable[VGAModeIndex];
        color_index = VGAModeIndex - 1;
        break;
    case 16:
        vbios_mode->std_table = &vbios_stdtable[HiCModeIndex];
        color_index = HiCModeIndex;
        break;
    case 24:
    case 32:
        vbios_mode->std_table = &vbios_stdtable[TrueCModeIndex];
        color_index = TrueCModeIndex;
        break;
    default:
        return false;
    }

    switch (crtc->mode.crtc_hdisplay) {
    case 640:
        vbios_mode->enh_table = &res_640x480[refresh_rate_index];
        break;
    case 800:
        vbios_mode->enh_table = &res_800x600[refresh_rate_index];
        break;
    case 1024:
        vbios_mode->enh_table = &res_1024x768[refresh_rate_index];
        break;
    case 1280:
        if (crtc->mode.crtc_vdisplay == 800)
            vbios_mode->enh_table = &res_1280x800[refresh_rate_index];
        else
            vbios_mode->enh_table = &res_1280x1024[refresh_rate_index];
        break;
    case 1360:
        vbios_mode->enh_table = &res_1360x768[refresh_rate_index];
        break;
    case 1440:
        vbios_mode->enh_table = &res_1440x900[refresh_rate_index];
        break;
    case 1600:
        if (crtc->mode.crtc_vdisplay == 900)
            vbios_mode->enh_table = &res_1600x900[refresh_rate_index];
        else
            vbios_mode->enh_table = &res_1600x1200[refresh_rate_index];
        break;
    case 1680:
        vbios_mode->enh_table = &res_1680x1050[refresh_rate_index];
        break;
    case 1920:
        if (crtc->mode.crtc_vdisplay == 1080)
            vbios_mode->enh_table = &res_1920x1080[refresh_rate_index];
        else
            vbios_mode->enh_table = &res_1920x1200[refresh_rate_index];
        break;
    default:
        return false;
    }

    refresh_rate = drm_mode_vrefresh(mode);
    check_sync = vbios_mode->enh_table->flags & WideScreenMode;
    do {
        struct ast_vbios_enhtable *loop = vbios_mode->enh_table;

        while (loop->refresh_rate != 0xff) {
            if ((check_sync) &&
                    (((mode->flags & DRM_MODE_FLAG_NVSYNC)  &&
                      (loop->flags & PVSync))  ||
                     ((mode->flags & DRM_MODE_FLAG_PVSYNC)  &&
                      (loop->flags & NVSync))  ||
                     ((mode->flags & DRM_MODE_FLAG_NHSYNC)  &&
                      (loop->flags & PHSync))  ||
                     ((mode->flags & DRM_MODE_FLAG_PHSYNC)  &&
                      (loop->flags & NHSync)))) {
                loop++;
                continue;
            }
            if (loop->refresh_rate <= refresh_rate
                    && (!best || loop->refresh_rate > best->refresh_rate))
                best = loop;
            loop++;
        }
        if (best || !check_sync)
            break;
        check_sync = 0;
    } while (1);
    if (best)
        vbios_mode->enh_table = best;

    hborder = (vbios_mode->enh_table->flags & HBorder) ? 8 : 0;
    vborder = (vbios_mode->enh_table->flags & VBorder) ? 8 : 0;

    adjusted_mode->crtc_htotal = vbios_mode->enh_table->ht;
    adjusted_mode->crtc_hblank_start = vbios_mode->enh_table->hde + hborder;
    adjusted_mode->crtc_hblank_end = vbios_mode->enh_table->ht - hborder;
    adjusted_mode->crtc_hsync_start = vbios_mode->enh_table->hde + hborder +
                                      vbios_mode->enh_table->hfp;
    adjusted_mode->crtc_hsync_end = (vbios_mode->enh_table->hde + hborder +
                                     vbios_mode->enh_table->hfp +
                                     vbios_mode->enh_table->hsync);

    adjusted_mode->crtc_vtotal = vbios_mode->enh_table->vt;
    adjusted_mode->crtc_vblank_start = vbios_mode->enh_table->vde + vborder;
    adjusted_mode->crtc_vblank_end = vbios_mode->enh_table->vt - vborder;
    adjusted_mode->crtc_vsync_start = vbios_mode->enh_table->vde + vborder +
                                      vbios_mode->enh_table->vfp;
    adjusted_mode->crtc_vsync_end = (vbios_mode->enh_table->vde + vborder +
                                     vbios_mode->enh_table->vfp +
                                     vbios_mode->enh_table->vsync);

    refresh_rate_index = vbios_mode->enh_table->refresh_rate_index;
    mode_id = vbios_mode->enh_table->mode_id;

    if (ast->chip == AST1180) {
        /* TODO 1180 */
    } else {
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8c, (u8)((color_index & 0xf) << 4));
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8d, refresh_rate_index & 0xff);
        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x8e, mode_id & 0xff);

        ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0x00);
        if (vbios_mode->enh_table->flags & NewModeInfo) {
            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x91, 0xa8);
            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x92, crtc->primary->fb->bits_per_pixel);
            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x93, adjusted_mode->clock / 1000);
            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x94, adjusted_mode->crtc_hdisplay);
            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x95, adjusted_mode->crtc_hdisplay >> 8);

            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x96, adjusted_mode->crtc_vdisplay);
            ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0x97, adjusted_mode->crtc_vdisplay >> 8);
        }
    }