/* * Panel power down status
*/ #define VR30 0x30 /* Read only bit indicating that the panel is not in a safe poweroff state. */ # define VR30_PANEL_ON (1 << 15)
/* Some Bios implementations do not restore the DVO state upon * resume from standby. Thus, this driver has to handle it * instead. The following list contains all registers that * require saving.
*/ staticconst u16 backup_addresses[] = {
0x11, 0x12,
0x18, 0x19, 0x1a, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x8e, 0x8f,
0x10 /* this must come last */
};
struct ivch_priv { bool quiet;
u16 width, height;
/* Register backup */
u16 reg_backup[ARRAY_SIZE(backup_addresses)];
};
staticvoid ivch_dump_regs(struct intel_dvo_device *dvo); /* * Reads a register on the ivch. * * Each of the 256 registers are 16 bits long.
*/ staticbool ivch_read(struct intel_dvo_device *dvo, int addr, u16 *data)
{ struct ivch_priv *priv = dvo->dev_priv; struct i2c_adapter *adapter = dvo->i2c_bus;
u8 out_buf[1];
u8 in_buf[2];
out_buf[0] = addr;
out_buf[1] = data & 0xff;
out_buf[2] = data >> 8;
if (i2c_transfer(adapter, &msg, 1) == 1) returntrue;
if (!priv->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d.\n",
addr, adapter->name, dvo->target_addr);
}
returnfalse;
}
/* Probes the given bus and target address for an ivch */ staticbool ivch_init(struct intel_dvo_device *dvo, struct i2c_adapter *adapter)
{ struct ivch_priv *priv;
u16 temp; int i;
priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (priv == NULL) returnfalse;
if (!ivch_read(dvo, VR00, &temp)) goto out;
priv->quiet = false;
/* Since the identification bits are probably zeroes, which doesn't seem * very unique, check that the value in the base address field matches * the address it's responding on.
*/ if ((temp & VR00_BASE_ADDRESS_MASK) != dvo->target_addr) {
DRM_DEBUG_KMS("ivch detect failed due to address mismatch " "(%d vs %d)\n",
(temp & VR00_BASE_ADDRESS_MASK), dvo->target_addr); goto out;
}
/* Make a backup of the registers to be able to restore them * upon suspend.
*/ for (i = 0; i < ARRAY_SIZE(backup_addresses); i++)
ivch_read(dvo, backup_addresses[i], priv->reg_backup + i);
/* Restore the DVO registers after a resume * from RAM. Registers have been saved during * the initialization.
*/ staticvoid ivch_reset(struct intel_dvo_device *dvo)
{ struct ivch_priv *priv = dvo->dev_priv; int i;
DRM_DEBUG_KMS("Resetting the IVCH registers\n");
ivch_write(dvo, VR10, 0x0000);
for (i = 0; i < ARRAY_SIZE(backup_addresses); i++)
ivch_write(dvo, backup_addresses[i], priv->reg_backup[i]);
}
/* Sets the power state of the panel connected to the ivch */ staticvoid ivch_dpms(struct intel_dvo_device *dvo, bool enable)
{ int i;
u16 vr01, vr30, backlight;
ivch_reset(dvo);
/* Set the new power state of the panel. */ if (!ivch_read(dvo, VR01, &vr01)) return;
/* Wait for the panel to make its state transition */ for (i = 0; i < 100; i++) { if (!ivch_read(dvo, VR30, &vr30)) break;
if (((vr30 & VR30_PANEL_ON) != 0) == enable) break;
udelay(1000);
} /* wait some more; vch may fail to resync sometimes without this */
udelay(16 * 1000);
}
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.