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; }
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; }
/* 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; }
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!"); } }
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; }
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; }
/* * 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); }
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; }
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); } }
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; } } }
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); } }