2
0
mirror of https://github.com/lm-sensors/lm-sensors synced 2025-08-29 21:38:17 +00:00

Major update of the ddcmon driver.

Add half a dozen new features.
        Add checksum parameter (same as for the eeprom module)
        Fix monitor limits


git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1934 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
Jean Delvare 2003-08-01 17:42:08 +00:00
parent 7c3528bebb
commit 24e6a6352d
5 changed files with 671 additions and 55 deletions

View File

@ -1,7 +1,7 @@
Kernel driver `ddcmon.o'
========================
Status: Beta
Status: As complete as we want it to be, lightly tested
Supported chips:
* Any DDC Monitor EDID EEPROM chip at 0x50
@ -24,11 +24,15 @@ Supported chips:
24C16 16K 0x50 (additional data at 0x51 - 0x57)
Authors: Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>,
and Mark Studebaker <mdsxyz123@yahoo.com>
Author: Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock
<phil@netroedge.com>, Mark Studebaker <mdsxyz123@yahoo.com> and
Jean Delvare <khali@linux-fr.org>
Special assistance on DDC provided by Petr Vandrovec <vandrove@vc.cvut.cz>
License: GPL
Module Parameters
-----------------
@ -44,6 +48,8 @@ Module Parameters
List of adapter,address pairs to scan additionally
* probe_range: short array (min = 1, max = 48)
List of adapter,start-addr,end-addr triples to scan additionally
* checksum: int
Only accept eeproms whose checksum is correct
Description
@ -63,12 +69,31 @@ represent interesting data from the DDC monitor.
/proc entries:
ID: Encoded Monitor ID string.
For encoding, see 'sensors'
dpms: bitmask
DPMS support flags
0x20 Active Off
0x40 Suspend
0x80 Standby
edid: 2 integers
EDID version and revision
gamma: 1 float
gamma factor
id: 2 integers
manufacturer ID and product ID
Manufacturer ID is encoded, see 'sensors'
source ../../prog/sensors/chips.c.
maxclock: 1 integer
max pixel clock (also known as video bandwidth) (MHz)
0 if not available.
serial: 1 integer
serial number
Encoding depends on the manufacturer, don't expect the
real serial number here. 0 probably means "not available".
size: 2 integers
vertical monitor size (cm)
@ -79,8 +104,20 @@ represent interesting data from the DDC monitor.
maximum vertical sync frequency (Hz)
minimum horizontal sync frequency (KHz)
maximum horizontal sync frequency (KHz)
0 0 0 0 if not available.
timings: supported timings (bitmask)
time: 2 integers
Manufacture year and week
timing[1-8]: 3 integers
supported standard timing
horizontal resolution
vertical resolution
(vertical) refresh rate
0 0 0 if not used.
timings: bitmask
supported established timings
0x000001 720x400@70Hz (VGA 640x400, IBM)
0x000002 720x400@88Hz (XGA2)
0x000004 640x480@60Hz (VGA)
@ -98,15 +135,111 @@ represent interesting data from the DDC monitor.
0x004000 1024x768@75Hz (VESA)
0x008000 1280x1024@75Hz (VESA)
0x010000 - 0x800000 Manufacturer reserved
0x800000 1152x870 @ 75 Hz (Mac II, Apple)?
Notes:
Chip Features
-------------
Chip 'ddcmon'
LABEL LABEL CLASS COMPUTE CLASS MODE MAGN
Manufacturer ID - - R- 0
Model Number - - R- 0
Monitor Size (cm) - - R- 0
hsize Monitor Size (cm) - R- 0
Vertical Sync (Hz) - - R- 0
v_sync_max Vertical Sync (Hz) - R- 0
Horizontal Sync (KHz) - - R- 0
h_sync_max Horizontal Sync (KHz) - R- 0
Established Timings - - R- 0
Serial Number - - R- 0
Manufacture Time - - R- 0
week Manufacture Time - R- 0
EDID Version - - R- 0
revision EDID Version - R- 0
Gamma Factor - - R- 2
DPMS Modes - - R- 0
Standard Timing 1 - - R- 0
vertical Standard Timing 1 - R- 0
refresh Standard Timing 1 - R- 0
Standard Timing 2 - - R- 0
vertical Standard Timing 2 - R- 0
refresh Standard Timing 2 - R- 0
Standard Timing 3 - - R- 0
vertical Standard Timing 3 - R- 0
refresh Standard Timing 3 - R- 0
Standard Timing 4 - - R- 0
vertical Standard Timing 4 - R- 0
refresh Standard Timing 4 - R- 0
Standard Timing 5 - - R- 0
vertical Standard Timing 5 - R- 0
refresh Standard Timing 5 - R- 0
Standard Timing 6 - - R- 0
vertical Standard Timing 6 - R- 0
refresh Standard Timing 6 - R- 0
Standard Timing 7 - - R- 0
vertical Standard Timing 7 - R- 0
refresh Standard Timing 7 - R- 0
Standard Timing 8 - - R- 0
vertical Standard Timing 8 - R- 0
refresh Standard Timing 8 - R- 0
Max Pixel Clock (MHz) - - R- 0
LABEL FEATURE SYMBOL SYSCTL FILE:N
Manufacturer ID SENSORS_DDCMON_MAN_ID id:1
Model Number SENSORS_DDCMON_PROD_ID id:2
Monitor Size (cm) SENSORS_DDCMON_VERSIZE size:1
hsize SENSORS_DDCMON_HORSIZE size:2
Vertical Sync (Hz) SENSORS_DDCMON_VERSYNCMIN sync:1
v_sync_max SENSORS_DDCMON_VERSYNCMAX sync:2
Horizontal Sync (KHz) SENSORS_DDCMON_HORSYNCMIN sync:3
h_sync_max SENSORS_DDCMON_HORSYNCMAX sync:4
Established Timings SENSORS_DDCMON_TIMINGS timings:1
Serial Number SENSORS_DDCMON_SERIAL serial:1
Manufacture Time SENSORS_DDCMON_YEAR time:1
week SENSORS_DDCMON_WEEK time:2
EDID Version SENSORS_DDCMON_EDID_VER edid:1
revision SENSORS_DDCMON_EDID_REV edid:2
Gamma Factor SENSORS_DDCMON_GAMMA gamma:1
DPMS Modes SENSORS_DDCMON_DPMS dpms:1
Standard Timing 1 SENSORS_DDCMON_TIMING1_HOR timing1:1
vertical SENSORS_DDCMON_TIMING1_VER timing1:2
refresh SENSORS_DDCMON_TIMING1_REF timing1:3
Standard Timing 2 SENSORS_DDCMON_TIMING2_HOR timing2:1
vertical SENSORS_DDCMON_TIMING2_VER timing2:2
refresh SENSORS_DDCMON_TIMING2_REF timing2:3
Standard Timing 3 SENSORS_DDCMON_TIMING3_HOR timing3:1
vertical SENSORS_DDCMON_TIMING3_VER timing3:2
refresh SENSORS_DDCMON_TIMING3_REF timing3:3
Standard Timing 4 SENSORS_DDCMON_TIMING4_HOR timing4:1
vertical SENSORS_DDCMON_TIMING4_VER timing4:2
refresh SENSORS_DDCMON_TIMING4_REF timing4:3
Standard Timing 5 SENSORS_DDCMON_TIMING5_HOR timing5:1
vertical SENSORS_DDCMON_TIMING5_VER timing5:2
refresh SENSORS_DDCMON_TIMING5_REF timing5:3
Standard Timing 6 SENSORS_DDCMON_TIMING6_HOR timing6:1
vertical SENSORS_DDCMON_TIMING6_VER timing6:2
refresh SENSORS_DDCMON_TIMING6_REF timing6:3
Standard Timing 7 SENSORS_DDCMON_TIMING7_HOR timing7:1
vertical SENSORS_DDCMON_TIMING7_VER timing7:2
refresh SENSORS_DDCMON_TIMING7_REF timing7:3
Standard Timing 8 SENSORS_DDCMON_TIMING8_HOR timing8:1
vertical SENSORS_DDCMON_TIMING8_VER timing8:2
refresh SENSORS_DDCMON_TIMING8_REF timing8:3
Max Pixel Clock (MHz) SENSORS_DDCMON_MAXCLOCK maxclock:1
Notes
-----
- The eeprom.o module will also attach to a DDC monitor. Install the
ddcmon.o module before the eeprom.o module to prevent this.
Alternatively, give the eeprom.o module an ignore= parameter or
a checksum= parameter. The ddcmon.o module will not attach to non-DDC
eeproms because it checks for a DDC 'signature' at the beginning
of the DDC Monitor's eeprom.
of the DDC Monitor's eeprom. Additionally, you can give it a checksum=
parameter.
- If a DDC monitor eeprom lacks the 'signature', you may use the
'force' parameter (modprobe ddcmon force=x,0x50 where 'x' is the
@ -118,13 +251,15 @@ Notes:
(Matrox and NVidia, for example) are available in the kernel or
elsewhere. See our 'Supported Devices' web page for details.
- There is a checksum over the 128 bytes in the eeprom but the driver
does not check it.
- There is a checksum over the 128 bytes in the eeprom. The driver
used not to check it, now it does (providing you give it a
checksum= parameter).
- More information is available in the eeprom which could be made
available by enhancing the driver.
To see the entire eeprom, use the eeprom.o module instead of ddcmon.o.
However, then you lose the DDC-specific formatting.
Also see ../../prog/eeprom/decode-edid.pl.
- This driver does not support the DDC/CI (DDC2Bi) bidirectional
communications channel to the monitor for controlling the monitor.
@ -133,4 +268,5 @@ Notes:
from the eeprom if the cache is more than 5 minutes old.
- X 4.0 also accesses the DDC monitor EEPROM to auto-configure itself.
There could possibly be conflicts from these multiple accesses.
There could possibly be conflicts from these multiple accesses, but
none were ever reported so far.

View File

@ -4,6 +4,7 @@
Copyright (c) 1998, 1999, 2000 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
and Mark Studebaker <mdsxyz123@yahoo.com>
Copyright (c) 2003 Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -38,18 +39,34 @@ static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
/* Insmod parameters */
SENSORS_INSMOD_1(ddcmon);
static int checksum = 0;
MODULE_PARM(checksum, "i");
MODULE_PARM_DESC(checksum, "Only accept eeproms whose checksum is correct");
/* Many constants specified below */
/* DDCMON registers */
#define DDCMON_REG_ID 0x08
/* vendor section */
#define DDCMON_REG_MAN_ID 0x08
#define DDCMON_REG_PROD_ID 0x0A
#define DDCMON_REG_SERIAL 0x0C
#define DDCMON_REG_WEEK 0x10
#define DDCMON_REG_YEAR 0x11
/* EDID version */
#define DDCMON_REG_EDID_VER 0x12
#define DDCMON_REG_EDID_REV 0x13
/* display information */
#define DDCMON_REG_HORSIZE 0x15
#define DDCMON_REG_VERSIZE 0x16
#define DDCMON_REG_TIMINGS 0x23
#define DDCMON_REG_GAMMA 0x17
#define DDCMON_REG_DPMS_FLAGS 0x18
/* supported timings */
#define DDCMON_REG_ESTABLISHED_TIMINGS 0x23
#define DDCMON_REG_STANDARD_TIMINGS 0x26
#define DDCMON_REG_TIMBASE 0x36
#define DDCMON_REG_TIMINCR 18
#define DDCMON_REG_TIMNUM 4
#define DDCMON_REG_TIMOFFSET 5
#define DDCMON_REG_CHECKSUM 0x7f
/* Size of DDCMON in bytes */
@ -64,7 +81,6 @@ struct ddcmon_data {
unsigned long last_updated; /* In jiffies */
u8 data[DDCMON_SIZE]; /* Register values */
int memtype;
};
@ -79,10 +95,22 @@ static void ddcmon_size(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_sync(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_maxclock(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_timings(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_serial(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_time(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_edid(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_gamma(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_dpms(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_standard_timing(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results);
static void ddcmon_update_client(struct i2c_client *client);
@ -97,11 +125,25 @@ static struct i2c_driver ddcmon_driver = {
};
/* -- SENSORS SYSCTL START -- */
#define DDCMON_SYSCTL_ID 1010
#define DDCMON_SYSCTL_SIZE 1011
#define DDCMON_SYSCTL_SYNC 1012
#define DDCMON_SYSCTL_TIMINGS 1013
#define DDCMON_SYSCTL_SERIAL 1014
#define DDCMON_SYSCTL_TIME 1015
#define DDCMON_SYSCTL_EDID 1016
#define DDCMON_SYSCTL_GAMMA 1017
#define DDCMON_SYSCTL_DPMS 1018
#define DDCMON_SYSCTL_TIMING1 1021
#define DDCMON_SYSCTL_TIMING2 1022
#define DDCMON_SYSCTL_TIMING3 1023
#define DDCMON_SYSCTL_TIMING4 1024
#define DDCMON_SYSCTL_TIMING5 1025
#define DDCMON_SYSCTL_TIMING6 1026
#define DDCMON_SYSCTL_TIMING7 1027
#define DDCMON_SYSCTL_TIMING8 1028
#define DDCMON_SYSCTL_MAXCLOCK 1029
/* -- SENSORS SYSCTL END -- */
@ -111,7 +153,7 @@ static struct i2c_driver ddcmon_driver = {
is done through one of the 'extra' fields which are initialized
when a new copy is allocated. */
static ctl_table ddcmon_dir_table_template[] = {
{DDCMON_SYSCTL_ID, "ID", NULL, 0, 0444, NULL, &i2c_proc_real,
{DDCMON_SYSCTL_ID, "id", NULL, 0, 0444, NULL, &i2c_proc_real,
&i2c_sysctl_real, NULL, &ddcmon_idcall},
{DDCMON_SYSCTL_SIZE, "size", NULL, 0, 0444, NULL, &i2c_proc_real,
&i2c_sysctl_real, NULL, &ddcmon_size},
@ -121,6 +163,32 @@ static ctl_table ddcmon_dir_table_template[] = {
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_timings},
{DDCMON_SYSCTL_SERIAL, "serial", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_serial},
{DDCMON_SYSCTL_TIME, "time", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_time},
{DDCMON_SYSCTL_EDID, "edid", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_edid},
{DDCMON_SYSCTL_GAMMA, "gamma", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_gamma},
{DDCMON_SYSCTL_DPMS, "dpms", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_dpms},
{DDCMON_SYSCTL_TIMING1, "timing1", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING2, "timing2", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING3, "timing3", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING4, "timing4", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING5, "timing5", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING6, "timing6", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING7, "timing7", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_TIMING8, "timing8", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_standard_timing},
{DDCMON_SYSCTL_MAXCLOCK, "maxclock", NULL, 0, 0444, NULL,
&i2c_proc_real, &i2c_sysctl_real, NULL, &ddcmon_maxclock},
{0}
};
@ -163,6 +231,16 @@ int ddcmon_detect(struct i2c_adapter *adapter, int address,
new_client->flags = 0;
/* Now, we do the remaining detection. */
if (checksum) {
int cs = 0;
/* prevent 24RF08 corruption (just in case) */
i2c_smbus_write_quick(new_client, 0);
for (i = 0; i < 0x80; i++)
cs += i2c_smbus_read_byte_data(new_client, i);
if ((cs & 0xff) != 0)
goto ERROR1;
}
/* Verify the first 8 locations 0x00FFFFFFFFFFFF00 */
/* Allow force and force_ddcmon arguments */
if(kind < 0)
@ -273,11 +351,11 @@ void ddcmon_idcall(struct i2c_client *client, int operation,
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
results[0] = data->data[DDCMON_REG_ID + 1] |
(data->data[DDCMON_REG_ID] << 8) |
(data->data[DDCMON_REG_ID + 3] << 16) |
(data->data[DDCMON_REG_ID + 2] << 24);
*nrels_mag = 1;
results[0] = data->data[DDCMON_REG_MAN_ID + 1] |
(data->data[DDCMON_REG_MAN_ID] << 8);
results[1] = data->data[DDCMON_REG_PROD_ID + 1] |
(data->data[DDCMON_REG_PROD_ID] << 8);
*nrels_mag = 2;
}
}
@ -307,15 +385,17 @@ void ddcmon_sync(struct i2c_client *client, int operation,
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
*nrels_mag = 4;
/* look for sync entry */
/* look for monitor limits entry */
for(i = DDCMON_REG_TIMBASE;
i < DDCMON_REG_TIMBASE +
(DDCMON_REG_TIMNUM * DDCMON_REG_TIMINCR);
i += DDCMON_REG_TIMINCR) {
if(data->data[i] == 0) {
if (data->data[i] == 0x00
&& data->data[i + 1] == 0x00
&& data->data[i + 2] == 0x00
&& data->data[i + 3] == 0xfd) {
for(j = 0; j < 4; j++)
results[j] = data->data[i + j +
DDCMON_REG_TIMOFFSET];
results[j] = data->data[i + j + 5];
return;
}
}
@ -324,6 +404,35 @@ void ddcmon_sync(struct i2c_client *client, int operation,
}
}
void ddcmon_maxclock(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
int i;
struct ddcmon_data *data = client->data;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
*nrels_mag = 1;
/* look for monitor limits entry */
for(i = DDCMON_REG_TIMBASE;
i < DDCMON_REG_TIMBASE +
(DDCMON_REG_TIMNUM * DDCMON_REG_TIMINCR);
i += DDCMON_REG_TIMINCR) {
if (data->data[i] == 0x00
&& data->data[i + 1] == 0x00
&& data->data[i + 2] == 0x00
&& data->data[i + 3] == 0xfd) {
results[0] = (data->data[i + 9] == 0xff ?
0 : data->data[i + 9] * 10);
return;
}
}
results[0] = 0;
}
}
void ddcmon_timings(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
@ -333,9 +442,9 @@ void ddcmon_timings(struct i2c_client *client, int operation,
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
results[0] = data->data[DDCMON_REG_TIMINGS] |
(data->data[DDCMON_REG_TIMINGS + 1] << 8) |
(data->data[DDCMON_REG_TIMINGS + 2] << 16);
results[0] = data->data[DDCMON_REG_ESTABLISHED_TIMINGS] |
(data->data[DDCMON_REG_ESTABLISHED_TIMINGS + 1] << 8) |
(data->data[DDCMON_REG_ESTABLISHED_TIMINGS + 2] << 16);
*nrels_mag = 1;
}
}
@ -357,6 +466,105 @@ void ddcmon_serial(struct i2c_client *client, int operation,
}
}
void ddcmon_time(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct ddcmon_data *data = client->data;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
results[0] = data->data[DDCMON_REG_YEAR] + 1990;
results[1] = data->data[DDCMON_REG_WEEK];
*nrels_mag = 2;
}
}
void ddcmon_edid(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct ddcmon_data *data = client->data;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
results[0] = data->data[DDCMON_REG_EDID_VER];
results[1] = data->data[DDCMON_REG_EDID_REV];
*nrels_mag = 2;
}
}
void ddcmon_gamma(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct ddcmon_data *data = client->data;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 2;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
results[0] = 100 + data->data[DDCMON_REG_GAMMA];
*nrels_mag = 1;
}
}
void ddcmon_dpms(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct ddcmon_data *data = client->data;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
results[0] = data->data[DDCMON_REG_DPMS_FLAGS];
*nrels_mag = 1;
}
}
void ddcmon_standard_timing(struct i2c_client *client, int operation,
int ctl_name, int *nrels_mag, long *results)
{
struct ddcmon_data *data = client->data;
int nr = ctl_name - DDCMON_SYSCTL_TIMING1;
if (operation == SENSORS_PROC_REAL_INFO)
*nrels_mag = 0;
else if (operation == SENSORS_PROC_REAL_READ) {
ddcmon_update_client(client);
/* If both bytes of the timing are 0x00 or 0x01, then the timing
slot is unused. */
if ((data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2]
| data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1]) & 0xfe) {
results[0] = (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2] + 31) * 8;
switch (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1] >> 6) {
/* We don't care about rounding issues there, it really
should be OK without it. */
case 0x00:
results[1] = results[0]; /* unconfirmed */
break;
case 0x01:
results[1] = results[0] * 3 / 4;
break;
case 0x02:
results[1] = results[0] * 4 / 5;
break;
case 0x03:
results[1] = results[0] * 9 / 16;
break;
}
results[2] = (data->data[DDCMON_REG_STANDARD_TIMINGS + nr * 2 + 1] & 0x3f) + 60;
} else {
results[0] = 0;
results[1] = 0;
results[2] = 0;
}
*nrels_mag = 3;
}
}
static int __init sm_ddcmon_init(void)
{
printk("ddcmon.o version %s (%s)\n", LM_VERSION, LM_DATE);
@ -371,8 +579,9 @@ static void __exit sm_ddcmon_exit(void)
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"Philip Edelbrock <phil@netroedge .com>, "
"and Mark Studebaker <mdsxyz123@yahoo.com>");
"Philip Edelbrock <phil@netroedge.com>, "
"Mark Studebaker <mdsxyz123@yahoo.com> "
"and Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("DDCMON driver");
module_init(sm_ddcmon_init);

View File

@ -2515,9 +2515,12 @@ static sensors_chip_feature via686a_features[] =
static sensors_chip_feature ddcmon_features[] =
{
{ SENSORS_DDCMON_ID, "Monitor ID",
{ SENSORS_DDCMON_MAN_ID, "Manufacturer ID",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_ID, VALUE(1), 0 },
{ SENSORS_DDCMON_PROD_ID, "Model Number",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_ID, VALUE(2), 0 },
{ SENSORS_DDCMON_VERSIZE, "Monitor Size (cm)",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_SIZE, VALUE(1), 0 },
@ -2536,12 +2539,105 @@ static sensors_chip_feature ddcmon_features[] =
{ SENSORS_DDCMON_HORSYNCMAX, "h_sync_max",
SENSORS_DDCMON_HORSYNCMIN, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_SYNC, VALUE(4), 0 },
{ SENSORS_DDCMON_TIMINGS, "timings",
{ SENSORS_DDCMON_TIMINGS, "Established Timings",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMINGS, VALUE(1), 0 },
{ SENSORS_DDCMON_SERIAL, "Serial number",
{ SENSORS_DDCMON_SERIAL, "Serial Number",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_SERIAL, VALUE(1), 0 },
{ SENSORS_DDCMON_YEAR, "Manufacture Time",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIME, VALUE(1), 0 },
{ SENSORS_DDCMON_WEEK, "week",
SENSORS_DDCMON_YEAR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIME, VALUE(2), 0 },
{ SENSORS_DDCMON_EDID_VER, "EDID Version",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_EDID, VALUE(1), 0 },
{ SENSORS_DDCMON_EDID_REV, "revision",
SENSORS_DDCMON_EDID_VER, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_EDID, VALUE(2), 0 },
{ SENSORS_DDCMON_GAMMA, "Gamma Factor",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_GAMMA, VALUE(1), 2 },
{ SENSORS_DDCMON_DPMS, "DPMS Modes",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_DPMS, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING1_HOR, "Standard Timing 1",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING1, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING1_VER, "vertical",
SENSORS_DDCMON_TIMING1_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING1, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING1_REF, "refresh",
SENSORS_DDCMON_TIMING1_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING1, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING2_HOR, "Standard Timing 2",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING2, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING2_VER, "vertical",
SENSORS_DDCMON_TIMING2_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING2, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING2_REF, "refresh",
SENSORS_DDCMON_TIMING2_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING2, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING3_HOR, "Standard Timing 3",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING3, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING3_VER, "vertical",
SENSORS_DDCMON_TIMING3_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING3, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING3_REF, "refresh",
SENSORS_DDCMON_TIMING3_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING3, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING4_HOR, "Standard Timing 4",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING4, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING4_VER, "vertical",
SENSORS_DDCMON_TIMING4_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING4, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING4_REF, "refresh",
SENSORS_DDCMON_TIMING4_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING4, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING5_HOR, "Standard Timing 5",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING5, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING5_VER, "vertical",
SENSORS_DDCMON_TIMING5_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING5, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING5_REF, "refresh",
SENSORS_DDCMON_TIMING5_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING5, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING6_HOR, "Standard Timing 6",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING6, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING6_VER, "vertical",
SENSORS_DDCMON_TIMING6_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING6, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING6_REF, "refresh",
SENSORS_DDCMON_TIMING6_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING6, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING7_HOR, "Standard Timing 7",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING7, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING7_VER, "vertical",
SENSORS_DDCMON_TIMING7_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING7, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING7_REF, "refresh",
SENSORS_DDCMON_TIMING7_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING7, VALUE(3), 0 },
{ SENSORS_DDCMON_TIMING8_HOR, "Standard Timing 8",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING8, VALUE(1), 0 },
{ SENSORS_DDCMON_TIMING8_VER, "vertical",
SENSORS_DDCMON_TIMING8_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING8, VALUE(2), 0 },
{ SENSORS_DDCMON_TIMING8_REF, "refresh",
SENSORS_DDCMON_TIMING8_HOR, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_TIMING8, VALUE(3), 0 },
{ SENSORS_DDCMON_MAXCLOCK, "Max Pixel Clock (MHz)",
SENSORS_NO_MAPPING, SENSORS_NO_MAPPING,
SENSORS_MODE_R, DDCMON_SYSCTL_MAXCLOCK, VALUE(1), 0 },
{ 0 }
};

View File

@ -1120,15 +1120,47 @@
#define SENSORS_DDCMON_PREFIX "ddcmon"
#define SENSORS_DDCMON_ID 10
#define SENSORS_DDCMON_MAN_ID 10
#define SENSORS_DDCMON_PROD_ID 11
#define SENSORS_DDCMON_YEAR 13
#define SENSORS_DDCMON_WEEK 14
#define SENSORS_DDCMON_EDID_VER 15
#define SENSORS_DDCMON_EDID_REV 16
#define SENSORS_DDCMON_HORSIZE 21
#define SENSORS_DDCMON_VERSIZE 22
#define SENSORS_DDCMON_GAMMA 23
#define SENSORS_DDCMON_DPMS 24
#define SENSORS_DDCMON_HORSYNCMIN 31
#define SENSORS_DDCMON_HORSYNCMAX 32
#define SENSORS_DDCMON_VERSYNCMIN 33
#define SENSORS_DDCMON_VERSYNCMAX 34
#define SENSORS_DDCMON_MAXCLOCK 35
#define SENSORS_DDCMON_SERIAL 40
#define SENSORS_DDCMON_TIMINGS 50
#define SENSORS_DDCMON_TIMING1_HOR 51
#define SENSORS_DDCMON_TIMING1_VER 52
#define SENSORS_DDCMON_TIMING1_REF 53
#define SENSORS_DDCMON_TIMING2_HOR 54
#define SENSORS_DDCMON_TIMING2_VER 55
#define SENSORS_DDCMON_TIMING2_REF 56
#define SENSORS_DDCMON_TIMING3_HOR 57
#define SENSORS_DDCMON_TIMING3_VER 58
#define SENSORS_DDCMON_TIMING3_REF 59
#define SENSORS_DDCMON_TIMING4_HOR 60
#define SENSORS_DDCMON_TIMING4_VER 61
#define SENSORS_DDCMON_TIMING4_REF 62
#define SENSORS_DDCMON_TIMING5_HOR 63
#define SENSORS_DDCMON_TIMING5_VER 64
#define SENSORS_DDCMON_TIMING5_REF 65
#define SENSORS_DDCMON_TIMING6_HOR 66
#define SENSORS_DDCMON_TIMING6_VER 67
#define SENSORS_DDCMON_TIMING6_REF 68
#define SENSORS_DDCMON_TIMING7_HOR 69
#define SENSORS_DDCMON_TIMING7_VER 70
#define SENSORS_DDCMON_TIMING7_REF 71
#define SENSORS_DDCMON_TIMING8_HOR 72
#define SENSORS_DDCMON_TIMING8_VER 73
#define SENSORS_DDCMON_TIMING8_REF 74
/* EEPROM (SDRAM DIMM) */

View File

@ -2638,29 +2638,33 @@ void print_maxilife(const sensors_chip_name *name)
void print_ddcmon(const sensors_chip_name *name)
{
char *label = NULL;
double a, b;
double a, b, c;
int valid, i;
char s[8];
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_ID, &label,&valid) &&
!sensors_get_feature(*name, SENSORS_DDCMON_ID, &a)) {
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_MAN_ID, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_MAN_ID, &a)) {
if (valid) {
i = (int) a;
s[0] = ((i >> 10) & 0x1f) | 0x40;
s[1] = ((i >> 5) & 0x1f) | 0x40;
s[2] = (i & 0x1f) | 0x40;
s[3] = ((i >> 20) & 0x0f) + '0';
s[4] = ((i >> 16) & 0x0f) + '0';
s[5] = ((i >> 28) & 0x0f) + '0';
s[6] = ((i >> 24) & 0x0f) + '0';
s[7] = 0;
i = (int) a;
print_label(label, 24);
printf("%s\n", s);
printf("%c%c%c\n",
((i >> 10) & 0x1f) + 'A' - 1, ((i >> 5) & 0x1f) + 'A' - 1,
(i & 0x1f) + 'A' - 1);
}
} else
printf("ERROR: data 1\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_PROD_ID, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_PROD_ID, &a)) {
if (valid) {
i = (int) a;
print_label(label, 24);
printf("0x%04X\n", i);
}
} else
printf("ERROR: data 2\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_SERIAL, &label,&valid) &&
!sensors_get_feature(*name, SENSORS_DDCMON_SERIAL, &a)) {
if (valid) {
@ -2668,7 +2672,29 @@ void print_ddcmon(const sensors_chip_name *name)
printf("%d\n", (int) a);
}
} else
printf("ERROR: data 2\n");
printf("ERROR: data 3\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_YEAR, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_YEAR, &a)
&& !sensors_get_feature(*name, SENSORS_DDCMON_WEEK, &b)) {
if (valid) {
print_label(label, 24);
printf("%d-W%d\n", (int) a, (int) b);
}
} else
printf("ERROR: data 4\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_EDID_VER, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_EDID_VER, &a)
&& !sensors_get_feature(*name, SENSORS_DDCMON_EDID_REV, &b)) {
if (valid) {
print_label(label, 24);
printf("%d.%d\n", (int) a, (int) b);
}
} else
printf("ERROR: data 5\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_VERSIZE, &label,&valid) &&
@ -2679,31 +2705,148 @@ void print_ddcmon(const sensors_chip_name *name)
printf("%dx%d\n", (int) a, (int) b);
}
} else
printf("ERROR: data 3\n");
printf("ERROR: data 6\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_GAMMA, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_GAMMA, &a)) {
if (valid) {
print_label(label, 24);
printf("%.02f\n", a);
}
} else
printf("ERROR: data 7\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_DPMS, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_DPMS, &a)) {
if (valid) {
i = (int) a;
print_label(label, 24);
if (i & 0xe0) {
printf("%s%s%s%s%s\n",
i & 0x20 ? "Active Off" : "",
(i & 0x40) && (i & 0x20) ? ", ": "",
i & 0x40 ? "Suspend" : "",
(i & 0x80) && (i & 0x60) ? ", ": "",
i & 0x80 ? "Standby" : "");
} else {
printf("None supported\n");
}
}
} else
printf("ERROR: data 8\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_TIMINGS, &label,&valid) &&
!sensors_get_feature(*name, SENSORS_DDCMON_TIMINGS, &a)) {
if (valid) {
i = (int) a;
if (i & 0x03) { /* 720x400 */
print_label(label, 24);
printf("720x400 @ %s%s%s Hz\n",
i & 0x01 ? "70" : "",
(i & 0x02) && (i & 0x01) ? "/" : "",
i & 0x02 ? "88" : "");
}
if (i & 0x3c) { /* 640x480 */
print_label(label, 24);
printf("640x480 @ %s%s%s%s%s%s%s Hz\n",
i & 0x04 ? "60" : "",
(i & 0x08) && (i & 0x04) ? "/" : "",
i & 0x08 ? "67" : "",
(i & 0x10) && (i & 0x0c) ? "/" : "",
i & 0x10 ? "72" : "",
(i & 0x20) && (i & 0x1c) ? "/" : "",
i & 0x20 ? "75" : "");
}
i >>= 6;
if (i & 0x0f) { /* 800x600 */
print_label(label, 24);
printf("800x600 @ %s%s%s%s%s%s%s Hz\n",
i & 0x01 ? "56" : "",
(i & 0x02) && (i & 0x01) ? "/" : "",
i & 0x02 ? "60" : "",
(i & 0x04) && (i & 0x03) ? "/" : "",
i & 0x04 ? "72" : "",
(i & 0x08) && (i & 0x07) ? "/" : "",
i & 0x08 ? "75" : "");
}
if (i & 0x10) { /* 832x624 */
print_label(label, 24);
printf("832x624 @ 75 Hz\n");
}
i >>= 5;
if (i & 0x0f) { /* 1024x768 */
print_label(label, 24);
printf("1024x768 @ %s%s%s%s%s%s%s Hz\n",
i & 0x01 ? "87i" : "",
(i & 0x02) && (i & 0x01) ? "/" : "",
i & 0x02 ? "60" : "",
(i & 0x04) && (i & 0x03) ? "/" : "",
i & 0x04 ? "70" : "",
(i & 0x08) && (i & 0x07) ? "/" : "",
i & 0x08 ? "75" : "");
}
if (i & 0x100) { /* 1152x870 */
print_label(label, 24);
printf("1152x870 @ 75 Hz\n");
}
if (i & 0x10) { /* 1280x1024 */
print_label(label, 24);
printf("1280x1024 @ 75 Hz\n");
}
}
} else
printf("ERROR: data 9\n");
free_the_label(&label);
for(i = 0; i < 8; i++) {
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_TIMING1_HOR + i * 3, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_TIMING1_HOR + i * 3, &a)
&& !sensors_get_feature(*name, SENSORS_DDCMON_TIMING1_VER + i * 3, &b)
&& !sensors_get_feature(*name, SENSORS_DDCMON_TIMING1_REF + i * 3, &c)) {
if (valid && ((int) a) != 0) {
print_label(label, 24);
printf("%dx%d @ %d Hz\n", (int) a, (int) b, (int) c);
}
} else
printf("ERROR: data 10-%d\n", i+1);
free_the_label(&label);
}
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_VERSYNCMIN, &label,&valid) &&
!sensors_get_feature(*name, SENSORS_DDCMON_VERSYNCMIN, &a) &&
!sensors_get_feature(*name, SENSORS_DDCMON_VERSYNCMAX, &b)) {
if (valid) {
if (valid && ((int) a) != 0) {
print_label(label, 24);
printf("%d-%d\n", (int) a, (int) b);
}
} else
printf("ERROR: data 4\n");
printf("ERROR: data 11\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_HORSYNCMIN, &label,&valid) &&
!sensors_get_feature(*name, SENSORS_DDCMON_HORSYNCMIN, &a) &&
!sensors_get_feature(*name, SENSORS_DDCMON_HORSYNCMAX, &b)) {
if (valid) {
if (valid && ((int) a) != 0) {
print_label(label, 24);
printf("%d-%d\n", (int) a, (int) b);
}
} else
printf("ERROR: data 5\n");
printf("ERROR: data 12\n");
free_the_label(&label);
if (!sensors_get_label_and_valid(*name, SENSORS_DDCMON_MAXCLOCK, &label, &valid)
&& !sensors_get_feature(*name, SENSORS_DDCMON_MAXCLOCK, &a)) {
if (valid && ((int) a) != 0) {
print_label(label, 24);
printf("%d\n", (int) a);
}
} else
printf("ERROR: data 13\n");
free_the_label(&label);
}
/*