REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
~POWER_TARGET_ON); do {
pp_status = REG_READ(PP_STATUS);
} while (pp_status & PP_ON);
}
gma_power_end(dev);
}
staticvoid cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
{ struct drm_device *dev = encoder->dev; if (mode == DRM_MODE_DPMS_ON)
cdv_intel_lvds_set_power(dev, encoder, true); else
cdv_intel_lvds_set_power(dev, encoder, false); /* XXX: We never power down the LVDS pairs. */
}
/* Should never happen!! */
list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
head) { if (tmp_encoder != encoder
&& tmp_encoder->crtc == encoder->crtc) {
pr_err("Can't enable LVDS and another encoder on the same pipe\n"); returnfalse;
}
}
/* * If we have timings from the BIOS for the panel, put them in * to the adjusted mode. The CRTC will be set up for this mode, * with the panel scaling set up to source from the H/VDisplay * of the original mode.
*/ if (panel_fixed_mode != NULL) {
adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
adjusted_mode->htotal = panel_fixed_mode->htotal;
adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
adjusted_mode->vtotal = panel_fixed_mode->vtotal;
adjusted_mode->clock = panel_fixed_mode->clock;
drm_mode_set_crtcinfo(adjusted_mode,
CRTC_INTERLACE_HALVE_V);
}
/* * XXX: It would be nice to support lower refresh rates on the * panels to reduce power consumption, and perhaps match the * user's requested refresh rate.
*/
/* * The LVDS pin pair will already have been turned on in the * cdv_intel_crtc_mode_set since it has a large impact on the DPLL * settings.
*/
/* * Enable automatic panel scaling so that non-native modes fill the * screen. Should be enabled before the pipe is enabled, according to * register description and PRM.
*/ if (mode->hdisplay != adjusted_mode->hdisplay ||
mode->vdisplay != adjusted_mode->vdisplay)
pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
HORIZ_INTERP_BILINEAR); else
pfit_control = 0;
/* * Enumerate the child dev array parsed from VBT to check whether * the LVDS is present. * If it is present, return 1. * If it is not present, return false. * If no child dev is parsed from VBT, it assumes that the LVDS is present.
*/ staticbool lvds_is_present_in_vbt(struct drm_device *dev,
u8 *i2c_pin)
{ struct drm_psb_private *dev_priv = to_drm_psb_private(dev); int i;
if (!dev_priv->child_dev_num) returntrue;
for (i = 0; i < dev_priv->child_dev_num; i++) { struct child_device_config *child = dev_priv->child_dev + i;
/* If the device type is not LFP, continue. * We have to check both the new identifiers as well as the * old for compatibility with some BIOSes.
*/ if (child->device_type != DEVICE_TYPE_INT_LFP &&
child->device_type != DEVICE_TYPE_LFP) continue;
if (child->i2c_pin)
*i2c_pin = child->i2c_pin;
/* However, we cannot trust the BIOS writers to populate * the VBT correctly. Since LVDS requires additional * information from AIM blocks, a non-zero addin offset is * a good indicator that the LVDS is actually present.
*/ if (child->addin_offset) returntrue;
/* But even then some BIOS writers perform some black magic * and instantiate the device without reference to any * additional data. Trust that if the VBT was written into * the OpRegion then they have validated the LVDS's existence.
*/ if (dev_priv->opregion.vbt) returntrue;
}
returnfalse;
}
/** * cdv_intel_lvds_init - setup LVDS connectors on this device * @dev: drm device * @mode_dev: PSB mode device * * Create the connector, register the LVDS DDC bus, and try to figure out what * modes we can display on the LVDS panel (if present).
*/ void cdv_intel_lvds_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev)
{ struct gma_encoder *gma_encoder; struct gma_connector *gma_connector; struct cdv_intel_lvds_priv *lvds_priv; struct drm_connector *connector; struct drm_encoder *encoder; struct drm_display_mode *scan; struct drm_crtc *crtc; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct gma_i2c_chan *ddc_bus;
u32 lvds; int pipe; int ret;
u8 pin;
if (!dev_priv->lvds_enabled_in_vbt) return;
pin = GMBUS_PORT_PANEL; if (!lvds_is_present_in_vbt(dev, &pin)) {
DRM_DEBUG_KMS("LVDS is not present in VBT\n"); return;
}
gma_encoder = kzalloc(sizeof(struct gma_encoder),
GFP_KERNEL); if (!gma_encoder) return;
gma_connector = kzalloc(sizeof(struct gma_connector),
GFP_KERNEL); if (!gma_connector) goto err_free_encoder;
lvds_priv = kzalloc(sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL); if (!lvds_priv) goto err_free_connector;
/* Set up the DDC bus. */
ddc_bus = gma_i2c_create(dev, GPIOC, "LVDSDDC_C"); if (!ddc_bus) {
dev_printk(KERN_ERR, dev->dev, "DDC bus registration ""failed.\n"); goto err_free_lvds_priv;
}
ret = drm_connector_init_with_ddc(dev, connector,
&cdv_intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS,
&ddc_bus->base); if (ret) goto err_destroy_ddc;
ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_LVDS); if (ret) goto err_connector_cleanup;
/** * Set up I2C bus * FIXME: distroy i2c_bus when exit
*/
gma_encoder->i2c_bus = gma_i2c_create(dev, GPIOB, "LVDSBLC_B"); if (!gma_encoder->i2c_bus) {
dev_printk(KERN_ERR,
dev->dev, "I2C bus registration failed.\n"); goto err_encoder_cleanup;
}
gma_encoder->i2c_bus->target_addr = 0x2C;
dev_priv->lvds_i2c_bus = gma_encoder->i2c_bus;
/* * LVDS discovery: * 1) check for EDID on DDC * 2) check for VBT data * 3) check to see if LVDS is already on * if none of the above, no panel * 4) make sure lid is open * if closed, act like it's not there for now
*/
/* * Attempt to get the fixed panel mode from DDC. Assume that the * preferred mode is the right one.
*/
mutex_lock(&dev->mode_config.mutex);
psb_intel_ddc_get_modes(connector, &ddc_bus->base);
/* Failed to get EDID, what about VBT? do we need this?*/ if (dev_priv->lfp_lvds_vbt_mode) {
mode_dev->panel_fixed_mode =
drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode); if (mode_dev->panel_fixed_mode) {
mode_dev->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED; goto out; /* FIXME: check for quirks */
}
} /* * If we didn't get EDID, try checking if the panel is already turned * on. If so, assume that whatever is currently programmed is the * correct mode.
*/
lvds = REG_READ(LVDS);
pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
if (crtc && (lvds & LVDS_PORT_EN)) {
mode_dev->panel_fixed_mode =
cdv_intel_crtc_mode_get(dev, crtc); if (mode_dev->panel_fixed_mode) {
mode_dev->panel_fixed_mode->type |=
DRM_MODE_TYPE_PREFERRED; goto out; /* FIXME: check for quirks */
}
}
/* If we still don't have a mode after all that, give up. */ if (!mode_dev->panel_fixed_mode) {
DRM_DEBUG
("Found no modes on the lvds, ignoring the LVDS\n"); goto err_unlock;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.