1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <lib/edid/edid.h>
6 #include <math.h>
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include "eisa_vid_lut.h"
11 
12 namespace {
13 
base_validate(const T * block)14 template<typename T> bool base_validate(const T* block) {
15     static_assert(sizeof(T) == edid::kBlockSize, "Size check for Edid struct");
16 
17     const uint8_t* edid_bytes = reinterpret_cast<const uint8_t*>(block);
18     if (edid_bytes[0] != T::kTag) {
19         return false;
20     }
21 
22     // The last byte of the 128-byte EDID data is a checksum byte which
23     // should make the 128 bytes sum to zero.
24     uint8_t sum = 0;
25     for (uint32_t i = 0; i < edid::kBlockSize; ++i) {
26         sum = static_cast<uint8_t>(sum + edid_bytes[i]);
27     }
28     return sum == 0;
29 }
30 
round_div(double num,double div)31 uint32_t round_div(double num, double div) {
32     return (uint32_t) ((num / div) + .5);
33 }
34 
35 } // namespace
36 
37 namespace edid {
38 
validate() const39 bool BaseEdid::validate() const {
40     static const uint8_t kEdidHeader[8] = {0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0};
41     return base_validate<BaseEdid>(this) && memcmp(header, kEdidHeader, sizeof(kEdidHeader)) == 0;
42 }
43 
validate() const44 bool CeaEdidTimingExtension::validate() const {
45     if (!(dtd_start_idx <= sizeof(payload) && base_validate<CeaEdidTimingExtension>(this))) {
46         return false;
47     }
48     size_t offset = 0;
49     size_t dbc_end = dtd_start_idx - offsetof(CeaEdidTimingExtension, payload);
50     while (offset < dbc_end) {
51         const DataBlock* data_block = reinterpret_cast<const DataBlock*>(payload + offset);
52         offset += (1 + data_block->length()); // Length doesn't include the header
53         // Check that the block doesn't run past the end if the dbc
54         if (offset > dbc_end) {
55             return false;
56         }
57     }
58     return true;
59 }
60 
Init(void * ctx,ddc_i2c_transact transact,const char ** err_msg)61 bool Edid::Init(void* ctx, ddc_i2c_transact transact, const char** err_msg) {
62     uint8_t segment_address = 0;
63     uint8_t segment_offset = 0;
64     ddc_i2c_msg_t msgs[3] = {
65         { .is_read = false, .addr = kDdcSegmentI2cAddress, .buf = &segment_address, .length = 1 },
66         { .is_read = false, .addr = kDdcDataI2cAddress, .buf = &segment_offset, .length = 1 },
67         { .is_read = true, .addr = kDdcDataI2cAddress, .buf = nullptr, .length = kBlockSize },
68     };
69 
70     BaseEdid base_edid;
71     msgs[2].buf = reinterpret_cast<uint8_t*>(&base_edid);
72     // + 1 to skip trying to set the segment for the first block
73     if (!transact(ctx, msgs + 1, 2)) {
74         *err_msg = "Failed to read base edid";
75         return false;
76     } else if (!base_edid.validate()) {
77         *err_msg = "Failed to validate base edid";
78         return false;
79     }
80 
81     uint16_t edid_length = static_cast<uint16_t>((base_edid.num_extensions + 1) * kBlockSize);
82     fbl::AllocChecker ac;
83     edid_bytes_ = fbl::unique_ptr<uint8_t[]>(new (&ac) uint8_t[edid_length]);
84     if (!ac.check()) {
85         *err_msg = "Failed to allocate edid storage";
86         return false;
87     }
88 
89     memcpy(edid_bytes_.get(), reinterpret_cast<void*>(&base_edid), kBlockSize);
90     for (uint8_t i = 1; i && i <= base_edid.num_extensions; i++) {
91         *msgs[0].buf = i / 2;
92         *msgs[1].buf = i % 2 ? kBlockSize : 0;
93         msgs[2].buf = edid_bytes_.get() + i * kBlockSize;
94         bool include_segment = i % 2;
95         if (!transact(ctx, msgs + include_segment, 3 - include_segment)) {
96             *err_msg = "Failed to read full edid";
97             return false;
98         }
99     }
100 
101     return Init(edid_bytes_.get(), edid_length, err_msg);
102 }
103 
Init(const uint8_t * bytes,uint16_t len,const char ** err_msg)104 bool Edid::Init(const uint8_t* bytes, uint16_t len, const char** err_msg) {
105     // The maximum size of an edid is 255 * 128 bytes, so any 16 bit multiple is fine.
106     if (len == 0 || len % kBlockSize != 0) {
107         *err_msg = "Invalid edid length";
108         return false;
109     }
110     bytes_ = bytes;
111     len_ = len;
112     if (!(base_edid_ = GetBlock<BaseEdid>(0)) || !base_edid_->validate()) {
113         *err_msg = "Failed to validate base edid";
114         return false;
115     }
116     if (((base_edid_->num_extensions + 1) * kBlockSize) != len) {
117         *err_msg = "Bad extension count";
118         return false;
119     }
120     if (!base_edid_->digital()) {
121         *err_msg = "Analog displays not supported";
122         return false;
123     }
124 
125     for (uint8_t i = 1; i < len / kBlockSize; i++) {
126         if (bytes_[i * kBlockSize] == CeaEdidTimingExtension::kTag) {
127             if (!GetBlock<CeaEdidTimingExtension>(i)->validate()) {
128                 *err_msg = "Failed to validate extensions";
129                 return false;
130             }
131         }
132     }
133 
134     monitor_serial_[0] = monitor_name_[0] = '\0';
135     for (auto it = descriptor_iterator(this); it.is_valid(); ++it) {
136         char* dest;
137         if (it->timing.pixel_clock_10khz != 0) {
138             continue;
139         } else if (it->monitor.type == Descriptor::Monitor::kName) {
140             dest = monitor_name_;
141         } else if (it->monitor.type == Descriptor::Monitor::kSerial) {
142             dest = monitor_serial_;
143         } else {
144             continue;
145         }
146 
147         uint32_t len;
148         for (len = 0;
149                 len < sizeof(Descriptor::Monitor::data) && it->monitor.data[len] != 0x0A;
150                 ++len) {
151             // Empty body
152         }
153 
154         snprintf(dest, len + 1, "%s", it->monitor.data);
155     }
156 
157     // If we didn't find a valid serial descriptor, use the base serial number
158     if (monitor_serial_[0] == '\0') {
159         sprintf(monitor_serial_, "%d", base_edid_->serial_number);
160     }
161 
162     uint8_t c1 = static_cast<uint8_t>(((base_edid_->manufacturer_id1 & 0x7c) >> 2) + 'A' - 1);
163     uint8_t c2 = static_cast<uint8_t>((((base_edid_->manufacturer_id1 & 0x03) << 3)
164             | (base_edid_->manufacturer_id2 & 0xe0) >> 5) + 'A' - 1);
165     uint8_t c3  = static_cast<uint8_t>(((base_edid_->manufacturer_id2 & 0x1f)) + 'A' - 1);
166 
167     manufacturer_id_[0] = c1;
168     manufacturer_id_[1] = c2;
169     manufacturer_id_[2] = c3;
170     manufacturer_id_[3] = '\0';
171     manufacturer_name_ = lookup_eisa_vid(EISA_ID(c1, c2, c3));
172 
173     return true;
174 }
175 
GetBlock(uint8_t block_num) const176 template<typename T> const T* Edid::GetBlock(uint8_t block_num) const {
177     const uint8_t* bytes = bytes_ + block_num * kBlockSize;
178     return bytes[0] == T::kTag ? reinterpret_cast<const T*>(bytes) : nullptr;
179 }
180 
is_hdmi() const181 bool Edid::is_hdmi() const {
182     data_block_iterator dbs(this);
183     if (!dbs.is_valid() || dbs.cea_revision() < 0x03) {
184         return false;
185     }
186 
187     do {
188         if (dbs->type() == VendorSpecificBlock::kType) {
189             // HDMI's 24-bit IEEE registration is 0x000c03 - vendor_number is little endian
190             if (dbs->payload.vendor.vendor_number[0] == 0x03
191                     && dbs->payload.vendor.vendor_number[1] == 0x0c
192                     && dbs->payload.vendor.vendor_number[2] == 0x00) {
193                 return true;
194             }
195         }
196     } while ((++dbs).is_valid());
197     return false;
198 }
199 
convert_dtd_to_timing(const DetailedTimingDescriptor & dtd,timing_params * params)200 void convert_dtd_to_timing(const DetailedTimingDescriptor& dtd, timing_params* params) {
201     params->pixel_freq_10khz = dtd.pixel_clock_10khz;
202     params->horizontal_addressable = dtd.horizontal_addressable();
203     params->horizontal_front_porch = dtd.horizontal_front_porch();
204     params->horizontal_sync_pulse = dtd.horizontal_sync_pulse_width();
205     params->horizontal_blanking = dtd.horizontal_blanking();
206 
207     params->vertical_addressable = dtd.vertical_addressable();
208     params->vertical_front_porch = dtd.vertical_front_porch();
209     params->vertical_sync_pulse = dtd.vertical_sync_pulse_width();
210     params->vertical_blanking = dtd.vertical_blanking();
211 
212     if (dtd.type() != TYPE_DIGITAL_SEPARATE) {
213         printf("edid: Ignoring bad timing type %d\n", dtd.type());
214     }
215     params->flags = (dtd.vsync_polarity() ? timing_params::kPositiveVsync : 0)
216             | (dtd.hsync_polarity() ? timing_params::kPositiveHsync : 0)
217             | (dtd.interlaced() ? timing_params::kInterlaced : 0);
218 
219     double total_pxls =
220             (params->horizontal_addressable + params->horizontal_blanking) *
221             (params->vertical_addressable + params->vertical_blanking);
222     double pixel_clock_hz = params->pixel_freq_10khz * 1000 * 10;
223     params->vertical_refresh_e2 =
224             static_cast<uint32_t>(round(100 * pixel_clock_hz / total_pxls));
225 }
226 
convert_std_to_timing(const BaseEdid & edid,const StandardTimingDescriptor & std,timing_params * params)227 void convert_std_to_timing(const BaseEdid& edid,
228                            const StandardTimingDescriptor& std, timing_params* params) {
229     // Pick the largest resolution advertised by the display and then use the
230     // generalized timing formula to compute the timing parameters.
231     // TODO(ZX-1413): Handle secondary GTF and CVT
232     // TODO(stevensd): Support interlaced modes and margins
233     uint32_t width = std.horizontal_resolution();
234     uint32_t height = std.vertical_resolution(edid.edid_version, edid.edid_revision);
235     uint32_t v_rate = std.vertical_freq() + 60;
236 
237     if (!width || !height || !v_rate) {
238         return;
239     }
240 
241     const timing_params_t* dmt_timing = internal::dmt_timings;
242     for (unsigned i = 0; i < internal::dmt_timings_count; i++, dmt_timing++) {
243         if (dmt_timing->horizontal_addressable == width
244                 && dmt_timing->vertical_addressable == height
245                 && ((dmt_timing->vertical_refresh_e2 + 50) / 100) == v_rate) {
246             *params = *dmt_timing;
247             return;
248         }
249     }
250 
251     // Default values for GFT variables
252     static constexpr uint32_t kCellGran = 8;
253     static constexpr uint32_t kMinPorch = 1;
254     static constexpr uint32_t kVsyncRequired = 3;
255     static constexpr uint32_t kHsyncPercent = 8;
256     static constexpr uint32_t kMinVsyncPlusBpUs = 550;
257     static constexpr uint32_t kM = 600;
258     static constexpr uint32_t kC = 40;
259     static constexpr uint32_t kK = 128;
260     static constexpr uint32_t kJ = 20;
261     static constexpr uint32_t kCPrime = ((kC - kJ) * kK / 256) + kJ;
262     static constexpr uint32_t kMPrime = (kK * kM) / 256;
263 
264     uint32_t h_pixels_rnd = round_div(width, kCellGran) * kCellGran;
265     double h_period_est =
266             (1000000.0 - kMinVsyncPlusBpUs * v_rate) / (v_rate * (height + kMinPorch));
267     uint32_t vsync_bp = round_div(kMinVsyncPlusBpUs, h_period_est);
268     uint32_t v_total_lines = height + vsync_bp + kMinPorch;
269     double v_field_rate_est = 1000000.0 / (h_period_est * v_total_lines);
270     double h_period = (1.0 * h_period_est * v_field_rate_est) / v_rate;
271     double v_field_rate = 1000000.0 / h_period / v_total_lines;
272     double ideal_duty_cycle = kCPrime - (kMPrime * h_period_est / 1000);
273     uint32_t h_blank_pixels = 2 * kCellGran * round_div(
274             h_pixels_rnd * ideal_duty_cycle, (100 - ideal_duty_cycle) * (2 * kCellGran));
275     uint32_t total_pixels = h_pixels_rnd + h_blank_pixels;
276     double pixel_freq = total_pixels / h_period;
277 
278     params->pixel_freq_10khz = (uint32_t) (pixel_freq * 100 + 50);
279     params->horizontal_addressable = h_pixels_rnd;
280     params->horizontal_sync_pulse =
281             round_div(kHsyncPercent * total_pixels, 100 * kCellGran) * kCellGran;
282     params->horizontal_front_porch = h_blank_pixels / 2 - params->horizontal_sync_pulse;
283     params->horizontal_blanking = h_blank_pixels;
284     params->vertical_addressable = height;
285     params->vertical_front_porch = kMinPorch;
286     params->vertical_sync_pulse = kVsyncRequired;
287     params->vertical_blanking = vsync_bp + kMinPorch;
288 
289     // TODO(ZX-1413): Set these depending on if we use default/secondary GTF
290     params->flags = timing_params::kPositiveVsync;
291 
292     params->vertical_refresh_e2 = static_cast<uint32_t>(v_field_rate * 100 + .5);
293 }
294 
operator ++()295 timing_iterator& timing_iterator::operator++() {
296     while (state_ != kDone) {
297         Advance();
298         // If either of these are 0, then the timing value is definitely wrong
299         if (params_.vertical_addressable != 0 && params_.horizontal_addressable != 0) {
300             break;
301         }
302     }
303     return *this;
304 }
305 
Advance()306 void timing_iterator::Advance() {
307     if (state_ == kDtds) {
308         while (descriptors_.is_valid()) {
309             if (descriptors_->timing.pixel_clock_10khz != 0) {
310                 convert_dtd_to_timing(descriptors_->timing, &params_);
311                 ++descriptors_;
312                 return;
313             }
314             ++descriptors_;
315         }
316         state_ = kSvds;
317         state_index_ = UINT16_MAX;
318     }
319 
320     if (state_ == kSvds) {
321         while (dbs_.is_valid()) {
322             if (dbs_->type() == ShortVideoDescriptor::kType) {
323                 state_index_++;
324                 uint32_t modes_to_skip = state_index_;
325                 for (unsigned i = 0; i < dbs_->length(); i++) {
326                     uint32_t idx = dbs_->payload.video[i].standard_mode_idx() - 1;
327                     if (idx >= internal::cea_timings_count) {
328                         continue;
329                     }
330                     if (modes_to_skip == 0) {
331                         params_ = internal::cea_timings[idx];
332                         return;
333                     }
334 
335                     // For timings with refresh rates that are multiples of 6, there are
336                     // corresponding timings adjusted by a factor of 1000/1001.
337                     uint32_t rounded_refresh =
338                             (internal::cea_timings[idx].vertical_refresh_e2 + 99) / 100;
339                     if (rounded_refresh % 6 == 0) {
340                         if (modes_to_skip == 1) {
341                             params_ = internal::cea_timings[idx];
342                             double clock = params_.pixel_freq_10khz;
343                             double refresh = params_.vertical_refresh_e2;
344                             // 240/480 height entries are already multipled by 1000/1001
345                             double mult = params_.vertical_addressable == 240
346                                     || params_.vertical_addressable == 480
347                                     ? 1.001 : (1000. / 1001.);
348                             params_.pixel_freq_10khz = static_cast<uint32_t>(round(clock * mult));
349                             params_.vertical_refresh_e2 =
350                                     static_cast<uint32_t>(round(refresh * mult));
351                             return;
352                         }
353                         modes_to_skip -= 2;
354                     } else {
355                         modes_to_skip--;
356                     }
357                 }
358             }
359 
360             ++dbs_;
361             // Reset the index for either the next SVD block or the STDs.
362             state_index_ = UINT16_MAX;
363         }
364 
365         state_ = kStds;
366     }
367 
368     if (state_ == kStds) {
369         while (++state_index_ < fbl::count_of(edid_->base_edid_->standard_timings)) {
370             const StandardTimingDescriptor* desc =
371                     edid_->base_edid_->standard_timings + state_index_;
372             if (desc->byte1 == 0x01 && desc->byte2 == 0x01) {
373                 continue;
374             }
375             convert_std_to_timing(*edid_->base_edid_, *desc, &params_);
376             return;
377         }
378 
379         state_ = kDone;
380     }
381 }
382 
operator ++()383 audio_data_block_iterator& audio_data_block_iterator::operator++() {
384     while (dbs_.is_valid()) {
385         uint32_t num_sads = static_cast<uint32_t>(dbs_->length() / sizeof(ShortAudioDescriptor));
386         if (dbs_->type() != ShortAudioDescriptor::kType || ++sad_idx_ > num_sads) {
387             ++dbs_;
388             sad_idx_ = UINT8_MAX;
389             continue;
390         }
391         descriptor_ = dbs_->payload.audio[sad_idx_];
392         return *this;
393     }
394 
395     edid_ = nullptr;
396     return *this;
397 }
398 
operator ++()399 Edid::descriptor_iterator& Edid::descriptor_iterator::operator++() {
400     if (!edid_) {
401         return *this;
402     }
403 
404     if (block_idx_ == 0) {
405         descriptor_idx_++;
406 
407         if (descriptor_idx_ < fbl::count_of(edid_->base_edid_->detailed_descriptors)) {
408             descriptor_ = edid_->base_edid_->detailed_descriptors + descriptor_idx_;
409             if (descriptor_->timing.pixel_clock_10khz != 0 || descriptor_->monitor.type != 0x10) {
410                 return *this;
411             }
412         }
413 
414         block_idx_++;
415         descriptor_idx_ = UINT32_MAX;
416     }
417 
418     while (block_idx_ < (edid_->len_ / kBlockSize)) {
419         auto cea_extn_block = edid_->GetBlock<CeaEdidTimingExtension>(block_idx_);
420         size_t offset = sizeof(CeaEdidTimingExtension::payload);
421         if (cea_extn_block &&
422                 cea_extn_block->dtd_start_idx > offsetof(CeaEdidTimingExtension, payload)) {
423             offset = cea_extn_block->dtd_start_idx - offsetof(CeaEdidTimingExtension, payload);
424         }
425 
426         descriptor_idx_++;
427         offset += sizeof(Descriptor) * descriptor_idx_;
428 
429         // Return if the descriptor is within bounds and either a timing descriptor or not
430         // a dummy monitor descriptor, otherwise advance to the next block
431         if (offset + sizeof(DetailedTimingDescriptor) <= sizeof(CeaEdidTimingExtension::payload)) {
432             descriptor_ = reinterpret_cast<const Descriptor*>(cea_extn_block->payload + offset);
433             if (descriptor_->timing.pixel_clock_10khz != 0
434                     || descriptor_->monitor.type != Descriptor::Monitor::kDummyType) {
435                 return *this;
436             }
437         }
438 
439         block_idx_++;
440         descriptor_idx_ = UINT32_MAX;
441     }
442 
443     edid_ = nullptr;
444     return *this;
445 }
446 
data_block_iterator(const Edid * edid)447 Edid::data_block_iterator::data_block_iterator(const Edid* edid) : edid_(edid) {
448     ++(*this);
449     if (is_valid()) {
450         cea_revision_ = edid_->GetBlock<CeaEdidTimingExtension>(block_idx_)->revision_number;
451     }
452 }
453 
operator ++()454 Edid::data_block_iterator& Edid::data_block_iterator::operator++() {
455     if (!edid_) {
456         return *this;
457     }
458 
459     while (block_idx_ < (edid_->len_ / kBlockSize)) {
460         auto cea_extn_block = edid_->GetBlock<CeaEdidTimingExtension>(block_idx_);
461         size_t dbc_end = 0;
462         if (cea_extn_block &&
463                 cea_extn_block->dtd_start_idx > offsetof(CeaEdidTimingExtension, payload)) {
464             dbc_end = cea_extn_block->dtd_start_idx - offsetof(CeaEdidTimingExtension, payload);
465         }
466 
467         db_idx_++;
468         uint32_t db_to_skip = db_idx_;
469 
470         uint32_t offset = 0;
471         while (offset < dbc_end) {
472             auto* dblk = reinterpret_cast<const DataBlock*>(cea_extn_block->payload + offset);
473             if (db_to_skip == 0) {
474                 db_ = dblk;
475                 return *this;
476             }
477             db_to_skip--;
478             offset += (dblk->length() + 1); // length doesn't include the data block header byte
479         }
480 
481         block_idx_++;
482         db_idx_ = UINT32_MAX;
483     }
484 
485     edid_ = nullptr;
486     return *this;
487 }
488 
Print(void (* print_fn)(const char * str)) const489 void Edid::Print(void (*print_fn)(const char* str)) const {
490     char str_buf[128];
491     print_fn("Raw edid:\n");
492     for (auto i = 0; i < edid_length(); i++) {
493         constexpr int kBytesPerLine = 16;
494         char *b = str_buf;
495         if (i % kBytesPerLine == 0) {
496             b += sprintf(b, "%04x: ", i);
497         }
498         sprintf(b, "%02x%s", edid_bytes()[i],
499                 i % kBytesPerLine == kBytesPerLine - 1 ? "\n" : " ");
500         print_fn(str_buf);
501     }
502 }
503 
supports_basic_audio() const504 bool Edid::supports_basic_audio() const {
505     uint8_t block_idx = 1; // Skip block 1, since it can't be a CEA block
506     while (block_idx < (len_ / kBlockSize)) {
507         auto cea_extn_block = GetBlock<CeaEdidTimingExtension>(block_idx);
508         if (cea_extn_block && cea_extn_block->revision_number >= 2) {
509             return cea_extn_block->basic_audio();
510         }
511         block_idx++;
512     }
513     return false;
514 }
515 
516 } // namespace edid
517