static int exynos_dp_get_modes(struct analogix_dp_plat_data *plat_data, struct drm_connector *connector) { struct exynos_dp_device *dp = to_dp(plat_data); struct drm_display_mode *mode; int num_modes = 0; if (dp->plat_data.panel) return num_modes; mode = drm_mode_create(connector->dev); if (!mode) { DRM_ERROR("failed to create a new display mode.\n"); return num_modes; } drm_display_mode_from_videomode(&dp->vm, mode); connector->display_info.width_mm = mode->width_mm; connector->display_info.height_mm = mode->height_mm; mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); return num_modes + 1; }
static struct drm_display_mode *sharp10x19_cmd_get_config_mode(void) { struct drm_display_mode *mode; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; mode->hdisplay = 1080; mode->hsync_start = mode->hdisplay + 8; mode->hsync_end = mode->hsync_start + 24; mode->htotal = mode->hsync_end + 8; mode->vdisplay = 1920; mode->vsync_start = 1923; mode->vsync_end = 1926; mode->vtotal = 1987; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; mode->type |= DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); return mode; }
static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, struct lvds_dvo_timing *dvo_timing) { panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo; panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + dvo_timing->hsync_pulse_width; panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo; panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + dvo_timing->vsync_off; panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + dvo_timing->vsync_pulse_width; panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; /* Some VBTs have bogus h/vtotal values */ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; drm_mode_set_name(panel_fixed_mode); }
/** * drm_mode_std - convert standard mode info (width, height, refresh) into mode * @t: standard timing params * * Take the standard timing params (in this case width, aspect, and refresh) * and convert them into a real mode using CVT. * * Punts for now, but should eventually use the FB layer's CVT based mode * generation code. */ struct drm_display_mode *drm_mode_std(struct drm_device *dev, struct std_timing *t) { // struct fb_videomode mode; // fb_find_mode_cvt(&mode, 0, 0); /* JJJ: convert to drm_display_mode */ struct drm_display_mode *mode; int hsize = t->hsize * 8 + 248, vsize; mode = drm_mode_create(dev); if (!mode) return NULL; if (t->aspect_ratio == 0) vsize = (hsize * 10) / 16; else if (t->aspect_ratio == 1) vsize = (hsize * 3) / 4; else if (t->aspect_ratio == 2) vsize = (hsize * 4) / 5; else vsize = (hsize * 9) / 16; drm_mode_set_name(mode); return mode; }
static int omap_connector_get_modes(struct drm_connector *connector) { 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 drm_device *dev = connector->dev; int n = 0; DBG("%s", omap_connector->dssdev->name); /* if display exposes EDID, then we parse that in the normal way to * build table of supported modes.. otherwise (ie. fixed resolution * LCD panels) we just return a single mode corresponding to the * currently configured timings: */ if (dssdrv->read_edid) { void *edid = kzalloc(MAX_EDID, GFP_KERNEL); if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) && drm_edid_is_valid(edid)) { drm_mode_connector_update_edid_property( connector, edid); n = drm_add_edid_modes(connector, edid); omap_connector->hdmi_mode = drm_detect_hdmi_monitor(edid); } else { drm_mode_connector_update_edid_property( connector, NULL); } kfree(edid); } else { struct drm_display_mode *mode = drm_mode_create(dev); struct videomode vm = {0}; dssdrv->get_timings(dssdev, &vm); drm_display_mode_from_videomode(&vm, mode); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); n = 1; } return n; }
/** * drm_mode_detailed - create a new mode from an EDID detailed timing section * @timing: EDID detailed timing info * @preferred: is this a preferred mode? * * An EDID detailed timing block contains enough info for us to create and * return a new struct drm_display_mode. The @preferred flag will be set * if this is the display's preferred timing, and we'll use it to indicate * to the other layers that this mode is desired. */ struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, struct detailed_timing *timing) { struct drm_display_mode *mode; struct detailed_pixel_timing *pt = &timing->data.pixel_data; if (pt->stereo) { printk(KERN_WARNING "stereo mode not supported\n"); return NULL; } if (!pt->separate_sync) { printk(KERN_WARNING "integrated sync not supported\n"); return NULL; } mode = drm_mode_create(dev); if (!mode) return NULL; mode->type = DRM_MODE_TYPE_DRIVER; mode->clock = timing->pixel_clock * 10; mode->hdisplay = (pt->hactive_hi << 8) | pt->hactive_lo; mode->hsync_start = mode->hdisplay + ((pt->hsync_offset_hi << 8) | pt->hsync_offset_lo); mode->hsync_end = mode->hsync_start + ((pt->hsync_pulse_width_hi << 8) | pt->hsync_pulse_width_lo); mode->htotal = mode->hdisplay + ((pt->hblank_hi << 8) | pt->hblank_lo); mode->vdisplay = (pt->vactive_hi << 8) | pt->vactive_lo; mode->vsync_start = mode->vdisplay + ((pt->vsync_offset_hi << 8) | pt->vsync_offset_lo); mode->vsync_end = mode->vsync_start + ((pt->vsync_pulse_width_hi << 8) | pt->vsync_pulse_width_lo); mode->vtotal = mode->vdisplay + ((pt->vblank_hi << 8) | pt->vblank_lo); drm_mode_set_name(mode); if (pt->interlaced) mode->flags |= V_INTERLACE; mode->flags |= pt->hsync_positive ? V_PHSYNC : V_NHSYNC; mode->flags |= pt->vsync_positive ? V_PVSYNC : V_NVSYNC; return mode; }
static int jzdrm_connector_get_modes(struct drm_connector *connector) { struct lcd_link *lcd_link = container_of(connector, struct lcd_link, connector); struct drm_display_mode *mode = drm_mode_create(connector->dev); int n; get_previous_mode(mode, lcd_link); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); n = 1; return n; }
static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, const struct lvds_dvo_timing *dvo_timing) { panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo; panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + dvo_timing->hsync_pulse_width; panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo; panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + dvo_timing->vsync_off; panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + dvo_timing->vsync_pulse_width; panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; panel_fixed_mode->width_mm = dvo_timing->h_image | ((dvo_timing->max_hv & 15) << 8); panel_fixed_mode->height_mm = dvo_timing->v_image | ((dvo_timing->max_hv >> 4) << 8); if (dvo_timing->hsync_positive) panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC; else panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC; if (dvo_timing->vsync_positive) panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC; else panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; /* Some VBTs have bogus h/vtotal values */ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; drm_mode_set_name(panel_fixed_mode); }
static int omap_connector_get_modes(struct drm_connector *connector) { 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 drm_device *dev = connector->dev; int n = 0; DBG("%s", omap_connector->dssdev->name); if (dssdrv->read_edid) { void *edid = kzalloc(MAX_EDID, GFP_KERNEL); if ((dssdrv->read_edid(dssdev, edid, MAX_EDID) > 0) && drm_edid_is_valid(edid)) { drm_mode_connector_update_edid_property( connector, edid); n = drm_add_edid_modes(connector, edid); kfree(connector->display_info.raw_edid); connector->display_info.raw_edid = edid; } else { drm_mode_connector_update_edid_property( connector, NULL); connector->display_info.raw_edid = NULL; kfree(edid); } } else { struct drm_display_mode *mode = drm_mode_create(dev); struct omap_video_timings timings; dssdrv->get_timings(dssdev, &timings); copy_timings_omap_to_drm(mode, &timings); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); n = 1; } return n; }
static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, const struct lvds_dvo_timing *dvo_timing) { panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo; panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + dvo_timing->hsync_pulse_width; panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo; panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + dvo_timing->vsync_off; panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + dvo_timing->vsync_pulse_width; panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; if (dvo_timing->hsync_positive) panel_fixed_mode->flags |= DRM_MODE_FLAG_PHSYNC; else panel_fixed_mode->flags |= DRM_MODE_FLAG_NHSYNC; if (dvo_timing->vsync_positive) panel_fixed_mode->flags |= DRM_MODE_FLAG_PVSYNC; else panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; drm_mode_set_name(panel_fixed_mode); }
struct drm_display_mode* pyr_cmd_get_config_mode(struct drm_device* dev) { struct drm_display_mode *mode; /*struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private;*/ /*struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;*/ PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay); PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay); PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start); PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end); PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal); PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start); PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end); PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal); PSB_DEBUG_ENTRY("clock is %d\n", mode->clock); mode->hdisplay = 480; mode->vdisplay = 864; mode->hsync_start = 487; mode->hsync_end = 490; mode->htotal = 499; mode->vsync_start = 874; mode->vsync_end = 878; mode->vtotal = 886; mode->clock = 25777; drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; return mode; }
static struct drm_display_mode *auo_cmd_get_config_mode(void) { struct drm_display_mode *mode; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; mode->hdisplay = 540; mode->vdisplay = 960; /* HFP = 40, HSYNC = 10, HBP = 20 */ mode->hsync_start = mode->hdisplay + 40; mode->hsync_end = mode->hsync_start + 10; mode->htotal = mode->hsync_end + 20; /* VFP = 4, VSYNC = 2, VBP = 4 */ mode->vsync_start = mode->vdisplay + 4; mode->vsync_end = mode->vsync_start + 2; mode->vtotal = mode->vsync_end + 4; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; mode->type |= DRM_MODE_TYPE_PREFERRED; PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay); PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay); PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start); PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end); PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal); PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start); PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end); PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal); PSB_DEBUG_ENTRY("clock is %d\n", mode->clock); drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); return mode; }
struct drm_display_mode *nt51021_get_modes(struct intel_dsi_device *dsi) { struct drm_display_mode *mode = NULL; /* Allocate */ mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) { DRM_DEBUG_KMS("AUO B101UAN01E Panel: No memory\n"); return NULL; } mode->hdisplay = 1200; //mode->hsync_start = mode->hdisplay + 100; //fp //mode->hsync_end = mode->hsync_start + 12; //sync //mode->htotal = mode->hsync_end + 20; //bp mode->hsync_start = mode->hdisplay + 42; //fp mode->hsync_end = mode->hsync_start + 1; //sync mode->htotal = mode->hsync_end + 32; //bp mode->vdisplay = 1920; mode->vsync_start = mode->vdisplay + 35; mode->vsync_end = mode->vsync_start + 1; mode->vtotal = mode->vsync_end + 25; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; /* Configure */ drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; printk("%s drm debug Loaded mode=%dx%d\n",__func__, mode->hdisplay, mode->vdisplay); return mode; }
static int s6e3ha2_get_modes(struct drm_panel *panel) { struct drm_connector *connector = panel->connector; struct s6e3ha2 *ctx = container_of(panel, struct s6e3ha2, panel); struct drm_display_mode *mode; mode = drm_mode_duplicate(panel->drm, ctx->desc->mode); if (!mode) { DRM_ERROR("failed to add mode %ux%ux@%u\n", ctx->desc->mode->hdisplay, ctx->desc->mode->vdisplay, ctx->desc->mode->vrefresh); return -ENOMEM; } drm_mode_set_name(mode); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); connector->display_info.width_mm = 71; connector->display_info.height_mm = 125; return 1; }
static struct drm_display_mode *bp080wx7_get_modes( struct intel_dsi_device *dsi) { struct drm_display_mode *mode = NULL; struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); DRM_DEBUG_KMS("\n"); /* Allocate */ mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) { DRM_DEBUG_KMS("Cpt panel: No memory\n"); return NULL; } /* Hardcode 800*1280 */ mode->hdisplay = 800; mode->hsync_start = mode->hdisplay + 16; mode->hsync_end = mode->hsync_start + 48; mode->htotal = mode->hsync_end + 16; mode->vdisplay = 1280; mode->vsync_start = mode->vdisplay + 4; mode->vsync_end = mode->vsync_start + 8; mode->vtotal = mode->vsync_end + 4; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; intel_dsi->pclk = mode->clock; /* Configure */ drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; return mode; }
static int exynos_drm_connector_get_modes(struct drm_connector *connector) { struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); struct exynos_drm_manager *manager = exynos_connector->manager; struct exynos_drm_display_ops *display_ops = manager->display_ops; struct edid *edid = NULL; unsigned int count = 0; int ret; if (!display_ops) { DRM_DEBUG_KMS("display_ops is null.\n"); return 0; } /* * if get_edid() exists then get_edid() callback of hdmi side * is called to get edid data through i2c interface else * get timing from the FIMD driver(display controller). * * P.S. in case of lcd panel, count is always 1 if success * because lcd panel has only one mode. */ if (display_ops->get_edid) { edid = display_ops->get_edid(manager->dev, connector); if (IS_ERR_OR_NULL(edid)) { ret = PTR_ERR(edid); edid = NULL; DRM_ERROR("Panel operation get_edid failed %d\n", ret); goto out; } count = drm_add_edid_modes(connector, edid); if (!count) { DRM_ERROR("Add edid modes failed %d\n", count); goto out; } drm_mode_connector_update_edid_property(connector, edid); } else { struct exynos_drm_panel_info *panel; struct drm_display_mode *mode = drm_mode_create(connector->dev); if (!mode) { DRM_ERROR("failed to create a new display mode.\n"); return 0; } if (display_ops->get_panel) panel = display_ops->get_panel(manager->dev); else { drm_mode_destroy(connector->dev, mode); return 0; } convert_to_display_mode(mode, panel); connector->display_info.width_mm = mode->width_mm; connector->display_info.height_mm = mode->height_mm; mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); count = 1; } out: kfree(edid); return count; }
struct drm_display_mode *otm1284a_vid_get_config_mode(void) { struct drm_display_mode *mode; mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; printk("[DISP] %s\n", __func__); if (lcd_id == ZE500ML_HSD) { /* RECOMMENDED PORCH SETTING HSA=18, HBP=48, HFP=64 VSA=3, VBP=14, VFP=9 Orise*/ mode->hdisplay = 720; mode->hsync_start = mode->hdisplay + 64; mode->hsync_end = mode->hsync_start + 18; mode->htotal = mode->hsync_end + 48; mode->vdisplay = 1280; mode->vsync_start = mode->vdisplay + 9; mode->vsync_end = mode->vsync_start + 3; mode->vtotal = mode->vsync_end + 14; } else if (lcd_id == ZE500ML_CTP || lcd_id == ZE550ML_CPT) { /* RECOMMENDED PORCH SETTING HSA=2, HBP=10, HFP=10 VSA=2, VBP=10, VFP=10 Orise*/ mode->hdisplay = 720; mode->hsync_start = mode->hdisplay + 10; mode->hsync_end = mode->hsync_start + 2; mode->htotal = mode->hsync_end + 10; mode->vdisplay = 1280; mode->vsync_start = mode->vdisplay + 10; mode->vsync_end = mode->vsync_start + 2; mode->vtotal = mode->vsync_end + 10; } else if (lcd_id == ZE550ML_TM || lcd_id == ZE550ML_TM_SR || lcd_id == ZE550ML_TM_MP) { /* RECOMMENDED PORCH SETTING HSA=12, HBP=64, HFP=64 VSA=5, VBP=13, VFP=10 Orise*/ mode->hdisplay = 720; mode->hsync_start = mode->hdisplay + 64; mode->hsync_end = mode->hsync_start + 12; mode->htotal = mode->hsync_end + 64; mode->vdisplay = 1280; mode->vsync_start = mode->vdisplay + 10; mode->vsync_end = mode->vsync_start + 5; mode->vtotal = mode->vsync_end + 13; } else { //TM /* RECOMMENDED PORCH SETTING HSA=2, HBP=42, HFP=44 VSA=2, VBP=14, VFP=16 Orise*/ mode->hdisplay = 720; mode->hsync_start = mode->hdisplay + 44; mode->hsync_end = mode->hsync_start + 2; mode->htotal = mode->hsync_end + 42; mode->vdisplay = 1280; mode->vsync_start = mode->vdisplay + 16; mode->vsync_end = mode->vsync_start + 2; mode->vtotal = mode->vsync_end + 14; } mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; mode->type |= DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); return mode; }
/** * drm_gtf_mode_complex - create the modeline based on full GTF algorithm * * @dev :drm device * @hdisplay :hdisplay size * @vdisplay :vdisplay size * @vrefresh :vrefresh rate. * @interlaced :whether the interlace is supported * @margins :desired margin size * @GTF_[MCKJ] :extended GTF formula parameters * * LOCKING. * none. * * return the modeline based on full GTF algorithm. * * GTF feature blocks specify C and J in multiples of 0.5, so we pass them * in here multiplied by two. For a C of 40, pass in 80. */ struct drm_display_mode * drm_gtf_mode_complex(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool interlaced, int margins, int GTF_M, int GTF_2C, int GTF_K, int GTF_2J) { /* 1) top/bottom margin size (% of height) - default: 1.8, */ #define GTF_MARGIN_PERCENTAGE 18 /* 2) character cell horizontal granularity (pixels) - default 8 */ #define GTF_CELL_GRAN 8 /* 3) Minimum vertical porch (lines) - default 3 */ #define GTF_MIN_V_PORCH 1 /* width of vsync in lines */ #define V_SYNC_RQD 3 /* width of hsync as % of total line */ #define H_SYNC_PERCENT 8 /* min time of vsync + back porch (microsec) */ #define MIN_VSYNC_PLUS_BP 550 /* C' and M' are part of the Blanking Duty Cycle computation */ #define GTF_C_PRIME ((((GTF_2C - GTF_2J) * GTF_K / 256) + GTF_2J) / 2) #define GTF_M_PRIME (GTF_K * GTF_M / 256) struct drm_display_mode *drm_mode; unsigned int hdisplay_rnd, vdisplay_rnd, vfieldrate_rqd; int top_margin, bottom_margin; int interlace; unsigned int hfreq_est; int vsync_plus_bp, vback_porch; unsigned int vtotal_lines, vfieldrate_est, hperiod; unsigned int vfield_rate, vframe_rate; int left_margin, right_margin; unsigned int total_active_pixels, ideal_duty_cycle; unsigned int hblank, total_pixels, pixel_freq; int hsync, hfront_porch, vodd_front_porch_lines; unsigned int tmp1, tmp2; drm_mode = drm_mode_create(dev); if (!drm_mode) return NULL; /* 1. In order to give correct results, the number of horizontal * pixels requested is first processed to ensure that it is divisible * by the character size, by rounding it to the nearest character * cell boundary: */ hdisplay_rnd = (hdisplay + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; hdisplay_rnd = hdisplay_rnd * GTF_CELL_GRAN; /* 2. If interlace is requested, the number of vertical lines assumed * by the calculation must be halved, as the computation calculates * the number of vertical lines per field. */ if (interlaced) vdisplay_rnd = vdisplay / 2; else vdisplay_rnd = vdisplay; /* 3. Find the frame rate required: */ if (interlaced) vfieldrate_rqd = vrefresh * 2; else vfieldrate_rqd = vrefresh; /* 4. Find number of lines in Top margin: */ top_margin = 0; if (margins) top_margin = (vdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / 1000; /* 5. Find number of lines in bottom margin: */ bottom_margin = top_margin; /* 6. If interlace is required, then set variable interlace: */ if (interlaced) interlace = 1; else interlace = 0; /* 7. Estimate the Horizontal frequency */ { tmp1 = (1000000 - MIN_VSYNC_PLUS_BP * vfieldrate_rqd) / 500; tmp2 = (vdisplay_rnd + 2 * top_margin + GTF_MIN_V_PORCH) * 2 + interlace; hfreq_est = (tmp2 * 1000 * vfieldrate_rqd) / tmp1; } /* 8. Find the number of lines in V sync + back porch */ /* [V SYNC+BP] = RINT(([MIN VSYNC+BP] * hfreq_est / 1000000)) */ vsync_plus_bp = MIN_VSYNC_PLUS_BP * hfreq_est / 1000; vsync_plus_bp = (vsync_plus_bp + 500) / 1000; /* 9. Find the number of lines in V back porch alone: */ vback_porch = vsync_plus_bp - V_SYNC_RQD; /* 10. Find the total number of lines in Vertical field period: */ vtotal_lines = vdisplay_rnd + top_margin + bottom_margin + vsync_plus_bp + GTF_MIN_V_PORCH; /* 11. Estimate the Vertical field frequency: */ vfieldrate_est = hfreq_est / vtotal_lines; /* 12. Find the actual horizontal period: */ hperiod = 1000000 / (vfieldrate_rqd * vtotal_lines); /* 13. Find the actual Vertical field frequency: */ vfield_rate = hfreq_est / vtotal_lines; /* 14. Find the Vertical frame frequency: */ if (interlaced) vframe_rate = vfield_rate / 2; else vframe_rate = vfield_rate; /* 15. Find number of pixels in left margin: */ if (margins) left_margin = (hdisplay_rnd * GTF_MARGIN_PERCENTAGE + 500) / 1000; else left_margin = 0; /* 16.Find number of pixels in right margin: */ right_margin = left_margin; /* 17.Find total number of active pixels in image and left and right */ total_active_pixels = hdisplay_rnd + left_margin + right_margin; /* 18.Find the ideal blanking duty cycle from blanking duty cycle */ ideal_duty_cycle = GTF_C_PRIME * 1000 - (GTF_M_PRIME * 1000000 / hfreq_est); /* 19.Find the number of pixels in the blanking time to the nearest * double character cell: */ hblank = total_active_pixels * ideal_duty_cycle / (100000 - ideal_duty_cycle); hblank = (hblank + GTF_CELL_GRAN) / (2 * GTF_CELL_GRAN); hblank = hblank * 2 * GTF_CELL_GRAN; /* 20.Find total number of pixels: */ total_pixels = total_active_pixels + hblank; /* 21.Find pixel clock frequency: */ pixel_freq = total_pixels * hfreq_est / 1000; /* Stage 1 computations are now complete; I should really pass * the results to another function and do the Stage 2 computations, * but I only need a few more values so I'll just append the * computations here for now */ /* 17. Find the number of pixels in the horizontal sync period: */ hsync = H_SYNC_PERCENT * total_pixels / 100; hsync = (hsync + GTF_CELL_GRAN / 2) / GTF_CELL_GRAN; hsync = hsync * GTF_CELL_GRAN; /* 18. Find the number of pixels in horizontal front porch period */ hfront_porch = hblank / 2 - hsync; /* 36. Find the number of lines in the odd front porch period: */ vodd_front_porch_lines = GTF_MIN_V_PORCH ; /* finally, pack the results in the mode struct */ drm_mode->hdisplay = hdisplay_rnd; drm_mode->hsync_start = hdisplay_rnd + hfront_porch; drm_mode->hsync_end = drm_mode->hsync_start + hsync; drm_mode->htotal = total_pixels; drm_mode->vdisplay = vdisplay_rnd; drm_mode->vsync_start = vdisplay_rnd + vodd_front_porch_lines; drm_mode->vsync_end = drm_mode->vsync_start + V_SYNC_RQD; drm_mode->vtotal = vtotal_lines; drm_mode->clock = pixel_freq; if (interlaced) { drm_mode->vtotal *= 2; drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; } drm_mode_set_name(drm_mode); if (GTF_M == 600 && GTF_2C == 80 && GTF_K == 128 && GTF_2J == 40) drm_mode->flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC; else drm_mode->flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC; return drm_mode; }
static void mdfld_h8c7_dsi_controller_init(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_hw_context *hw_ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct csc_setting csc = { .pipe = 0, .type = CSC_REG_SETTING, .enable_state = true, .data_len = CSC_REG_COUNT, .data.csc_reg_data = { 0xFFB0424, 0xFDF, 0x4320FF1, 0xFDC, 0xFF50FF5, 0x415} }; struct gamma_setting gamma = { .pipe = 0, .type = GAMMA_REG_SETTING, .enable_state = true, .data_len = GAMMA_10_BIT_TABLE_COUNT, .gamma_tableX100 = { 0x000000, 0x030303, 0x050505, 0x070707, 0x090909, 0x0C0C0C, 0x0E0E0E, 0x101010, 0x121212, 0x141414, 0x171717, 0x191919, 0x1B1B1B, 0x1D1D1D, 0x1F1F1F, 0x212121, 0x232323, 0x252525, 0x282828, 0x2A2A2A, 0x2C2C2C, 0x2E2E2E, 0x303030, 0x323232, 0x343434, 0x363636, 0x383838, 0x3A3A3A, 0x3C3C3C, 0x3E3E3E, 0x404040, 0x424242, 0x444444, 0x464646, 0x484848, 0x4A4A4A, 0x4C4C4C, 0x4E4E4E, 0x505050, 0x525252, 0x545454, 0x565656, 0x585858, 0x5A5A5A, 0x5C5C5C, 0x5E5E5E, 0x606060, 0x626262, 0x646464, 0x666666, 0x686868, 0x6A6A6A, 0x6C6C6C, 0x6E6E6E, 0x707070, 0x727272, 0x747474, 0x767676, 0x787878, 0x7A7A7A, 0x7C7C7C, 0x7E7E7E, 0x808080, 0x828282, 0x848484, 0x868686, 0x888888, 0x8A8A8A, 0x8C8C8C, 0x8E8E8E, 0x909090, 0x929292, 0x949494, 0x969696, 0x989898, 0x999999, 0x9B9B9B, 0x9D9D9D, 0x9F9F9F, 0xA1A1A1, 0xA3A3A3, 0xA5A5A5, 0xA7A7A7, 0xA9A9A9, 0xABABAB, 0xADADAD, 0xAFAFAF, 0xB1B1B1, 0xB3B3B3, 0xB5B5B5, 0xB6B6B6, 0xB8B8B8, 0xBABABA, 0xBCBCBC, 0xBEBEBE, 0xC0C0C0, 0xC2C2C2, 0xC4C4C4, 0xC6C6C6, 0xC8C8C8, 0xCACACA, 0xCCCCCC, 0xCECECE, 0xCFCFCF, 0xD1D1D1, 0xD3D3D3, 0xD5D5D5, 0xD7D7D7, 0xD9D9D9, 0xDBDBDB, 0xDDDDDD, 0xDFDFDF, 0xE1E1E1, 0xE3E3E3, 0xE4E4E4, 0xE6E6E6, 0xE8E8E8, 0xEAEAEA, 0xECECEC, 0xEEEEEE, 0xF0F0F0, 0xF2F2F2, 0xF4F4F4, 0xF6F6F6, 0xF7F7F7, 0xF9F9F9, 0xFBFBFB, 0xFDFDFD} }; PSB_DEBUG_ENTRY("\n"); /*reconfig lane configuration*/ dsi_config->lane_count = 3; dsi_config->lane_config = MDFLD_DSI_DATA_LANE_3_1; dsi_config->enable_gamma_csc = ENABLE_GAMMA | ENABLE_CSC; /* This is for 400 mhz. Set it to 0 for 800mhz */ hw_ctx->cck_div = 1; hw_ctx->pll_bypass_mode = 0; hw_ctx->mipi_control = 0x00; hw_ctx->intr_en = 0xffffffff; hw_ctx->hs_tx_timeout = 0xffffff; hw_ctx->lp_rx_timeout = 0xffffff; hw_ctx->turn_around_timeout = 0x1f; hw_ctx->device_reset_timer = 0xffff; hw_ctx->high_low_switch_count = 0x20; hw_ctx->init_count = 0xf0; hw_ctx->eot_disable = 0x3; hw_ctx->lp_byteclk = 0x4; hw_ctx->clk_lane_switch_time_cnt = 0x20000E; hw_ctx->hs_ls_dbi_enable = 0x0; /* HW team suggested 1390 for bandwidth setting */ hw_ctx->dbi_bw_ctrl = 1390; hw_ctx->dphy_param = 0x20124E1A; hw_ctx->dsi_func_prg = (0xa000 | dsi_config->lane_count); hw_ctx->mipi = TE_TRIGGER_GPIO_PIN; hw_ctx->mipi |= dsi_config->lane_config; if (dsi_config->enable_gamma_csc & ENABLE_CSC) { /* setting the tuned csc setting */ drm_psb_enable_color_conversion = 1; mdfld_intel_crtc_set_color_conversion(dev, &csc); } if (dsi_config->enable_gamma_csc & ENABLE_GAMMA) { /* setting the tuned gamma setting */ drm_psb_enable_gamma = 1; mdfld_intel_crtc_set_gamma(dev, &gamma); } } static struct drm_display_mode *h8c7_cmd_get_config_mode(void) { struct drm_display_mode *mode; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; mode->htotal = 920; mode->hdisplay = 720; mode->hsync_start = 816; mode->hsync_end = 824; mode->vtotal = 1300; mode->vdisplay = 1280; mode->vsync_start = 1294; mode->vsync_end = 1296; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; mode->type |= DRM_MODE_TYPE_PREFERRED; PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay); PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay); PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start); PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end); PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal); PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start); PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end); PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal); PSB_DEBUG_ENTRY("clock is %d\n", mode->clock); drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); return mode; } static int mdfld_dsi_h8c7_cmd_power_on(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; int enable_err, enabled = 0; PSB_DEBUG_ENTRY("\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } if (!IS_ERR(h8c7_regulator_status.regulator)) { if (!h8c7_regulator_status.h8c7_mmc2_on) { PSB_DEBUG_ENTRY("Before power on, regulator is %d\n", regulator_is_enabled(h8c7_regulator_status.regulator)); PSB_DEBUG_ENTRY("Begin to power on\n"); h8c7_regulator_status.h8c7_mmc2_on = true; } else { DRM_ERROR("power on several times without off\n"); } enabled = regulator_is_enabled(h8c7_regulator_status.regulator); enable_err = regulator_enable(h8c7_regulator_status.regulator); if (enable_err < 0) { regulator_put(h8c7_regulator_status.regulator); DRM_ERROR("FATAL:enable h8c7 regulator error\n"); } /* vemmc2 need 50ms delay due to stability ** If already enabled, no need to wait for this delay. ** This code isn't race proof but since in addition to ** this panel driver only touch driver is enabling this ** regulator and does it after this function has been ** finished, this code works well enough for now. */ if (!enabled) msleep(50); PSB_DEBUG_ENTRY("After power on, regulator is %d\n", regulator_is_enabled(h8c7_regulator_status.regulator)); } /*exit sleep */ err = mdfld_dsi_send_dcs(sender, exit_sleep_mode, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("faild to exit_sleep mode\n"); goto power_err; } msleep(120); /*set tear on*/ err = mdfld_dsi_send_dcs(sender, set_tear_on, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("faild to set_tear_on mode\n"); goto power_err; } /*turn on display*/ err = mdfld_dsi_send_dcs(sender, set_display_on, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("faild to set_display_on mode\n"); goto power_err; } if (drm_psb_enable_cabc) { /* turn on cabc */ h8c7_disable_cabc[1] = 0x2; mdfld_dsi_send_mcs_long_hs(sender, h8c7_disable_cabc, sizeof(h8c7_disable_cabc), 0); mdelay(5); mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_off, 4, 0); mdfld_dsi_send_mcs_long_hs(sender, h8c7_set_cabc_gain, 10, 0); mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_on, 4, 0); DRM_INFO("%s enable h8c7 cabc\n", __func__); } power_err: return err; } static int mdfld_dsi_h8c7_cmd_power_off(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; PSB_DEBUG_ENTRY("\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } /* turn off cabc */ h8c7_disable_cabc[1] = 0x0; mdfld_dsi_send_mcs_long_lp(sender, h8c7_disable_cabc, sizeof(h8c7_disable_cabc), 0); /*turn off backlight*/ err = mdfld_dsi_send_mcs_long_lp(sender, h8c7_turn_off_backlight, sizeof(h8c7_turn_off_backlight), 0); if (err) { DRM_ERROR("%s: failed to turn off backlight\n", __func__); goto out; } mdelay(1); /*turn off display */ err = mdfld_dsi_send_dcs(sender, set_display_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("sent set_display_off faild\n"); goto out; } /*set tear off */ err = mdfld_dsi_send_dcs(sender, set_tear_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("sent set_tear_off faild\n"); goto out; } /*Enter sleep mode */ err = mdfld_dsi_send_dcs(sender, enter_sleep_mode, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("DCS 0x%x sent failed\n", enter_sleep_mode); goto out; } /** * MIPI spec shows it must wait 5ms * before sneding next command */ mdelay(5); /*enter deep standby mode*/ err = mdfld_dsi_send_mcs_long_lp(sender, h8c7_mcs_protect_off, 4, 0); if (err) { DRM_ERROR("Failed to turn off protection\n"); goto out; } err = mdfld_dsi_send_mcs_long_lp(sender, h8c7_set_power_dstb, 14, 0); if (err) DRM_ERROR("Failed to enter DSTB\n"); mdelay(5); mdfld_dsi_send_mcs_long_lp(sender, h8c7_mcs_protect_on, 4, 0); out: if (!IS_ERR(h8c7_regulator_status.regulator)) { if (h8c7_regulator_status.h8c7_mmc2_on) { h8c7_regulator_status.h8c7_mmc2_on = false; PSB_DEBUG_GENERAL("Begin to power off\n"); } else DRM_ERROR("power off several times without on\n"); regulator_disable(h8c7_regulator_status.regulator); PSB_DEBUG_GENERAL("After power off, regulator is %d\n", regulator_is_enabled(h8c7_regulator_status.regulator)); } return err; } static void h8c7_cmd_get_panel_info(int pipe, struct panel_info *pi) { PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { pi->width_mm = PANEL_4DOT3_WIDTH; pi->height_mm = PANEL_4DOT3_HEIGHT; } } static int mdfld_dsi_h8c7_cmd_detect(struct mdfld_dsi_config *dsi_config) { int status; struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; u32 dpll_val, device_ready_val; int pipe = dsi_config->pipe; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { /* * FIXME: WA to detect the panel connection status, and need to * implement detection feature with get_power_mode DSI command. */ if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return -EAGAIN; } dpll_val = REG_READ(regs->dpll_reg); device_ready_val = REG_READ(regs->device_ready_reg); if ((device_ready_val & DSI_DEVICE_READY) && (dpll_val & DPLL_VCO_ENABLE)) { dsi_config->dsi_hw_context.panel_on = true; mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_off, 4, 0); mdfld_dsi_send_gen_long_hs(sender, h8c7_set_disp_reg, 13, 0); mdfld_dsi_send_gen_long_hs(sender, h8c7_mcs_protect_on, 4, 0); } else { dsi_config->dsi_hw_context.panel_on = false; DRM_INFO("%s: panel is not initialized!\n", __func__); } status = MDFLD_DSI_PANEL_CONNECTED; ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } else { DRM_INFO("%s: do NOT support dual panel\n", __func__); status = MDFLD_DSI_PANEL_DISCONNECTED; } return status; }
/* Try to find panel data */ static void parse_panel_data(struct drm_i915_private *dev_priv, struct bdb_header *bdb) { struct bdb_lvds_options *lvds_options; struct bdb_lvds_lfp_data *lvds_lfp_data; struct bdb_lvds_lfp_data_entry *entry; struct lvds_dvo_timing *dvo_timing; struct drm_display_mode *panel_fixed_mode; /* Defaults if we can't find VBT info */ dev_priv->lvds_dither = 0; dev_priv->lvds_vbt = 0; lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); if (!lvds_options) return; dev_priv->lvds_dither = lvds_options->pixel_dither; if (lvds_options->panel_type == 0xff) return; lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); if (!lvds_lfp_data) return; dev_priv->lvds_vbt = 1; entry = &lvds_lfp_data->data[lvds_options->panel_type]; dvo_timing = &entry->dvo_timing; panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | dvo_timing->hactive_lo; panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + dvo_timing->hsync_pulse_width; panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | dvo_timing->vactive_lo; panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + dvo_timing->vsync_off; panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + dvo_timing->vsync_pulse_width; panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); panel_fixed_mode->clock = dvo_timing->clock * 10; panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; /* Some VBTs have bogus h/vtotal values */ if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; drm_mode_set_name(panel_fixed_mode); dev_priv->vbt_mode = panel_fixed_mode; DRM_DEBUG("Found panel mode in BIOS VBT tables:\n"); drm_mode_debug_printmodeline(panel_fixed_mode); return; }
static void gi_renesas_dsi_controller_init(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_hw_context *hw_ctx = &dsi_config->dsi_hw_context; struct drm_device *dev = dsi_config->dev; struct csc_setting csc = { .pipe = 0, .type = CSC_REG_SETTING, .enable_state = true, .data_len = CSC_REG_COUNT, .data.csc_reg_data = { 0xF510486, 0x27, 0x3F10FD0, 0x3E, 0x51000F, 0x39F} }; struct gamma_setting gamma = { .pipe = 0, .type = GAMMA_REG_SETTING, .enable_state = true, .data_len = GAMMA_10_BIT_TABLE_COUNT, .gamma_tableX100 = { 0x000000, 0x010101, 0x020202, 0x030303, 0x040404, 0x050505, 0x060606, 0x070807, 0x080908, 0x0A0B0A, 0x0B0C0B, 0x0D0D0D, 0x0E0F0E, 0x0F100F, 0x111211, 0x121312, 0x141514, 0x151715, 0x171817, 0x191A19, 0x1A1C1A, 0x1C1D1C, 0x1D1F1D, 0x1F211F, 0x212221, 0x222422, 0x242624, 0x262726, 0x272928, 0x292B29, 0x2B2D2B, 0x2D2F2D, 0x2E302F, 0x303230, 0x323432, 0x343634, 0x363836, 0x383A38, 0x393B39, 0x3B3D3B, 0x3D3F3D, 0x3F413F, 0x414341, 0x434543, 0x454745, 0x474947, 0x494B49, 0x4B4D4B, 0x4C4F4D, 0x4E514F, 0x505351, 0x525552, 0x545754, 0x565956, 0x585B58, 0x5A5D5A, 0x5C5F5D, 0x5E615F, 0x606361, 0x636563, 0x656765, 0x676967, 0x696B69, 0x6B6D6B, 0x6D6F6D, 0x6F716F, 0x717371, 0x737573, 0x757775, 0x777A78, 0x7A7C7A, 0x7C7E7C, 0x7E807E, 0x808280, 0x828482, 0x848684, 0x868887, 0x898B89, 0x8B8D8B, 0x8D8F8D, 0x8F918F, 0x919391, 0x949594, 0x969896, 0x989A98, 0x9A9C9A, 0x9D9E9D, 0x9FA09F, 0xA1A3A1, 0xA3A5A3, 0xA5A7A6, 0xA8A9A8, 0xAAACAA, 0xACAEAC, 0xAFB0AF, 0xB1B2B1, 0xB3B5B3, 0xB5B7B5, 0xB8B9B8, 0xBABBBA, 0xBCBEBC, 0xBFC0BF, 0xC1C2C1, 0xC3C5C3, 0xC6C7C6, 0xC8C9C8, 0xCACBCA, 0xCDCECD, 0xCFD0CF, 0xD1D2D1, 0xD4D5D4, 0xD6D7D6, 0xD8D9D8, 0xDBDCDB, 0xDDDEDD, 0xE0E0E0, 0xE2E3E2, 0xE4E5E4, 0xE7E7E7, 0xE9EAE9, 0xECECEC, 0xEEEEEE, 0xF0F1F0, 0xF3F3F3, 0xF5F5F5, 0xF8F8F8, 0xFAFAFA, 0xFDFDFD} }; PSB_DEBUG_ENTRY("\n"); dsi_config->lane_count = 1; dsi_config->lane_config = MDFLD_DSI_DATA_LANE_2_2; dsi_config->enable_gamma_csc = ENABLE_GAMMA | ENABLE_CSC; hw_ctx->pll_bypass_mode = 1; hw_ctx->cck_div = 1; hw_ctx->mipi_control = 0x00; hw_ctx->intr_en = 0xffffffff; hw_ctx->hs_tx_timeout = 0xffffff; hw_ctx->lp_rx_timeout = 0xffffff; hw_ctx->turn_around_timeout = 0x14; hw_ctx->device_reset_timer = 0xffff; hw_ctx->high_low_switch_count = 0x28; hw_ctx->init_count = 0xf0; hw_ctx->eot_disable = 0x2; hw_ctx->hs_ls_dbi_enable = 0x0; hw_ctx->lp_byteclk = 0x0; hw_ctx->clk_lane_switch_time_cnt = 0xa0014; hw_ctx->dphy_param = 0x150a600f; hw_ctx->dbi_bw_ctrl = 0x820; hw_ctx->mipi = PASS_FROM_SPHY_TO_AFE | TE_TRIGGER_GPIO_PIN; hw_ctx->mipi |= dsi_config->lane_config; /*set up func_prg*/ hw_ctx->dsi_func_prg = (0xa000 | dsi_config->lane_count); if (dsi_config->enable_gamma_csc & ENABLE_CSC) { /* setting the tuned csc setting */ drm_psb_enable_color_conversion = 1; mdfld_intel_crtc_set_color_conversion(dev, &csc); } if (dsi_config->enable_gamma_csc & ENABLE_GAMMA) { /* setting the tuned gamma setting */ drm_psb_enable_gamma = 1; mdfld_intel_crtc_set_gamma(dev, &gamma); } } static struct drm_display_mode *gi_renesas_cmd_get_config_mode(void) { struct drm_display_mode *mode; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; mode->hdisplay = 320; mode->vdisplay = 480; /* HFP = 10, HSYNC = 10, HBP = 20 */ mode->hsync_start = mode->hdisplay + 10; mode->hsync_end = mode->hsync_start + 10; mode->htotal = mode->hsync_end + 20; /* VFP = 10, VSYNC = 2, VBP = 20 */ mode->vsync_start = mode->vdisplay + 10; mode->vsync_end = mode->vsync_start + 2; mode->vtotal = mode->vsync_end + 10; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; return mode; } static int __gi_renesas_dsi_power_on(struct mdfld_dsi_config *dsi_config) { struct drm_device *dev = dsi_config->dev; struct drm_psb_private *dev_priv = dev->dev_private; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; PSB_DEBUG_ENTRY("\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } if (drm_psb_enable_cabc) { /* enable cabc */ gi_er61529_backlight_cntr_1[1] = 0x01; mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_backlight_cntr_1, 21, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); } mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_backlight_cntr, 5, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_exit_sleep_mode, 1, 0); mdelay(120); mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_set_tear_on, 2, 0); mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_dcs_set_display_on, 1, 0); return err; } static int __gi_renesas_dsi_power_off(struct mdfld_dsi_config *dsi_config) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); int err = 0; PSB_DEBUG_ENTRY("Turn off video mode TMD panel...\n"); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } /* turn off display */ err = mdfld_dsi_send_dcs(sender, set_display_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("%s - sent set_display_off faild\n", __func__); goto power_err; } mdelay(70); /* set tear off display */ err = mdfld_dsi_send_dcs(sender, set_tear_off, NULL, 0, CMD_DATA_SRC_SYSTEM_MEM, MDFLD_DSI_SEND_PACKAGE); if (err) { DRM_ERROR("%s - sent set_tear_off faild\n", __func__); goto power_err; } /* disable CABC */ gi_er61529_backlight_cntr_1[1] = 0x00; mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_backlight_cntr_1, 21, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); err = mdfld_dsi_send_mcs_long_hs(sender, gi_er61529_enter_sleep_mode, 1, 0); if (err) { DRM_ERROR("Enter sleep mode error\n"); goto power_err; } mdelay(120); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_lp_mode_cntr, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); power_err: return err; } static void gi_renesas_cmd_get_panel_info(int pipe, struct panel_info *pi) { if (pipe == 0) { pi->width_mm = PANEL_3DOT47_WIDTH; pi->height_mm = PANEL_3DOT47_HEIGHT; } } static int gi_renesas_dsi_cmd_detect(struct mdfld_dsi_config *dsi_config) { struct drm_device *dev = dsi_config->dev; struct mdfld_dsi_hw_registers *regs = &dsi_config->regs; int status; int pipe = dsi_config->pipe; uint32_t dpll_val, device_ready_val; PSB_DEBUG_ENTRY("\n"); if (pipe == 0) { if (!ospm_power_using_hw_begin(OSPM_DISPLAY_ISLAND, OSPM_UHB_FORCE_POWER_ON)) { DRM_ERROR("hw begin failed\n"); return -EAGAIN; } dpll_val = REG_READ(regs->dpll_reg); device_ready_val = REG_READ(regs->device_ready_reg); if ((device_ready_val & DSI_DEVICE_READY) && (dpll_val & DPLL_VCO_ENABLE)) { dsi_config->dsi_hw_context.panel_on = true; status = MDFLD_DSI_PANEL_CONNECTED; } else { dsi_config->dsi_hw_context.panel_on = false; status = MDFLD_DSI_PANEL_DISCONNECTED; DRM_INFO("%s: do NOT support dual panel\n", __func__); } ospm_power_using_hw_end(OSPM_DISPLAY_ISLAND); } else { PSB_DEBUG_ENTRY("Only support single panel\n"); status = MDFLD_DSI_PANEL_DISCONNECTED; dsi_config->dsi_hw_context.panel_on = 0; } return 0; } static int gi_renesas_dsi_cmd_set_brightness(struct mdfld_dsi_config *dsi_config, int level) { struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); u8 backlight_val; PSB_DEBUG_ENTRY("Set brightness level %d...\n", level); if (!sender) { DRM_ERROR("Failed to get DSI packet sender\n"); return -EINVAL; } backlight_val = level * 255 / 100; gi_er61529_set_backlight[2] = backlight_val; mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_on, 2, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_set_backlight, 5, 0); mdfld_dsi_send_gen_long_hs(sender, gi_er61529_mcs_protect_off, 2, 0); return 0; } static int gi_renesas_dsi_panel_reset(struct mdfld_dsi_config *dsi_config) { static int mipi_reset_gpio; int ret = 0; PSB_DEBUG_ENTRY("\n"); if (mipi_reset_gpio == 0) { ret = get_gpio_by_name("mipi-reset"); if (ret < 0) { DRM_ERROR("Faild to get panel reset gpio, " \ "use default reset pin\n"); ret = 128; } mipi_reset_gpio = ret; ret = gpio_request(mipi_reset_gpio, "mipi_display"); if (ret) { DRM_ERROR("Faild to request panel reset gpio\n"); return -EINVAL; } gpio_direction_output(mipi_reset_gpio, 0); } gpio_set_value_cansleep(mipi_reset_gpio, 0); mdelay(11); gpio_set_value_cansleep(mipi_reset_gpio, 1); mdelay(20); return 0; } void gi_renesas_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) { p_funcs->get_config_mode = gi_renesas_cmd_get_config_mode; p_funcs->get_panel_info = gi_renesas_cmd_get_panel_info; p_funcs->reset = gi_renesas_dsi_panel_reset; p_funcs->drv_ic_init = gi_renesas_dbi_ic_init; p_funcs->dsi_controller_init = gi_renesas_dsi_controller_init; p_funcs->detect = gi_renesas_dsi_cmd_detect; p_funcs->set_brightness = gi_renesas_dsi_cmd_set_brightness; p_funcs->power_on = __gi_renesas_dsi_power_on; p_funcs->power_off = __gi_renesas_dsi_power_off; }
static int exynos_drm_connector_get_modes(struct drm_connector *connector) { struct exynos_drm_connector *exynos_connector = to_exynos_connector(connector); struct exynos_drm_manager *manager = exynos_connector->manager; struct exynos_drm_display_ops *display_ops = manager->display_ops; unsigned int count; DRM_DEBUG_KMS("%s\n", __FILE__); if (!display_ops) { DRM_DEBUG_KMS("display_ops is null.\n"); return 0; } /* * if get_edid() exists then get_edid() callback of hdmi side * is called to get edid data through i2c interface else * get timing from the FIMD driver(display controller). * * P.S. in case of lcd panel, count is always 1 if success * because lcd panel has only one mode. */ if (display_ops->get_edid) { int ret; void *edid; edid = kzalloc(MAX_EDID, GFP_KERNEL); if (!edid) { DRM_ERROR("failed to allocate edid\n"); return 0; } ret = display_ops->get_edid(manager->dev, connector, edid, MAX_EDID); if (ret < 0) { DRM_ERROR("failed to get edid data.\n"); kfree(edid); edid = NULL; return 0; } drm_mode_connector_update_edid_property(connector, edid); count = drm_add_edid_modes(connector, edid); kfree(connector->display_info.raw_edid); connector->display_info.raw_edid = edid; } else { struct drm_display_mode *mode = drm_mode_create(connector->dev); struct fb_videomode *timing; if (display_ops->get_timing) timing = display_ops->get_timing(manager->dev); else { drm_mode_destroy(connector->dev, mode); return 0; } convert_to_display_mode(mode, timing); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_set_name(mode); drm_mode_probed_add(connector, mode); count = 1; } return count; }
struct drm_display_mode *h8c7_get_config_mode(struct drm_device *dev) { struct drm_display_mode *mode; struct drm_psb_private *dev_priv = (struct drm_psb_private *) dev->dev_private; struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; bool use_gct = false; /*Disable GCT for now*/ if (IS_CTP(dev)) use_gct = true; PSB_DEBUG_ENTRY("\n"); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; if (use_gct) { PSB_DEBUG_ENTRY("gct find MIPI panel.\n"); mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; mode->hsync_start = mode->hdisplay + \ ((ti->hsync_offset_hi << 8) | \ ti->hsync_offset_lo); mode->hsync_end = mode->hsync_start + \ ((ti->hsync_pulse_width_hi << 8) | \ ti->hsync_pulse_width_lo); mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ ti->hblank_lo); mode->vsync_start = \ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ ti->vsync_offset_lo); mode->vsync_end = \ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ ti->vsync_pulse_width_lo); mode->vtotal = mode->vdisplay + \ ((ti->vblank_hi << 8) | ti->vblank_lo); mode->clock = ti->pixel_clock * 10; PSB_DEBUG_ENTRY("hdisplay is %d\n", mode->hdisplay); PSB_DEBUG_ENTRY("vdisplay is %d\n", mode->vdisplay); PSB_DEBUG_ENTRY("HSS is %d\n", mode->hsync_start); PSB_DEBUG_ENTRY("HSE is %d\n", mode->hsync_end); PSB_DEBUG_ENTRY("htotal is %d\n", mode->htotal); PSB_DEBUG_ENTRY("VSS is %d\n", mode->vsync_start); PSB_DEBUG_ENTRY("VSE is %d\n", mode->vsync_end); PSB_DEBUG_ENTRY("vtotal is %d\n", mode->vtotal); PSB_DEBUG_ENTRY("clock is %d\n", mode->clock); } else { mode->hdisplay = 720; mode->vdisplay = 1280; mode->hsync_start = 816; mode->hsync_end = 824; mode->htotal = 920; mode->vsync_start = 1284; mode->vsync_end = 1286; mode->vtotal = 1300; mode->vrefresh = 60; mode->clock = mode->vrefresh * mode->vtotal * mode->htotal / 1000; } drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; return mode; }
struct drm_display_mode *drm_cvt_mode(struct drm_device *dev, int hdisplay, int vdisplay, int vrefresh, bool reduced, bool interlaced, bool margins) { /* 1) top/bottom margin size (% of height) - default: 1.8, */ #define CVT_MARGIN_PERCENTAGE 18 /* 2) character cell horizontal granularity (pixels) - default 8 */ #define CVT_H_GRANULARITY 8 /* 3) Minimum vertical porch (lines) - default 3 */ #define CVT_MIN_V_PORCH 3 /* 4) Minimum number of vertical back porch lines - default 6 */ #define CVT_MIN_V_BPORCH 6 /* Pixel Clock step (kHz) */ #define CVT_CLOCK_STEP 250 struct drm_display_mode *drm_mode; unsigned int vfieldrate, hperiod; int hdisplay_rnd, hmargin, vdisplay_rnd, vmargin, vsync; int interlace; /* allocate the drm_display_mode structure. If failure, we will * return directly */ drm_mode = drm_mode_create(dev); if (!drm_mode) return NULL; /* the CVT default refresh rate is 60Hz */ if (!vrefresh) vrefresh = 60; /* the required field fresh rate */ if (interlaced) vfieldrate = vrefresh * 2; else vfieldrate = vrefresh; /* horizontal pixels */ hdisplay_rnd = hdisplay - (hdisplay % CVT_H_GRANULARITY); /* determine the left&right borders */ hmargin = 0; if (margins) { hmargin = hdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; hmargin -= hmargin % CVT_H_GRANULARITY; } /* find the total active pixels */ drm_mode->hdisplay = hdisplay_rnd + 2 * hmargin; /* find the number of lines per field */ if (interlaced) vdisplay_rnd = vdisplay / 2; else vdisplay_rnd = vdisplay; /* find the top & bottom borders */ vmargin = 0; if (margins) vmargin = vdisplay_rnd * CVT_MARGIN_PERCENTAGE / 1000; drm_mode->vdisplay = vdisplay + 2 * vmargin; /* Interlaced */ if (interlaced) interlace = 1; else interlace = 0; /* Determine VSync Width from aspect ratio */ if (!(vdisplay % 3) && ((vdisplay * 4 / 3) == hdisplay)) vsync = 4; else if (!(vdisplay % 9) && ((vdisplay * 16 / 9) == hdisplay)) vsync = 5; else if (!(vdisplay % 10) && ((vdisplay * 16 / 10) == hdisplay)) vsync = 6; else if (!(vdisplay % 4) && ((vdisplay * 5 / 4) == hdisplay)) vsync = 7; else if (!(vdisplay % 9) && ((vdisplay * 15 / 9) == hdisplay)) vsync = 7; else /* custom */ vsync = 10; if (!reduced) { /* simplify the GTF calculation */ /* 4) Minimum time of vertical sync + back porch interval (µs) * default 550.0 */ int tmp1, tmp2; #define CVT_MIN_VSYNC_BP 550 /* 3) Nominal HSync width (% of line period) - default 8 */ #define CVT_HSYNC_PERCENTAGE 8 unsigned int hblank_percentage; int vsyncandback_porch, vback_porch, hblank; /* estimated the horizontal period */ tmp1 = HV_FACTOR * 1000000 - CVT_MIN_VSYNC_BP * HV_FACTOR * vfieldrate; tmp2 = (vdisplay_rnd + 2 * vmargin + CVT_MIN_V_PORCH) * 2 + interlace; hperiod = tmp1 * 2 / (tmp2 * vfieldrate); tmp1 = CVT_MIN_VSYNC_BP * HV_FACTOR / hperiod + 1; /* 9. Find number of lines in sync + backporch */ if (tmp1 < (vsync + CVT_MIN_V_PORCH)) vsyncandback_porch = vsync + CVT_MIN_V_PORCH; else vsyncandback_porch = tmp1; /* 10. Find number of lines in back porch */ vback_porch = vsyncandback_porch - vsync; drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vsyncandback_porch + CVT_MIN_V_PORCH; /* 5) Definition of Horizontal blanking time limitation */ /* Gradient (%/kHz) - default 600 */ #define CVT_M_FACTOR 600 /* Offset (%) - default 40 */ #define CVT_C_FACTOR 40 /* Blanking time scaling factor - default 128 */ #define CVT_K_FACTOR 128 /* Scaling factor weighting - default 20 */ #define CVT_J_FACTOR 20 #define CVT_M_PRIME (CVT_M_FACTOR * CVT_K_FACTOR / 256) #define CVT_C_PRIME ((CVT_C_FACTOR - CVT_J_FACTOR) * CVT_K_FACTOR / 256 + \ CVT_J_FACTOR) /* 12. Find ideal blanking duty cycle from formula */ hblank_percentage = CVT_C_PRIME * HV_FACTOR - CVT_M_PRIME * hperiod / 1000; /* 13. Blanking time */ if (hblank_percentage < 20 * HV_FACTOR) hblank_percentage = 20 * HV_FACTOR; hblank = drm_mode->hdisplay * hblank_percentage / (100 * HV_FACTOR - hblank_percentage); hblank -= hblank % (2 * CVT_H_GRANULARITY); /* 14. find the total pixes per line */ drm_mode->htotal = drm_mode->hdisplay + hblank; drm_mode->hsync_end = drm_mode->hdisplay + hblank / 2; drm_mode->hsync_start = drm_mode->hsync_end - (drm_mode->htotal * CVT_HSYNC_PERCENTAGE) / 100; drm_mode->hsync_start += CVT_H_GRANULARITY - drm_mode->hsync_start % CVT_H_GRANULARITY; /* fill the Vsync values */ drm_mode->vsync_start = drm_mode->vdisplay + CVT_MIN_V_PORCH; drm_mode->vsync_end = drm_mode->vsync_start + vsync; } else { /* Reduced blanking */ /* Minimum vertical blanking interval time (µs)- default 460 */ #define CVT_RB_MIN_VBLANK 460 /* Fixed number of clocks for horizontal sync */ #define CVT_RB_H_SYNC 32 /* Fixed number of clocks for horizontal blanking */ #define CVT_RB_H_BLANK 160 /* Fixed number of lines for vertical front porch - default 3*/ #define CVT_RB_VFPORCH 3 int vbilines; int tmp1, tmp2; /* 8. Estimate Horizontal period. */ tmp1 = HV_FACTOR * 1000000 - CVT_RB_MIN_VBLANK * HV_FACTOR * vfieldrate; tmp2 = vdisplay_rnd + 2 * vmargin; hperiod = tmp1 / (tmp2 * vfieldrate); /* 9. Find number of lines in vertical blanking */ vbilines = CVT_RB_MIN_VBLANK * HV_FACTOR / hperiod + 1; /* 10. Check if vertical blanking is sufficient */ if (vbilines < (CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH)) vbilines = CVT_RB_VFPORCH + vsync + CVT_MIN_V_BPORCH; /* 11. Find total number of lines in vertical field */ drm_mode->vtotal = vdisplay_rnd + 2 * vmargin + vbilines; /* 12. Find total number of pixels in a line */ drm_mode->htotal = drm_mode->hdisplay + CVT_RB_H_BLANK; /* Fill in HSync values */ drm_mode->hsync_end = drm_mode->hdisplay + CVT_RB_H_BLANK / 2; drm_mode->hsync_start = drm_mode->hsync_end - CVT_RB_H_SYNC; /* Fill in VSync values */ drm_mode->vsync_start = drm_mode->vdisplay + CVT_RB_VFPORCH; drm_mode->vsync_end = drm_mode->vsync_start + vsync; } /* 15/13. Find pixel clock frequency (kHz for xf86) */ drm_mode->clock = drm_mode->htotal * HV_FACTOR * 1000 / hperiod; drm_mode->clock -= drm_mode->clock % CVT_CLOCK_STEP; /* 18/16. Find actual vertical frame frequency */ /* ignore - just set the mode flag for interlaced */ if (interlaced) { drm_mode->vtotal *= 2; drm_mode->flags |= DRM_MODE_FLAG_INTERLACE; } /* Fill the mode line name */ drm_mode_set_name(drm_mode); if (reduced) drm_mode->flags |= (DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC); else drm_mode->flags |= (DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NHSYNC); return drm_mode; }
static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev) { struct drm_display_mode *mode; struct drm_psb_private *dev_priv = dev->dev_private; struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; bool use_gct = false; mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; if (use_gct) { dev_dbg(dev->dev, "gct find MIPI panel.\n"); mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; mode->hsync_start = mode->hdisplay + \ ((ti->hsync_offset_hi << 8) | \ ti->hsync_offset_lo); mode->hsync_end = mode->hsync_start + \ ((ti->hsync_pulse_width_hi << 8) | \ ti->hsync_pulse_width_lo); mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ ti->hblank_lo); mode->vsync_start = \ mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ ti->vsync_offset_lo); mode->vsync_end = \ mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ ti->vsync_pulse_width_lo); mode->vtotal = mode->vdisplay + \ ((ti->vblank_hi << 8) | ti->vblank_lo); mode->clock = ti->pixel_clock * 10; dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); dev_dbg(dev->dev, "clock is %d\n", mode->clock); } else { mode->hdisplay = 864; mode->vdisplay = 480; mode->hsync_start = 872; mode->hsync_end = 876; mode->htotal = 884; mode->vsync_start = 482; mode->vsync_end = 494; mode->vtotal = 486; mode->clock = 25777; } drm_mode_set_name(mode); drm_mode_set_crtcinfo(mode, 0); mode->type |= DRM_MODE_TYPE_PREFERRED; return mode; }