/* * * Copyright (c) 2012 Gilles Dartiguelongue, Thomas Richter * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
*/
/* * The following registers are not part of the official datasheet * and are the result of reverse engineering.
*/
/* * Register c0 controls how the DVO synchronizes with * its input.
*/ #define NS2501_REGC0 0xc0 #define NS2501_C0_ENABLE (1<<0) /* enable the DVO sync in general */ #define NS2501_C0_HSYNC (1<<1) /* synchronize horizontal with input */ #define NS2501_C0_VSYNC (1<<2) /* synchronize vertical with input */ #define NS2501_C0_RESET (1<<7) /* reset the synchronization flip/flops */
/* * Register 41 is somehow related to the sync register and sync * configuration. It should be 0x32 whenever regC0 is 0x05 (hsync off) * and 0x00 otherwise.
*/ #define NS2501_REG41 0x41
/* * this register controls the dithering of the DVO * One bit enables it, the other define the dithering depth. * The higher the value, the lower the dithering depth.
*/ #define NS2501_F9_REG 0xf9 #define NS2501_F9_ENABLE (1<<0) /* if set, dithering is enabled */ #define NS2501_F9_DITHER_MASK (0x7f<<1) /* controls the dither depth */ #define NS2501_F9_DITHER_SHIFT 1 /* shifts the dither mask */
/* * PLL configuration register. This is a pair of registers, * one single byte register at 1B, and a pair at 1C,1D. * These registers are counters/dividers.
*/ #define NS2501_REG1B 0x1b /* one byte PLL control register */ #define NS2501_REG1C 0x1c /* low-part of the second register */ #define NS2501_REG1D 0x1d /* high-part of the second register */
/* * Scaler control registers. Horizontal at b8,b9, * vertical at 10,11. The scale factor is computed as * 2^16/control-value. The low-byte comes first.
*/ #define NS2501_REG10 0x10 /* low-byte vertical scaler */ #define NS2501_REG11 0x11 /* high-byte vertical scaler */ #define NS2501_REGB8 0xb8 /* low-byte horizontal scaler */ #define NS2501_REGB9 0xb9 /* high-byte horizontal scaler */
/* * Display window definition. This consists of four registers * per dimension. One register pair defines the start of the * display, one the end. * As far as I understand, this defines the window within which * the scaler samples the input.
*/ #define NS2501_REGC1 0xc1 /* low-byte horizontal display start */ #define NS2501_REGC2 0xc2 /* high-byte horizontal display start */ #define NS2501_REGC3 0xc3 /* low-byte horizontal display stop */ #define NS2501_REGC4 0xc4 /* high-byte horizontal display stop */ #define NS2501_REGC5 0xc5 /* low-byte vertical display start */ #define NS2501_REGC6 0xc6 /* high-byte vertical display start */ #define NS2501_REGC7 0xc7 /* low-byte vertical display stop */ #define NS2501_REGC8 0xc8 /* high-byte vertical display stop */
/* * The following register pair seems to define the start of * the vertical sync. If automatic syncing is enabled, and the * register value defines a sync pulse that is later than the * incoming sync, then the register value is ignored and the * external hsync triggers the synchronization.
*/ #define NS2501_REG80 0x80 /* low-byte vsync-start */ #define NS2501_REG81 0x81 /* high-byte vsync-start */
/* * The following register pair seems to define the total number * of lines created at the output side of the scaler. * This is again a low-high register pair.
*/ #define NS2501_REG82 0x82 /* output display height, low byte */ #define NS2501_REG83 0x83 /* output display height, high byte */
/* * The following registers define the end of the front-porch * in horizontal and vertical position and hence allow to shift * the image left/right or up/down.
*/ #define NS2501_REG98 0x98 /* horizontal start of display + 256, low */ #define NS2501_REG99 0x99 /* horizontal start of display + 256, high */ #define NS2501_REG8E 0x8e /* vertical start of the display, low byte */ #define NS2501_REG8F 0x8f /* vertical start of the display, high byte */
/* * The following register pair control the function of the * backlight and the DVO output. To enable the corresponding * function, the corresponding bit must be set in both registers.
*/ #define NS2501_REG34 0x34 /* DVO enable functions, first register */ #define NS2501_REG35 0x35 /* DVO enable functions, second register */ #define NS2501_34_ENABLE_OUTPUT (1<<0) /* enable DVO output */ #define NS2501_34_ENABLE_BACKLIGHT (1<<1) /* enable backlight */
/* * Registers 9C and 9D define the vertical output offset * of the visible region.
*/ #define NS2501_REG9C 0x9c #define NS2501_REG9D 0x9d
/* * The register 9F defines the dithering. This requires the * scaler to be ON. Bit 0 enables dithering, the remaining * bits control the depth of the dither. The higher the value, * the LOWER the dithering amplitude. A good value seems to be * 15 (total register value).
*/ #define NS2501_REGF9 0xf9 #define NS2501_F9_ENABLE_DITHER (1<<0) /* enable dithering */ #define NS2501_F9_DITHER_MASK (0x7f<<1) /* dither masking */ #define NS2501_F9_DITHER_SHIFT 1 /* upshift of the dither mask */
/* * Other configuration values left by the BIOS of the * Fujitsu S6010 in the DVO control registers. Their * value does not depend on the BIOS and their meaning * is unknown.
*/
/* ** Read a register from the ns2501. ** Returns true if successful, false otherwise. ** If it returns false, it might be wise to enable the ** DVO with the above function.
*/ staticbool ns2501_readb(struct intel_dvo_device *dvo, int addr, u8 *ch)
{ struct ns2501_priv *ns = dvo->dev_priv; struct i2c_adapter *adapter = dvo->i2c_bus;
u8 out_buf[2];
u8 in_buf[2];
if (!ns->quiet) {
DRM_DEBUG_KMS
("Unable to read register 0x%02x from %s:0x%02x.\n", addr,
adapter->name, dvo->target_addr);
}
returnfalse;
}
/* ** Write a register to the ns2501. ** Returns true if successful, false otherwise. ** If it returns false, it might be wise to enable the ** DVO with the above function.
*/ staticbool ns2501_writeb(struct intel_dvo_device *dvo, int addr, u8 ch)
{ struct ns2501_priv *ns = dvo->dev_priv; struct i2c_adapter *adapter = dvo->i2c_bus;
u8 out_buf[2];
if (i2c_transfer(adapter, &msg, 1) == 1) { returntrue;
}
if (!ns->quiet) {
DRM_DEBUG_KMS("Unable to write register 0x%02x to %s:%d\n",
addr, adapter->name, dvo->target_addr);
}
returnfalse;
}
/* National Semiconductor 2501 driver for chip on i2c bus * scan for the chip on the bus. * Hope the VBIOS initialized the PLL correctly so we can * talk to it. If not, it will not be seen and not detected. * Bummer!
*/ staticbool ns2501_init(struct intel_dvo_device *dvo, struct i2c_adapter *adapter)
{ /* this will detect the NS2501 chip on the specified i2c bus */ struct ns2501_priv *ns; unsignedchar ch;
ns = kzalloc(sizeof(*ns), GFP_KERNEL); if (ns == NULL) returnfalse;
staticenum drm_connector_status ns2501_detect(struct intel_dvo_device *dvo)
{ /* * This is a Laptop display, it doesn't have hotplugging. * Even if not, the detection bit of the 2501 is unreliable as * it only works for some display types. * It is even more unreliable as the PLL must be active for * allowing reading from the chip.
*/ return connector_status_connected;
}
/* * Currently, these are all the modes I have data from. * More might exist. Unclear how to find the native resolution * of the panel in here so we could always accept it * by disabling the scaler.
*/ if ((mode->hdisplay == 640 && mode->vdisplay == 480 && mode->clock == 25175) ||
(mode->hdisplay == 800 && mode->vdisplay == 600 && mode->clock == 40000) ||
(mode->hdisplay == 1024 && mode->vdisplay == 768 && mode->clock == 65000)) { return MODE_OK;
} else { return MODE_ONE_SIZE; /* Is this a reasonable error? */
}
}
/* Hopefully doing it every time won't hurt... */ for (i = 0; i < ARRAY_SIZE(regs_init); i++)
ns2501_writeb(dvo, regs_init[i].offset, regs_init[i].value);
/* Write the mode-agnostic values */ for (i = 0; i < ARRAY_SIZE(mode_agnostic_values); i++)
ns2501_writeb(dvo, mode_agnostic_values[i].offset,
mode_agnostic_values[i].value);
/* Write now the mode-specific configuration */
conf = ns2501_modes + mode_idx;
ns->conf = conf;
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.