2 * Handle reading the EDID information, validating it, and parsing it into
3 * a struct edid_info. EDID reads are done using the Block Device Protocol
4 * as it's already supported by the cat24c256 driver and there is no need
5 * to add yet another message format/type.
9 #include <minix/chardriver.h>
10 #include <minix/drivers.h>
13 #include <minix/log.h>
14 #include <minix/sysutil.h>
15 #include <minix/type.h>
17 #include <sys/ioc_fb.h>
19 #include <sys/ioctl.h>
26 #include <dev/videomode/videomode.h>
27 #include <dev/videomode/edidvar.h>
28 #include <dev/videomode/edidreg.h>
33 static int do_read(endpoint_t endpt
, uint8_t *buf
, size_t bufsize
);
35 /* logging - use with log_warn(), log_info(), log_debug(), log_trace() */
36 static struct log log
= {
38 .log_level
= LEVEL_INFO
,
39 .log_func
= default_log
43 * Labels corresponding to drivers which provide EDID.
45 static char edid_providers
[FB_DEV_NR
][RS_MAX_LABEL_LEN
+1];
48 * Populate edid_providers from command line arguments. The minix-service
49 * command should get EDID providers like this: "-args edid.0=tda19988.1.3470"
50 * where 0 is the minor number of the frame buffer, tda19988 is the device
51 * driver, 1 is the i2c bus and 3470 is the slave address (the TDA19988 has 2
52 * slave addresses 0x34 and 0x70).
55 fb_edid_args_parse(void)
61 for (i
= 0; i
< FB_DEV_NR
; i
++) {
63 memset(key
, '\0', 32);
64 snprintf(key
, 32, "edid.%d", i
);
66 memset(edid_providers
[i
], '\0', RS_MAX_LABEL_LEN
);
67 r
= env_get_param(key
, edid_providers
[i
], RS_MAX_LABEL_LEN
);
69 log_debug(&log
, "Found key:%s value:%s\n", key
, edid_providers
[i
]);
71 /* not an error, user is allowed to omit EDID
72 * providers in order to skip EDID reading and use
73 * the default settings.
75 log_debug(&log
, "Couldn't find key:%s\n", key
);
83 * Send a read request to the block driver at endpoint endpt.
86 do_read(endpoint_t driver_endpt
, uint8_t *buf
, size_t bufsize
)
90 cp_grant_id_t grant_nr
;
92 /* Open Device - required for drivers using libblockdriver */
93 memset(&m
, '\0', sizeof(message
));
95 m
.m_lbdev_lblockdriver_msg
.access
= BDEV_R_BIT
;
96 m
.m_lbdev_lblockdriver_msg
.id
= 0;
97 m
.m_lbdev_lblockdriver_msg
.minor
= 0;
99 r
= ipc_sendrec(driver_endpt
, &m
);
101 log_debug(&log
, "ipc_sendrec(BDEV_OPEN) failed (r=%d)\n", r
);
105 grant_nr
= cpf_grant_direct(driver_endpt
, (vir_bytes
) buf
,
106 bufsize
, CPF_READ
| CPF_WRITE
);
108 /* Perform the read */
109 memset(&m
, '\0', sizeof(message
));
110 m
.m_type
= BDEV_READ
;
111 m
.m_lbdev_lblockdriver_msg
.minor
= 0;
112 m
.m_lbdev_lblockdriver_msg
.count
= bufsize
;
113 m
.m_lbdev_lblockdriver_msg
.grant
= grant_nr
;
114 m
.m_lbdev_lblockdriver_msg
.flags
= BDEV_NOPAGE
; /* the EEPROMs used for EDID are pageless */
115 m
.m_lbdev_lblockdriver_msg
.id
= 0;
116 m
.m_lbdev_lblockdriver_msg
.pos
= 0;
118 r
= ipc_sendrec(driver_endpt
, &m
);
119 cpf_revoke(grant_nr
);
121 log_debug(&log
, "ipc_sendrec(BDEV_READ) failed (r=%d)\n", r
);
122 /* Clean-up: try to close the device */
123 memset(&m
, '\0', sizeof(message
));
124 m
.m_type
= BDEV_CLOSE
;
125 m
.m_lbdev_lblockdriver_msg
.minor
= 0;
126 m
.m_lbdev_lblockdriver_msg
.id
= 0;
127 ipc_sendrec(driver_endpt
, &m
);
131 /* Close the device */
132 memset(&m
, '\0', sizeof(message
));
133 m
.m_type
= BDEV_CLOSE
;
134 m
.m_lbdev_lblockdriver_msg
.minor
= 0;
135 m
.m_lbdev_lblockdriver_msg
.id
= 0;
136 r
= ipc_sendrec(driver_endpt
, &m
);
138 log_debug(&log
, "ipc_sendrec(BDEV_CLOSE) failed (r=%d)\n", r
);
146 fb_edid_read(int minor
, struct edid_info
*info
)
153 if (info
== NULL
|| minor
< 0 || minor
>= FB_DEV_NR
||
154 edid_providers
[minor
][0] == '\0') {
158 log_debug(&log
, "Contacting %s to get EDID.\n", edid_providers
[minor
]);
160 /* Look up the endpoint that corresponds to the label */
162 r
= ds_retrieve_label_endpt(edid_providers
[minor
], &endpt
);
163 if (r
!= 0 || endpt
== 0) {
164 log_warn(&log
, "Couldn't find endpoint for label '%s'\n", edid_providers
[minor
]);
168 /* Perform the request and put the resulting EDID into the buffer. */
169 memset(buffer
, 0x00, 128);
170 r
= do_read(endpt
, buffer
, 128);
172 log_debug(&log
, "Failed to read EDID\n");
176 /* parse and validate EDID */
177 r
= edid_parse(buffer
, info
);
179 log_warn(&log
, "Invalid EDID data in buffer.\n");
183 log_debug(&log
, "EDID Retrieved and Parsed OK\n");