blob: d6e37a1201cf28f08261139f14b82f40003e9c64 [file] [log] [blame]
Sachin Bhayareeeb88892018-01-02 16:36:01 +05301/* Copyright (c) 2010-2018, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/io.h>
14#include <linux/types.h>
15#include <linux/stat.h>
16#include <linux/slab.h>
17#include <linux/device.h>
18#include "mdss_fb.h"
19#include "mdss_hdmi_edid.h"
20
21#define DBC_START_OFFSET 4
22#define EDID_DTD_LEN 18
23/*
24 * As per CEA-861-E specification 7.5.2, there can be
25 * upto 31 bytes following any tag (data block type).
26 */
27#define MAX_DATA_BLOCK_SIZE 31
28
29#define HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd) \
30 (!((vsd)[8] & BIT(7)) ? 9 : (!((vsd)[8] & BIT(6)) ? 11 : 13))
31
32/*
33 * As per the CEA-861E spec, there can be a total of 10 short audio
34 * descriptors with each SAD being 3 bytes long.
35 * Thus, the maximum length of the audio data block would be 30 bytes
36 */
37#define MAX_NUMBER_ADB 5
38#define MAX_AUDIO_DATA_BLOCK_SIZE 30
39#define MAX_SPKR_ALLOC_DATA_BLOCK_SIZE 3
40
41/*
42 * As per the HDMI 2.0 spec, the size of the HF-VSDB cannot exceed 31 bytes and
43 * the minimum size is 7 bytes.
44 */
45#define MAX_HF_VSDB_SIZE 31
46#define MIN_HF_VSDB_SIZE 7
47
48/* IEEE OUI for HDMI Forum. */
49#define HDMI_FORUM_IEEE_OUI 0xD85DC4
50
51/* Support for first 5 EDID blocks */
52#define MAX_EDID_SIZE (EDID_BLOCK_SIZE * MAX_EDID_BLOCKS)
53
54#define BUFF_SIZE_3D 128
55
56#define DTD_MAX 0x04
57#define DTD_OFFSET 0x36
58#define DTD_SIZE 0x12
59#define REVISION_OFFSET 0x13
60#define EDID_REVISION_FOUR 0x04
61
62#define EDID_VENDOR_ID_SIZE 4
63#define EDID_IEEE_REG_ID 0x0c03
64
65enum edid_sink_mode {
66 SINK_MODE_DVI,
67 SINK_MODE_HDMI
68};
69
70enum data_block_types {
71 RESERVED,
72 AUDIO_DATA_BLOCK,
73 VIDEO_DATA_BLOCK,
74 VENDOR_SPECIFIC_DATA_BLOCK,
75 SPEAKER_ALLOCATION_DATA_BLOCK,
76 VESA_DTC_DATA_BLOCK,
77 RESERVED2,
78 USE_EXTENDED_TAG
79};
80
81enum extended_data_block_types {
82 VIDEO_CAPABILITY_DATA_BLOCK = 0x0,
83 VENDOR_SPECIFIC_VIDEO_DATA_BLOCK = 0x01,
84 HDMI_VIDEO_DATA_BLOCK = 0x04,
85 Y420_VIDEO_DATA_BLOCK = 0x0E,
86 VIDEO_FORMAT_PREFERENCE_DATA_BLOCK = 0x0D,
87 Y420_CAPABILITY_MAP_DATA_BLOCK = 0x0F,
88 VENDOR_SPECIFIC_AUDIO_DATA_BLOCK = 0x11,
89 INFOFRAME_DATA_BLOCK = 0x20,
90};
91
92struct disp_mode_info {
93 u32 video_format;
94 u32 video_3d_format; /* Flags like SIDE_BY_SIDE_HALF*/
95 bool rgb_support;
96 bool y420_support;
97};
98
99struct hdmi_edid_sink_data {
100 struct disp_mode_info disp_mode_list[HDMI_VFRMT_MAX];
101 u32 disp_multi_3d_mode_list[16];
102 u32 disp_multi_3d_mode_list_cnt;
103 u32 num_of_elements;
104 u32 preferred_video_format;
105};
106
107struct hdmi_edid_sink_caps {
108 u32 max_pclk_in_hz;
109 bool scdc_present;
110 bool scramble_support; /* scramble support for less than 340Mcsc */
111 bool read_req_support;
112 bool osd_disparity;
113 bool dual_view_support;
114 bool ind_view_support;
115};
116
117struct hdmi_edid_override_data {
118 int scramble;
119 int sink_mode;
120 int format;
121 int vic;
122};
123
124struct hdmi_edid_ctrl {
125 u8 pt_scan_info;
126 u8 it_scan_info;
127 u8 ce_scan_info;
128 u8 cea_blks;
129 u16 physical_address;
130 u32 video_resolution; /* selected by user */
131 u32 sink_mode; /* HDMI or DVI */
132 u32 default_vic;
133 u16 audio_latency;
134 u16 video_latency;
135 u32 present_3d;
136 u32 page_id;
137 u8 audio_data_block[MAX_NUMBER_ADB * MAX_AUDIO_DATA_BLOCK_SIZE];
138 int adb_size;
139 u8 spkr_alloc_data_block[MAX_SPKR_ALLOC_DATA_BLOCK_SIZE];
140 int sadb_size;
141 u8 edid_buf[MAX_EDID_SIZE];
142 char vendor_id[EDID_VENDOR_ID_SIZE];
143 bool keep_resv_timings;
144 bool edid_override;
145
146 struct hdmi_edid_sink_data sink_data;
147 struct hdmi_edid_init_data init_data;
148 struct hdmi_edid_sink_caps sink_caps;
149 struct hdmi_edid_override_data override_data;
150};
151
152static bool hdmi_edid_is_mode_supported(struct hdmi_edid_ctrl *edid_ctrl,
153 struct msm_hdmi_mode_timing_info *timing)
154{
155 if (!timing->supported ||
156 timing->pixel_freq > edid_ctrl->init_data.max_pclk_khz)
157 return false;
158
159 return true;
160}
161
162static int hdmi_edid_reset_parser(struct hdmi_edid_ctrl *edid_ctrl)
163{
164 if (!edid_ctrl) {
165 DEV_ERR("%s: invalid input\n", __func__);
166 return -EINVAL;
167 }
168
169 /* reset res info read page */
170 edid_ctrl->page_id = MSM_HDMI_INIT_RES_PAGE;
171
172 /* reset sink mode to DVI as default */
173 edid_ctrl->sink_mode = SINK_MODE_DVI;
174
175 edid_ctrl->sink_data.num_of_elements = 0;
176
177 /* reset scan info data */
178 edid_ctrl->pt_scan_info = 0;
179 edid_ctrl->it_scan_info = 0;
180 edid_ctrl->ce_scan_info = 0;
181
182 /* reset 3d data */
183 edid_ctrl->present_3d = 0;
184
185 /* reset number of cea extension blocks to 0 */
186 edid_ctrl->cea_blks = 0;
187
188 /* reset resolution related sink data */
189 memset(&edid_ctrl->sink_data, 0, sizeof(edid_ctrl->sink_data));
190
191 /* reset audio related data */
192 memset(edid_ctrl->audio_data_block, 0,
193 sizeof(edid_ctrl->audio_data_block));
194 memset(edid_ctrl->spkr_alloc_data_block, 0,
195 sizeof(edid_ctrl->spkr_alloc_data_block));
196 edid_ctrl->adb_size = 0;
197 edid_ctrl->sadb_size = 0;
198
199 hdmi_edid_set_video_resolution(edid_ctrl, edid_ctrl->default_vic, true);
200
201 /* reset new resolution details */
202 if (!edid_ctrl->keep_resv_timings)
203 hdmi_reset_resv_timing_info();
204
205 return 0;
206}
207
208static struct hdmi_edid_ctrl *hdmi_edid_get_ctrl(struct device *dev)
209{
210 struct fb_info *fbi;
211 struct msm_fb_data_type *mfd;
212 struct mdss_panel_info *pinfo;
213
214 if (!dev) {
215 pr_err("invlid input\n");
216 goto error;
217 }
218
219 fbi = dev_get_drvdata(dev);
220
221 if (!fbi) {
222 pr_err("invlid fbi\n");
223 goto error;
224 }
225
226 mfd = (struct msm_fb_data_type *)fbi->par;
227 if (!mfd) {
228 pr_err("invlid mfd\n");
229 goto error;
230 }
231
232 pinfo = mfd->panel_info;
233 if (!pinfo) {
234 pr_err("invlid pinfo\n");
235 goto error;
236 }
237
238 return pinfo->edid_data;
239
240error:
241 return NULL;
242}
243
244static ssize_t hdmi_edid_sysfs_rda_audio_data_block(struct device *dev,
245 struct device_attribute *attr, char *buf)
246{
247 int adb_size, adb_count;
248 ssize_t ret;
249 char *data = buf;
250
251 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
252
253 if (!edid_ctrl) {
254 DEV_ERR("%s: invalid input\n", __func__);
255 return -EINVAL;
256 }
257
258 adb_count = 1;
259 adb_size = edid_ctrl->adb_size;
260 ret = sizeof(adb_count) + sizeof(adb_size) + adb_size;
261
262 if (ret > PAGE_SIZE) {
263 DEV_DBG("%s: Insufficient buffer size\n", __func__);
264 return 0;
265 }
266
267 /* Currently only extracting one audio data block */
268 memcpy(data, &adb_count, sizeof(adb_count));
269 data += sizeof(adb_count);
270 memcpy(data, &adb_size, sizeof(adb_size));
271 data += sizeof(adb_size);
272 memcpy(data, edid_ctrl->audio_data_block,
273 edid_ctrl->adb_size);
274
275 print_hex_dump(KERN_DEBUG, "AUDIO DATA BLOCK: ", DUMP_PREFIX_NONE,
276 32, 8, buf, ret, false);
277
278 return ret;
279}
280static DEVICE_ATTR(audio_data_block, 0444,
281 hdmi_edid_sysfs_rda_audio_data_block,
282 NULL);
283
284static ssize_t hdmi_edid_sysfs_rda_spkr_alloc_data_block(struct device *dev,
285 struct device_attribute *attr, char *buf)
286{
287 int sadb_size, sadb_count;
288 ssize_t ret;
289 char *data = buf;
290
291 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
292
293 if (!edid_ctrl) {
294 DEV_ERR("%s: invalid input\n", __func__);
295 return -EINVAL;
296 }
297
298 sadb_count = 1;
299 sadb_size = edid_ctrl->sadb_size;
300 ret = sizeof(sadb_count) + sizeof(sadb_size) + sadb_size;
301
302 if (ret > PAGE_SIZE) {
303 DEV_DBG("%s: Insufficient buffer size\n", __func__);
304 return 0;
305 }
306
307 /* Currently only extracting one speaker allocation data block */
308 memcpy(data, &sadb_count, sizeof(sadb_count));
309 data += sizeof(sadb_count);
310 memcpy(data, &sadb_size, sizeof(sadb_size));
311 data += sizeof(sadb_size);
312 memcpy(data, edid_ctrl->spkr_alloc_data_block,
313 edid_ctrl->sadb_size);
314
315 print_hex_dump(KERN_DEBUG, "SPKR ALLOC DATA BLOCK: ", DUMP_PREFIX_NONE,
316 32, 8, buf, ret, false);
317
318 return ret;
319}
320static DEVICE_ATTR(spkr_alloc_data_block, 0444,
321 hdmi_edid_sysfs_rda_spkr_alloc_data_block, NULL);
322
323static ssize_t hdmi_edid_sysfs_wta_modes(struct device *dev,
324 struct device_attribute *attr, const char *buf, size_t count)
325{
326 ssize_t ret = strnlen(buf, PAGE_SIZE);
327 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
328
329 if (!edid_ctrl) {
330 DEV_ERR("%s: invalid ctrl\n", __func__);
331 ret = -EINVAL;
332 goto error;
333 }
334
335 if (sscanf(buf, "%d %d %d %d",
336 &edid_ctrl->override_data.scramble,
337 &edid_ctrl->override_data.sink_mode,
338 &edid_ctrl->override_data.format,
339 &edid_ctrl->override_data.vic) != 4) {
340 DEV_ERR("could not read input\n");
341 ret = -EINVAL;
342 goto bail;
343 }
344
345 edid_ctrl->edid_override = true;
346 return ret;
347bail:
348 DEV_DBG("%s: reset edid override\n", __func__);
349 edid_ctrl->edid_override = false;
350error:
351 return ret;
352}
353
354static ssize_t hdmi_edid_sysfs_rda_modes(struct device *dev,
355 struct device_attribute *attr, char *buf)
356{
357 ssize_t ret = 0;
358 int i;
359 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
360 u32 num_of_elements = 0;
361 struct disp_mode_info *video_mode;
362
363 if (!edid_ctrl) {
364 DEV_ERR("%s: invalid input\n", __func__);
365 return -EINVAL;
366 }
367
368 num_of_elements = edid_ctrl->sink_data.num_of_elements;
369 video_mode = edid_ctrl->sink_data.disp_mode_list;
370
371 if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) {
372 num_of_elements = 1;
373 edid_ctrl->sink_data.disp_mode_list[0].video_format =
374 edid_ctrl->override_data.vic;
375 }
376
377 buf[0] = 0;
378 if (num_of_elements) {
379 for (i = 0; i < num_of_elements; i++) {
380 if (ret > 0)
381 ret += scnprintf(buf + ret, PAGE_SIZE - ret,
382 ",%d", video_mode[i].video_format);
383 else
384 ret += scnprintf(buf + ret, PAGE_SIZE - ret,
385 "%d", video_mode[i].video_format);
386 }
387 } else {
388 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%d",
389 edid_ctrl->video_resolution);
390 }
391
392 DEV_DBG("%s: '%s'\n", __func__, buf);
393 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
394
395 return ret;
396} /* hdmi_edid_sysfs_rda_modes */
397static DEVICE_ATTR(edid_modes, 0644, hdmi_edid_sysfs_rda_modes,
398 hdmi_edid_sysfs_wta_modes);
399
400static ssize_t hdmi_edid_sysfs_rda_res_info_data(struct device *dev,
401 struct device_attribute *attr, char *buf)
402{
403 ssize_t ret;
404 u32 i, no_of_elem, offset = 0;
405 struct msm_hdmi_mode_timing_info info = {0};
406 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
407 struct disp_mode_info *minfo = NULL;
408
409 if (!edid_ctrl) {
410 DEV_ERR("%s: invalid input\n", __func__);
411 return -EINVAL;
412 }
413
414 no_of_elem = edid_ctrl->sink_data.num_of_elements;
415 minfo = edid_ctrl->sink_data.disp_mode_list;
416
417 if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) {
418 no_of_elem = 1;
419 minfo[0].video_format = edid_ctrl->override_data.vic;
420 }
421
422 for (i = 0; i < no_of_elem; i++) {
423 ret = hdmi_get_supported_mode(&info,
424 &edid_ctrl->init_data.ds_data,
425 minfo->video_format);
426
427 if (edid_ctrl->edid_override &&
428 (edid_ctrl->override_data.format > 0))
429 info.pixel_formats = edid_ctrl->override_data.format;
430 else
431 info.pixel_formats =
432 (minfo->rgb_support ?
433 MSM_HDMI_RGB_888_24BPP_FORMAT : 0) |
434 (minfo->y420_support ?
435 MSM_HDMI_YUV_420_12BPP_FORMAT : 0);
436
437 minfo++;
438 if (ret || !info.supported)
439 continue;
440
441 offset += scnprintf(buf + offset, PAGE_SIZE - offset,
442 "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
443 info.video_format, info.active_h,
444 info.front_porch_h, info.pulse_width_h,
445 info.back_porch_h, info.active_low_h,
446 info.active_v, info.front_porch_v,
447 info.pulse_width_v, info.back_porch_v,
448 info.active_low_v, info.pixel_freq,
449 info.refresh_rate, info.interlaced,
450 info.supported, info.ar,
451 info.pixel_formats);
452 }
453
454 return offset;
455}
456static DEVICE_ATTR(res_info_data, 0444, hdmi_edid_sysfs_rda_res_info_data,
457 NULL);
458
459static ssize_t hdmi_edid_sysfs_wta_res_info(struct device *dev,
460 struct device_attribute *attr, const char *buf, size_t count)
461{
462 int rc, page_id;
463 u32 i = 0, j, page;
464 ssize_t ret = strnlen(buf, PAGE_SIZE);
465 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
466 struct msm_hdmi_mode_timing_info info = {0};
467
468 if (!edid_ctrl) {
469 DEV_ERR("%s: invalid input\n", __func__);
470 return -EINVAL;
471 }
472
473 rc = kstrtoint(buf, 10, &page_id);
474 if (rc) {
475 DEV_ERR("%s: kstrtoint failed. rc=%d\n", __func__, rc);
476 return rc;
477 }
478
479 if (page_id > MSM_HDMI_INIT_RES_PAGE) {
480 page = MSM_HDMI_INIT_RES_PAGE;
481 while (page < page_id) {
482 j = 1;
483 while (sizeof(info) * j < PAGE_SIZE) {
484 i++;
485 j++;
486 }
487 page++;
488 }
489 }
490
491 if (i < HDMI_VFRMT_MAX)
492 edid_ctrl->page_id = page_id;
493 else
494 DEV_ERR("%s: invalid page id\n", __func__);
495
496 DEV_DBG("%s: %d\n", __func__, edid_ctrl->page_id);
497 return ret;
498}
499
500static ssize_t hdmi_edid_sysfs_rda_res_info(struct device *dev,
501 struct device_attribute *attr, char *buf)
502{
503 ssize_t ret;
504 u32 no_of_elem;
505 u32 i = 0, j, page;
506 char *buf_dbg = buf;
507 struct msm_hdmi_mode_timing_info info = {0};
508 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
509 u32 size_to_write = sizeof(info);
510 struct disp_mode_info *minfo = NULL;
511
512 if (!edid_ctrl) {
513 DEV_ERR("%s: invalid input\n", __func__);
514 return -EINVAL;
515 }
516
517 minfo = edid_ctrl->sink_data.disp_mode_list;
518 no_of_elem = edid_ctrl->sink_data.num_of_elements;
519
520 if (edid_ctrl->page_id > MSM_HDMI_INIT_RES_PAGE) {
521 page = MSM_HDMI_INIT_RES_PAGE;
522 while (page < edid_ctrl->page_id) {
523 j = 1;
524 while (sizeof(info) * j < PAGE_SIZE) {
525 i++;
526 j++;
527 minfo++;
528 }
529 page++;
530 }
531 }
532
533 if (edid_ctrl->edid_override && (edid_ctrl->override_data.vic > 0)) {
534 no_of_elem = 1;
535 minfo[0].video_format = edid_ctrl->override_data.vic;
536 }
537
538 for (; i < no_of_elem && size_to_write < PAGE_SIZE; i++) {
539 ret = hdmi_get_supported_mode(&info,
540 &edid_ctrl->init_data.ds_data,
541 minfo->video_format);
542
543 if (edid_ctrl->edid_override &&
544 (edid_ctrl->override_data.format > 0))
545 info.pixel_formats = edid_ctrl->override_data.format;
546 else
547 info.pixel_formats =
548 (minfo->rgb_support ?
549 MSM_HDMI_RGB_888_24BPP_FORMAT : 0) |
550 (minfo->y420_support ?
551 MSM_HDMI_YUV_420_12BPP_FORMAT : 0);
552
553 minfo++;
554 if (ret || !info.supported)
555 continue;
556
557 memcpy(buf, &info, sizeof(info));
558
559 buf += sizeof(info);
560 size_to_write += sizeof(info);
561 }
562
563 for (i = sizeof(info); i < size_to_write; i += sizeof(info)) {
564 struct msm_hdmi_mode_timing_info info_dbg = {0};
565
566 memcpy(&info_dbg, buf_dbg, sizeof(info_dbg));
567
568 DEV_DBG("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",
569 info_dbg.video_format, info_dbg.active_h,
570 info_dbg.front_porch_h, info_dbg.pulse_width_h,
571 info_dbg.back_porch_h, info_dbg.active_low_h,
572 info_dbg.active_v, info_dbg.front_porch_v,
573 info_dbg.pulse_width_v, info_dbg.back_porch_v,
574 info_dbg.active_low_v, info_dbg.pixel_freq,
575 info_dbg.refresh_rate, info_dbg.interlaced,
576 info_dbg.supported, info_dbg.ar,
577 info_dbg.pixel_formats);
578
579 buf_dbg += sizeof(info_dbg);
580 }
581
582 return size_to_write - sizeof(info);
583}
584static DEVICE_ATTR(res_info, 0644, hdmi_edid_sysfs_rda_res_info,
585 hdmi_edid_sysfs_wta_res_info);
586
587static ssize_t hdmi_edid_sysfs_rda_audio_latency(struct device *dev,
588 struct device_attribute *attr, char *buf)
589{
590 ssize_t ret;
591 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
592
593 if (!edid_ctrl) {
594 DEV_ERR("%s: invalid input\n", __func__);
595 return -EINVAL;
596 }
597 ret = scnprintf(buf, PAGE_SIZE, "%d\n", edid_ctrl->audio_latency);
598
599 DEV_DBG("%s: '%s'\n", __func__, buf);
600
601 return ret;
602} /* hdmi_edid_sysfs_rda_audio_latency */
603static DEVICE_ATTR(edid_audio_latency, 0444,
604 hdmi_edid_sysfs_rda_audio_latency, NULL);
605
606static ssize_t hdmi_edid_sysfs_rda_video_latency(struct device *dev,
607 struct device_attribute *attr, char *buf)
608{
609 ssize_t ret;
610 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
611
612 if (!edid_ctrl) {
613 DEV_ERR("%s: invalid input\n", __func__);
614 return -EINVAL;
615 }
616 ret = scnprintf(buf, PAGE_SIZE, "%d\n", edid_ctrl->video_latency);
617
618 DEV_DBG("%s: '%s'\n", __func__, buf);
619
620 return ret;
621} /* hdmi_edid_sysfs_rda_video_latency */
622static DEVICE_ATTR(edid_video_latency, 0444,
623 hdmi_edid_sysfs_rda_video_latency, NULL);
624
625static ssize_t hdmi_edid_sysfs_rda_physical_address(struct device *dev,
626 struct device_attribute *attr, char *buf)
627{
628 ssize_t ret;
629 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
630
631 if (!edid_ctrl) {
632 DEV_ERR("%s: invalid input\n", __func__);
633 return -EINVAL;
634 }
635
636 ret = scnprintf(buf, PAGE_SIZE, "%d\n", edid_ctrl->physical_address);
637 DEV_DBG("%s: '%d'\n", __func__, edid_ctrl->physical_address);
638
639 return ret;
640} /* hdmi_edid_sysfs_rda_physical_address */
641static DEVICE_ATTR(pa, 0400, hdmi_edid_sysfs_rda_physical_address, NULL);
642
643static ssize_t hdmi_edid_sysfs_rda_scan_info(struct device *dev,
644 struct device_attribute *attr, char *buf)
645{
646 ssize_t ret;
647 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
648
649 if (!edid_ctrl) {
650 DEV_ERR("%s: invalid input\n", __func__);
651 return -EINVAL;
652 }
653
654 ret = scnprintf(buf, PAGE_SIZE, "%d, %d, %d\n", edid_ctrl->pt_scan_info,
655 edid_ctrl->it_scan_info, edid_ctrl->ce_scan_info);
656 DEV_DBG("%s: '%s'\n", __func__, buf);
657
658 return ret;
659} /* hdmi_edid_sysfs_rda_scan_info */
660static DEVICE_ATTR(scan_info, 0444, hdmi_edid_sysfs_rda_scan_info, NULL);
661
662static ssize_t hdmi_edid_sysfs_rda_3d_modes(struct device *dev,
663 struct device_attribute *attr, char *buf)
664{
665 ssize_t ret = 0;
666 int i;
667 char buff_3d[BUFF_SIZE_3D];
668
669 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
670
671 if (!edid_ctrl) {
672 DEV_ERR("%s: invalid input\n", __func__);
673 return -EINVAL;
674 }
675
676 buf[0] = 0;
677 if (edid_ctrl->sink_data.num_of_elements) {
678 struct disp_mode_info *video_mode =
679 edid_ctrl->sink_data.disp_mode_list;
680
681 for (i = 0; i < edid_ctrl->sink_data.num_of_elements; i++) {
682 if (!video_mode[i].video_3d_format)
683 continue;
684 hdmi_get_video_3d_fmt_2string(
685 video_mode[i].video_3d_format,
686 buff_3d,
687 sizeof(buff_3d));
688 if (ret > 0)
689 ret += scnprintf(buf + ret, PAGE_SIZE - ret,
690 ",%d=%s", video_mode[i].video_format,
691 buff_3d);
692 else
693 ret += scnprintf(buf + ret, PAGE_SIZE - ret,
694 "%d=%s", video_mode[i].video_format,
695 buff_3d);
696 }
697 }
698
699 DEV_DBG("%s: '%s'\n", __func__, buf);
700 ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
701
702 return ret;
703} /* hdmi_edid_sysfs_rda_3d_modes */
704static DEVICE_ATTR(edid_3d_modes, 0444, hdmi_edid_sysfs_rda_3d_modes, NULL);
705
706static ssize_t hdmi_common_rda_edid_raw_data(struct device *dev,
707 struct device_attribute *attr, char *buf)
708{
709 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
710 u32 size;
711
712 if (!edid_ctrl) {
713 DEV_ERR("%s: invalid input\n", __func__);
714 return -EINVAL;
715 }
716
717 size = sizeof(edid_ctrl->edid_buf) < PAGE_SIZE ?
718 sizeof(edid_ctrl->edid_buf) : PAGE_SIZE;
719
720 /* buf can have max size of PAGE_SIZE */
721 memcpy(buf, edid_ctrl->edid_buf, size);
722
723 return size;
724} /* hdmi_common_rda_edid_raw_data */
725static DEVICE_ATTR(edid_raw_data, 0444, hdmi_common_rda_edid_raw_data, NULL);
726
727static ssize_t hdmi_edid_sysfs_wta_add_resolution(struct device *dev,
728 struct device_attribute *attr, const char *buf, size_t count)
729{
730 int rc;
731 ssize_t ret = strnlen(buf, PAGE_SIZE);
732 struct hdmi_edid_ctrl *edid_ctrl = hdmi_edid_get_ctrl(dev);
733 struct msm_hdmi_mode_timing_info timing;
734
735 if (!edid_ctrl) {
736 DEV_ERR("%s: invalid input\n", __func__);
737 return -EINVAL;
738 }
739
740 rc = sscanf(buf,
741 "%lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu",
742 (unsigned long *) &timing.active_h,
743 (unsigned long *) &timing.front_porch_h,
744 (unsigned long *) &timing.pulse_width_h,
745 (unsigned long *) &timing.back_porch_h,
746 (unsigned long *) &timing.active_low_h,
747 (unsigned long *) &timing.active_v,
748 (unsigned long *) &timing.front_porch_v,
749 (unsigned long *) &timing.pulse_width_v,
750 (unsigned long *) &timing.back_porch_v,
751 (unsigned long *) &timing.active_low_v,
752 (unsigned long *) &timing.pixel_freq,
753 (unsigned long *) &timing.refresh_rate,
754 (unsigned long *) &timing.interlaced,
755 (unsigned long *) &timing.supported,
756 (unsigned long *) &timing.ar);
757
758 if (rc != 15) {
759 DEV_ERR("%s: error reading buf\n", __func__);
760 goto err;
761 }
762
763 rc = hdmi_set_resv_timing_info(&timing);
764
765 if (!IS_ERR_VALUE(rc)) {
766 DEV_DBG("%s: added new res %d\n", __func__, rc);
767 } else {
768 DEV_ERR("%s: error adding new res %d\n", __func__, rc);
769 goto err;
770 }
771
772 edid_ctrl->keep_resv_timings = true;
773 return ret;
774
775err:
776 edid_ctrl->keep_resv_timings = false;
777 return -EFAULT;
778}
779static DEVICE_ATTR(add_res, 0200, NULL, hdmi_edid_sysfs_wta_add_resolution);
780
781static struct attribute *hdmi_edid_fs_attrs[] = {
782 &dev_attr_edid_modes.attr,
783 &dev_attr_pa.attr,
784 &dev_attr_scan_info.attr,
785 &dev_attr_edid_3d_modes.attr,
786 &dev_attr_edid_raw_data.attr,
787 &dev_attr_audio_data_block.attr,
788 &dev_attr_spkr_alloc_data_block.attr,
789 &dev_attr_edid_audio_latency.attr,
790 &dev_attr_edid_video_latency.attr,
791 &dev_attr_res_info.attr,
792 &dev_attr_res_info_data.attr,
793 &dev_attr_add_res.attr,
794 NULL,
795};
796
797static struct attribute_group hdmi_edid_fs_attrs_group = {
798 .attrs = hdmi_edid_fs_attrs,
799};
800
801static const u8 *hdmi_edid_find_block(const u8 *in_buf, u32 start_offset,
802 u8 type, u8 *len)
803{
804 /* the start of data block collection, start of Video Data Block */
805 u32 offset = start_offset;
806 u32 dbc_offset = in_buf[2];
807
808 if (dbc_offset >= EDID_BLOCK_SIZE - EDID_DTD_LEN)
809 return NULL;
810 *len = 0;
811
812 /*
813 * * edid buffer 1, byte 2 being 4 means no non-DTD/Data block
814 * collection present.
815 * * edid buffer 1, byte 2 being 0 menas no non-DTD/DATA block
816 * collection present and no DTD data present.
817 */
818 if ((dbc_offset == 0) || (dbc_offset == 4)) {
819 DEV_WARN("EDID: no DTD or non-DTD data present\n");
820 return NULL;
821 }
822
823 while (offset < dbc_offset) {
824 u8 block_len = in_buf[offset] & 0x1F;
825
826 if ((offset + block_len <= dbc_offset) &&
827 (in_buf[offset] >> 5) == type) {
828 *len = block_len;
829 DEV_DBG("%s: EDID: block=%d found @ 0x%x w/ len=%d\n",
830 __func__, type, offset, block_len);
831
832 return in_buf + offset;
833 }
834 offset += 1 + block_len;
835 }
836 DEV_WARN("%s: EDID: type=%d block not found in EDID block\n",
837 __func__, type);
838
839 return NULL;
840} /* hdmi_edid_find_block */
841
842static void hdmi_edid_set_y420_support(struct hdmi_edid_ctrl *edid_ctrl,
843 u32 video_format)
844{
845 u32 i = 0;
846
847 if (!edid_ctrl) {
848 DEV_ERR("%s: Invalid input\n", __func__);
849 return;
850 }
851
852 for (i = 0; i < edid_ctrl->sink_data.num_of_elements; ++i) {
853 if (video_format ==
854 edid_ctrl->sink_data.disp_mode_list[i].video_format) {
855 edid_ctrl->sink_data.disp_mode_list[i].y420_support =
856 true;
857 DEV_DBG("%s: Yuv420 supported for format %d\n",
858 __func__,
859 edid_ctrl->sink_data.disp_mode_list[i].video_format);
860 }
861 }
862}
863
864static void hdmi_edid_add_sink_y420_format(struct hdmi_edid_ctrl *edid_ctrl,
865 u32 video_format)
866{
867 struct msm_hdmi_mode_timing_info timing = {0};
868 u32 ret = hdmi_get_supported_mode(&timing,
869 &edid_ctrl->init_data.ds_data,
870 video_format);
871 u32 supported = hdmi_edid_is_mode_supported(edid_ctrl, &timing);
872 struct hdmi_edid_sink_data *sink = &edid_ctrl->sink_data;
873
874 if (video_format >= HDMI_VFRMT_MAX) {
875 DEV_ERR("%s: video format: %s is not supported\n", __func__,
876 msm_hdmi_mode_2string(video_format));
877 return;
878 }
879
880 if (!sink) {
881 DEV_ERR("%s: invalid input\n", __func__);
882 return;
883 }
884
885 DEV_DBG("%s: EDID: format: %d [%s], %s\n", __func__,
886 video_format, msm_hdmi_mode_2string(video_format),
887 supported ? "Supported" : "Not-Supported");
888
889 if (!ret && supported) {
890 sink->disp_mode_list[sink->num_of_elements].video_format
891 = video_format;
892 sink->disp_mode_list[sink->num_of_elements].y420_support
893 = true;
894 sink->num_of_elements++;
895 }
896}
897
898static void hdmi_edid_parse_Y420VDB(struct hdmi_edid_ctrl *edid_ctrl,
899 const u8 *in_buf)
900{
901 u8 len = 0;
902 u8 i = 0;
903 u32 video_format = 0;
904
905 if (!edid_ctrl) {
906 DEV_ERR("%s: invalid input\n", __func__);
907 return;
908 }
909
910 len = in_buf[0] & 0x1F;
911 /* Offset to byte 3 */
912 in_buf += 2;
913 for (i = 0; i < len - 1; i++) {
914 video_format = *(in_buf + i) & 0x7F;
915 hdmi_edid_add_sink_y420_format(edid_ctrl, video_format);
916 }
917}
918
919static void hdmi_edid_parse_Y420CMDB(struct hdmi_edid_ctrl *edid_ctrl,
920 const u8 *in_buf)
921{
922 u32 offset = 0;
923 u8 svd_len = 0;
924 u32 i = 0, j = 0;
925 u32 video_format = 0;
926 u32 len = 0;
927 const u8 *svd = NULL;
928
929 if (!edid_ctrl) {
930 DEV_ERR("%s: invalid input\n", __func__);
931 return;
932 }
933 /* Byte 3 to L+1 contain SVDs */
934 offset += 2;
935 len = in_buf[0] & 0x1F;
936
937 /*
938 * The Y420 Capability map data block should be parsed along with the
939 * video data block. Each bit in Y420CMDB maps to each SVD in data
940 * block
941 */
942 svd = hdmi_edid_find_block(edid_ctrl->edid_buf+0x80, DBC_START_OFFSET,
943 VIDEO_DATA_BLOCK, &svd_len);
944
945 ++svd;
946 for (i = 0; i < svd_len; i++, j++) {
947 video_format = *svd & 0x7F;
948 if (in_buf[offset] & (1 << j))
949 hdmi_edid_set_y420_support(edid_ctrl, video_format);
950
951 if (j & 0x80) {
952 j = j/8;
953 offset++;
954 if (offset >= len)
955 break;
956 }
957 }
958}
959
960static void hdmi_edid_parse_hvdb(struct hdmi_edid_ctrl *edid_ctrl,
961 const u8 *in_buf)
962{
963 u32 len = 0;
964 struct hdmi_edid_sink_caps *sink_caps = NULL;
965
966 if (!edid_ctrl) {
967 DEV_ERR("%s: invalid input\n", __func__);
968 return;
969 }
970
971 sink_caps = &edid_ctrl->sink_caps;
972 len = in_buf[0] & 0x1F;
973 if ((in_buf[1] != HDMI_VIDEO_DATA_BLOCK) ||
974 (len < 5)) {
975 DEV_ERR("%s: Not a HVDB tag code\n", __func__);
976 return;
977 }
978 DEV_ERR("FOUND HVDB flags = 0x%x\n", in_buf[4]);
979 sink_caps->max_pclk_in_hz = in_buf[3]*5000;
980 sink_caps->scdc_present = (in_buf[4] & 0x80) ? true : false;
981 sink_caps->read_req_support = (in_buf[4] & 0x40) ? true : false;
982 sink_caps->scramble_support = (in_buf[4] & 0x08) ? true : false;
983 sink_caps->ind_view_support = (in_buf[4] & 0x04) ? true : false;
984 sink_caps->dual_view_support = (in_buf[4] & 0x02) ? true : false;
985 sink_caps->osd_disparity = (in_buf[4] * 0x01) ? true : false;
986
987}
988
989static void hdmi_edid_extract_extended_data_blocks(
990 struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
991{
992 u8 len = 0;
993 u32 start_offset = 0;
994 u8 const *etag = NULL;
995
996 if (!edid_ctrl) {
997 DEV_ERR("%s: invalid input\n", __func__);
998 return;
999 }
1000
1001 do {
1002 if (!start_offset && !etag)
1003 start_offset = DBC_START_OFFSET;
1004 else
1005 start_offset = etag - in_buf + len + 1;
1006
1007 etag = hdmi_edid_find_block(in_buf, start_offset,
1008 USE_EXTENDED_TAG, &len);
1009
1010 if (!etag || !len) {
1011 DEV_DBG("%s: No more extended block found\n", __func__);
1012 break;
1013 }
1014
1015 /* The extended data block should at least be 2 bytes long */
1016 if (len < 2) {
1017 DEV_DBG("%s: invalid block size\n", __func__);
1018 continue;
1019 }
1020
1021 /*
1022 * The second byte of the extended data block has the
1023 * extended tag code
1024 */
1025 switch (etag[1]) {
1026 case VIDEO_CAPABILITY_DATA_BLOCK:
1027 /* Video Capability Data Block */
1028 DEV_DBG("%s: EDID: VCDB=%02X %02X\n", __func__,
1029 etag[1], etag[2]);
1030
1031 /*
1032 * Check if the sink specifies underscan
1033 * support for:
1034 * BIT 5: preferred video format
1035 * BIT 3: IT video format
1036 * BIT 1: CE video format
1037 */
1038 edid_ctrl->pt_scan_info =
1039 (etag[2] & (BIT(4) | BIT(5))) >> 4;
1040 edid_ctrl->it_scan_info =
1041 (etag[2] & (BIT(3) | BIT(2))) >> 2;
1042 edid_ctrl->ce_scan_info =
1043 etag[2] & (BIT(1) | BIT(0));
1044 DEV_DBG("%s: Scan Info (pt|it|ce): (%d|%d|%d)",
1045 __func__,
1046 edid_ctrl->pt_scan_info,
1047 edid_ctrl->it_scan_info,
1048 edid_ctrl->ce_scan_info);
1049 break;
1050 case HDMI_VIDEO_DATA_BLOCK:
1051 /* HDMI Video data block defined in HDMI 2.0 */
1052 DEV_DBG("%s: EDID: HVDB found\n", __func__);
1053 hdmi_edid_parse_hvdb(edid_ctrl, etag);
1054 break;
1055 case Y420_CAPABILITY_MAP_DATA_BLOCK:
1056 DEV_DBG("%s found Y420CMDB byte 3 = 0x%x",
1057 __func__, etag[2]);
1058 hdmi_edid_parse_Y420CMDB(edid_ctrl, etag);
1059 break;
1060 case Y420_VIDEO_DATA_BLOCK:
1061 DEV_DBG("%s found Y420VDB byte 3 = 0x%x",
1062 __func__, etag[2]);
1063 hdmi_edid_parse_Y420VDB(edid_ctrl, etag);
1064 break;
1065 default:
1066 DEV_DBG("%s: Tag Code %d not supported\n",
1067 __func__, etag[1]);
1068 break;
1069 }
1070 } while (1);
1071} /* hdmi_edid_extract_extended_data_blocks */
1072
1073static void hdmi_edid_extract_3d_present(struct hdmi_edid_ctrl *edid_ctrl,
1074 const u8 *in_buf)
1075{
1076 u8 len, offset;
1077 const u8 *vsd = NULL;
1078
1079 if (!edid_ctrl) {
1080 DEV_ERR("%s: invalid input\n", __func__);
1081 return;
1082 }
1083
1084 vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
1085 VENDOR_SPECIFIC_DATA_BLOCK, &len);
1086
1087 edid_ctrl->present_3d = 0;
1088 if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
1089 DEV_DBG("%s: No/Invalid vendor Specific Data Block\n",
1090 __func__);
1091 return;
1092 }
1093
1094 offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
1095 DEV_DBG("%s: EDID: 3D present @ 0x%x = %02x\n", __func__,
1096 offset, vsd[offset]);
1097
1098 if (vsd[offset] >> 7) { /* 3D format indication present */
1099 DEV_INFO("%s: EDID: 3D present, 3D-len=%d\n", __func__,
1100 vsd[offset+1] & 0x1F);
1101 edid_ctrl->present_3d = 1;
1102 }
1103} /* hdmi_edid_extract_3d_present */
1104
1105static void hdmi_edid_extract_audio_data_blocks(
1106 struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
1107{
1108 u8 len = 0;
1109 u8 adb_max = 0;
1110 const u8 *adb = NULL;
1111 u32 offset = DBC_START_OFFSET;
1112
1113 if (!edid_ctrl) {
1114 DEV_ERR("%s: invalid input\n", __func__);
1115 return;
1116 }
1117
1118 edid_ctrl->adb_size = 0;
1119
1120 memset(edid_ctrl->audio_data_block, 0,
1121 sizeof(edid_ctrl->audio_data_block));
1122
1123 do {
1124 len = 0;
1125 adb = hdmi_edid_find_block(in_buf, offset, AUDIO_DATA_BLOCK,
1126 &len);
1127
1128 if ((adb == NULL) || (len > MAX_AUDIO_DATA_BLOCK_SIZE ||
1129 adb_max >= MAX_NUMBER_ADB)) {
1130 if (!edid_ctrl->adb_size) {
1131 DEV_DBG("%s: No/Invalid Audio Data Block\n",
1132 __func__);
1133 return;
1134 }
1135 DEV_DBG("%s: No more valid ADB found\n",
1136 __func__);
1137
1138 continue;
1139 }
1140
1141 memcpy(edid_ctrl->audio_data_block + edid_ctrl->adb_size,
1142 adb + 1, len);
1143 offset = (adb - in_buf) + 1 + len;
1144
1145 edid_ctrl->adb_size += len;
1146 adb_max++;
1147 } while (adb);
1148
1149} /* hdmi_edid_extract_audio_data_blocks */
1150
1151static void hdmi_edid_extract_speaker_allocation_data(
1152 struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
1153{
1154 u8 len;
1155 const u8 *sadb = NULL;
1156
1157 if (!edid_ctrl) {
1158 DEV_ERR("%s: invalid input\n", __func__);
1159 return;
1160 }
1161
1162 sadb = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
1163 SPEAKER_ALLOCATION_DATA_BLOCK, &len);
1164 if ((sadb == NULL) || (len != MAX_SPKR_ALLOC_DATA_BLOCK_SIZE)) {
1165 DEV_DBG("%s: No/Invalid Speaker Allocation Data Block\n",
1166 __func__);
1167 return;
1168 }
1169
1170 memcpy(edid_ctrl->spkr_alloc_data_block, sadb + 1, len);
1171 edid_ctrl->sadb_size = len;
1172
1173 DEV_DBG("%s: EDID: speaker alloc data SP byte = %08x %s%s%s%s%s%s%s\n",
1174 __func__, sadb[1],
1175 (sadb[1] & BIT(0)) ? "FL/FR," : "",
1176 (sadb[1] & BIT(1)) ? "LFE," : "",
1177 (sadb[1] & BIT(2)) ? "FC," : "",
1178 (sadb[1] & BIT(3)) ? "RL/RR," : "",
1179 (sadb[1] & BIT(4)) ? "RC," : "",
1180 (sadb[1] & BIT(5)) ? "FLC/FRC," : "",
1181 (sadb[1] & BIT(6)) ? "RLC/RRC," : "");
1182} /* hdmi_edid_extract_speaker_allocation_data */
1183
1184static void hdmi_edid_extract_sink_caps(struct hdmi_edid_ctrl *edid_ctrl,
1185 const u8 *in_buf)
1186{
1187 u8 len = 0, i = 0;
1188 const u8 *vsd = NULL;
1189 u32 vsd_offset = DBC_START_OFFSET;
1190 u32 hf_ieee_oui = 0;
1191
1192 if (!edid_ctrl) {
1193 DEV_ERR("%s: invalid input\n", __func__);
1194 return;
1195 }
1196
1197 /* Find HF-VSDB with HF-OUI */
1198 do {
1199 vsd = hdmi_edid_find_block(in_buf, vsd_offset,
1200 VENDOR_SPECIFIC_DATA_BLOCK, &len);
1201
1202 if (!vsd || !len || len > MAX_DATA_BLOCK_SIZE) {
1203 if (i == 0)
1204 DEV_ERR("%s: VSDB not found\n", __func__);
1205 else
1206 DEV_DBG("%s: no more VSDB found\n", __func__);
1207 break;
1208 }
1209
1210 hf_ieee_oui = (vsd[1] << 16) | (vsd[2] << 8) | vsd[3];
1211
1212 if (hf_ieee_oui == HDMI_FORUM_IEEE_OUI) {
1213 DEV_DBG("%s: found HF-VSDB\n", __func__);
1214 break;
1215 }
1216
1217 DEV_DBG("%s: Not a HF OUI 0x%x\n", __func__, hf_ieee_oui);
1218
1219 i++;
1220 vsd_offset = vsd - in_buf + len + 1;
1221 } while (1);
1222
1223 if (!vsd) {
1224 DEV_DBG("%s: HF-VSDB not found\n", __func__);
1225 return;
1226 }
1227
1228 /* Max pixel clock is in multiples of 5Mhz. */
1229 edid_ctrl->sink_caps.max_pclk_in_hz =
1230 vsd[5]*5000000;
1231 edid_ctrl->sink_caps.scdc_present =
1232 (vsd[6] & 0x80) ? true : false;
1233 edid_ctrl->sink_caps.scramble_support =
1234 (vsd[6] & 0x08) ? true : false;
1235 edid_ctrl->sink_caps.read_req_support =
1236 (vsd[6] & 0x40) ? true : false;
1237 edid_ctrl->sink_caps.osd_disparity =
1238 (vsd[6] & 0x01) ? true : false;
1239 edid_ctrl->sink_caps.dual_view_support =
1240 (vsd[6] & 0x02) ? true : false;
1241 edid_ctrl->sink_caps.ind_view_support =
1242 (vsd[6] & 0x04) ? true : false;
1243}
1244
1245static void hdmi_edid_extract_latency_fields(struct hdmi_edid_ctrl *edid_ctrl,
1246 const u8 *in_buf)
1247{
1248 u8 len;
1249 const u8 *vsd = NULL;
1250
1251 if (!edid_ctrl) {
1252 DEV_ERR("%s: invalid input\n", __func__);
1253 return;
1254 }
1255
1256 vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
1257 VENDOR_SPECIFIC_DATA_BLOCK, &len);
1258
1259 if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE ||
1260 !(vsd[8] & BIT(7))) {
1261 edid_ctrl->video_latency = (u16)-1;
1262 edid_ctrl->audio_latency = (u16)-1;
1263 DEV_DBG("%s: EDID: No audio/video latency present\n", __func__);
1264 } else {
1265 edid_ctrl->video_latency = vsd[9];
1266 edid_ctrl->audio_latency = vsd[10];
1267 DEV_DBG("%s: EDID: video-latency=%04x, audio-latency=%04x\n",
1268 __func__, edid_ctrl->video_latency,
1269 edid_ctrl->audio_latency);
1270 }
1271} /* hdmi_edid_extract_latency_fields */
1272
1273static u32 hdmi_edid_extract_ieee_reg_id(struct hdmi_edid_ctrl *edid_ctrl,
1274 const u8 *in_buf)
1275{
1276 u8 len;
1277 const u8 *vsd = NULL;
1278
1279 if (!edid_ctrl) {
1280 DEV_ERR("%s: invalid input\n", __func__);
1281 return 0;
1282 }
1283
1284 vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
1285 VENDOR_SPECIFIC_DATA_BLOCK, &len);
1286
1287 if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
1288 DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
1289 __func__);
1290 return 0;
1291 }
1292
1293 DEV_DBG("%s: EDID: VSD PhyAddr=%04x, MaxTMDS=%dMHz\n", __func__,
1294 ((u32)vsd[4] << 8) + (u32)vsd[5], (u32)vsd[7] * 5);
1295
1296 edid_ctrl->physical_address = ((u16)vsd[4] << 8) + (u16)vsd[5];
1297
1298 return ((u32)vsd[3] << 16) + ((u32)vsd[2] << 8) + (u32)vsd[1];
1299} /* hdmi_edid_extract_ieee_reg_id */
1300
1301static void hdmi_edid_extract_vendor_id(struct hdmi_edid_ctrl *edid_ctrl)
1302{
1303 char *vendor_id;
1304 u32 id_codes;
1305
1306 if (!edid_ctrl) {
1307 DEV_ERR("%s: invalid input\n", __func__);
1308 return;
1309 }
1310
1311 vendor_id = edid_ctrl->vendor_id;
1312 id_codes = ((u32)edid_ctrl->edid_buf[8] << 8) +
1313 edid_ctrl->edid_buf[9];
1314
1315 vendor_id[0] = 'A' - 1 + ((id_codes >> 10) & 0x1F);
1316 vendor_id[1] = 'A' - 1 + ((id_codes >> 5) & 0x1F);
1317 vendor_id[2] = 'A' - 1 + (id_codes & 0x1F);
1318 vendor_id[3] = 0;
1319} /* hdmi_edid_extract_vendor_id */
1320
1321static u32 hdmi_edid_check_header(const u8 *edid_buf)
1322{
1323 return (edid_buf[0] == 0x00) && (edid_buf[1] == 0xff)
1324 && (edid_buf[2] == 0xff) && (edid_buf[3] == 0xff)
1325 && (edid_buf[4] == 0xff) && (edid_buf[5] == 0xff)
1326 && (edid_buf[6] == 0xff) && (edid_buf[7] == 0x00);
1327} /* hdmi_edid_check_header */
1328
1329static void hdmi_edid_detail_desc(struct hdmi_edid_ctrl *edid_ctrl,
1330 const u8 *data_buf, u32 *disp_mode)
1331{
1332 u32 aspect_ratio_4_3 = false;
1333 u32 aspect_ratio_5_4 = false;
1334 u32 interlaced = false;
1335 u32 active_h = 0;
1336 u32 active_v = 0;
1337 u32 blank_h = 0;
1338 u32 blank_v = 0;
1339 u32 img_size_h = 0;
1340 u32 img_size_v = 0;
1341 u32 pixel_clk = 0;
1342 u32 front_porch_h = 0;
1343 u32 front_porch_v = 0;
1344 u32 pulse_width_h = 0;
1345 u32 pulse_width_v = 0;
1346 u32 active_low_h = 0;
1347 u32 active_low_v = 0;
1348 const u32 khz_to_hz = 1000;
1349 u32 frame_data;
1350 struct msm_hdmi_mode_timing_info timing = {0};
1351 int rc;
1352
1353 /*
1354 * Pixel clock/ 10,000
1355 * LSB stored in byte 0 and MSB stored in byte 1
1356 */
1357 pixel_clk = (u32) (data_buf[0x0] | (data_buf[0x1] << 8));
1358
1359 /* store pixel clock in /1000 terms */
1360 pixel_clk *= 10;
1361
1362 /*
1363 * byte 0x8 -- Horizontal Front Porch - contains lower 8 bits
1364 * byte 0xb (bits 6, 7) -- contains upper 2 bits
1365 */
1366 front_porch_h = (u32) (data_buf[0x8] |
1367 (data_buf[0xb] & (0x3 << 6)) << 2);
1368
1369 /*
1370 * byte 0x9 -- Horizontal pulse width - contains lower 8 bits
1371 * byte 0xb (bits 4, 5) -- contains upper 2 bits
1372 */
1373 pulse_width_h = (u32) (data_buf[0x9] |
1374 (data_buf[0xb] & (0x3 << 4)) << 4);
1375
1376 /*
1377 * byte 0xa -- Vertical front porch -- stored in Upper Nibble,
1378 * contains lower 4 bits.
1379 * byte 0xb (bits 2, 3) -- contains upper 2 bits
1380 */
1381 front_porch_v = (u32) (((data_buf[0xa] & (0xF << 4)) >> 4) |
1382 (data_buf[0xb] & (0x3 << 2)) << 2);
1383
1384 /*
1385 * byte 0xa -- Vertical pulse width -- stored in Lower Nibble,
1386 * contains lower 4 bits.
1387 * byte 0xb (bits 0, 1) -- contains upper 2 bits
1388 */
1389 pulse_width_v = (u32) ((data_buf[0xa] & 0xF) |
1390 ((data_buf[0xb] & 0x3) << 4));
1391
1392 /*
1393 * * See VESA Spec
1394 * * EDID_TIMING_DESC_UPPER_H_NIBBLE[0x4]: Relative Offset to the
1395 * EDID detailed timing descriptors - Upper 4 bit for each H
1396 * active/blank field
1397 * * EDID_TIMING_DESC_H_ACTIVE[0x2]: Relative Offset to the EDID
1398 * detailed timing descriptors - H active
1399 */
1400 active_h = ((((u32)data_buf[0x4] >> 0x4) & 0xF) << 8)
1401 | data_buf[0x2];
1402
1403 /*
1404 * EDID_TIMING_DESC_H_BLANK[0x3]: Relative Offset to the EDID detailed
1405 * timing descriptors - H blank
1406 */
1407 blank_h = (((u32)data_buf[0x4] & 0xF) << 8)
1408 | data_buf[0x3];
1409
1410 /*
1411 * * EDID_TIMING_DESC_UPPER_V_NIBBLE[0x7]: Relative Offset to the
1412 * EDID detailed timing descriptors - Upper 4 bit for each V
1413 * active/blank field
1414 * * EDID_TIMING_DESC_V_ACTIVE[0x5]: Relative Offset to the EDID
1415 * detailed timing descriptors - V active
1416 */
1417 active_v = ((((u32)data_buf[0x7] >> 0x4) & 0xF) << 8)
1418 | data_buf[0x5];
1419
1420 /*
1421 * EDID_TIMING_DESC_V_BLANK[0x6]: Relative Offset to the EDID
1422 * detailed timing descriptors - V blank
1423 */
1424 blank_v = (((u32)data_buf[0x7] & 0xF) << 8)
1425 | data_buf[0x6];
1426
1427 /*
1428 * * EDID_TIMING_DESC_IMAGE_SIZE_UPPER_NIBBLE[0xE]: Relative Offset
1429 * to the EDID detailed timing descriptors - Image Size upper
1430 * nibble V and H
1431 * * EDID_TIMING_DESC_H_IMAGE_SIZE[0xC]: Relative Offset to the EDID
1432 * detailed timing descriptors - H image size
1433 * * EDID_TIMING_DESC_V_IMAGE_SIZE[0xD]: Relative Offset to the EDID
1434 * detailed timing descriptors - V image size
1435 */
1436 img_size_h = ((((u32)data_buf[0xE] >> 0x4) & 0xF) << 8)
1437 | data_buf[0xC];
1438 img_size_v = (((u32)data_buf[0xE] & 0xF) << 8)
1439 | data_buf[0xD];
1440
1441 /*
1442 * aspect ratio as 4:3 if within specificed range, rather than being
1443 * absolute value
1444 */
1445 aspect_ratio_4_3 = (abs(img_size_h * 3 - img_size_v * 4) < 5) ? 1 : 0;
1446
1447 aspect_ratio_5_4 = (abs(img_size_h * 4 - img_size_v * 5) < 5) ? 1 : 0;
1448
1449 /*
1450 * EDID_TIMING_DESC_INTERLACE[0x11:7]: Relative Offset to the EDID
1451 * detailed timing descriptors - Interlace flag
1452 */
1453 DEV_DBG("%s: Interlaced mode byte data_buf[0x11]=[%x]\n", __func__,
1454 data_buf[0x11]);
1455
1456 /*
1457 * CEA 861-D: interlaced bit is bit[7] of byte[0x11]
1458 */
1459 interlaced = (data_buf[0x11] & 0x80) >> 7;
1460
1461 active_low_v = ((data_buf[0x11] & (0x7 << 2)) >> 2) == 0x7 ? 0 : 1;
1462
1463 active_low_h = ((data_buf[0x11] & BIT(1)) &&
1464 (data_buf[0x11] & BIT(4))) ? 0 : 1;
1465
1466 frame_data = (active_h + blank_h) * (active_v + blank_v);
1467
1468 if (frame_data) {
1469 int refresh_rate_khz = (pixel_clk * khz_to_hz) / frame_data;
1470
1471 timing.active_h = active_h;
1472 timing.front_porch_h = front_porch_h;
1473 timing.pulse_width_h = pulse_width_h;
1474 timing.back_porch_h = blank_h -
1475 (front_porch_h + pulse_width_h);
1476 timing.active_low_h = active_low_h;
1477 timing.active_v = active_v;
1478 timing.front_porch_v = front_porch_v;
1479 timing.pulse_width_v = pulse_width_v;
1480 timing.back_porch_v = blank_v -
1481 (front_porch_v + pulse_width_v);
1482 timing.active_low_v = active_low_v;
1483 timing.pixel_freq = pixel_clk;
1484 timing.refresh_rate = refresh_rate_khz * khz_to_hz;
1485 timing.interlaced = interlaced;
1486 timing.supported = true;
1487 timing.ar = aspect_ratio_4_3 ? HDMI_RES_AR_4_3 :
1488 (aspect_ratio_5_4 ? HDMI_RES_AR_5_4 :
1489 HDMI_RES_AR_16_9);
1490
1491 DEV_DBG("%s: new res: %dx%d%s@%dHz\n", __func__,
1492 timing.active_h, timing.active_v,
1493 interlaced ? "i" : "p",
1494 timing.refresh_rate / khz_to_hz);
1495
1496 rc = hdmi_set_resv_timing_info(&timing);
1497 } else {
1498 DEV_ERR("%s: Invalid frame data\n", __func__);
1499 rc = -EINVAL;
1500 }
1501
1502 if (!IS_ERR_VALUE(rc)) {
1503 *disp_mode = rc;
1504 DEV_DBG("%s: DTD mode found: %d\n", __func__, *disp_mode);
1505 } else {
1506 *disp_mode = HDMI_VFRMT_UNKNOWN;
1507 DEV_ERR("%s: error adding mode from DTD: %d\n", __func__, rc);
1508 }
1509} /* hdmi_edid_detail_desc */
1510
1511static void hdmi_edid_add_sink_3d_format(struct hdmi_edid_sink_data *sink_data,
1512 u32 video_format, u32 video_3d_format)
1513{
1514 char string[BUFF_SIZE_3D];
1515 u32 added = false;
1516 int i;
1517
1518 for (i = 0; i < sink_data->num_of_elements; ++i) {
1519 if (sink_data->disp_mode_list[i].video_format == video_format) {
1520 sink_data->disp_mode_list[i].video_3d_format |=
1521 video_3d_format;
1522 added = true;
1523 break;
1524 }
1525 }
1526
1527 hdmi_get_video_3d_fmt_2string(video_3d_format, string, sizeof(string));
1528
1529 DEV_DBG("%s: EDID[3D]: format: %d [%s], %s %s\n", __func__,
1530 video_format, msm_hdmi_mode_2string(video_format),
1531 string, added ? "added" : "NOT added");
1532} /* hdmi_edid_add_sink_3d_format */
1533
1534static void hdmi_edid_add_sink_video_format(struct hdmi_edid_ctrl *edid_ctrl,
1535 u32 video_format)
1536{
1537 struct msm_hdmi_mode_timing_info timing = {0};
1538 u32 ret = hdmi_get_supported_mode(&timing,
1539 &edid_ctrl->init_data.ds_data,
1540 video_format);
1541 u32 supported = hdmi_edid_is_mode_supported(edid_ctrl, &timing);
1542 struct hdmi_edid_sink_data *sink_data = &edid_ctrl->sink_data;
1543 struct disp_mode_info *disp_mode_list = sink_data->disp_mode_list;
1544
1545 if (video_format >= HDMI_VFRMT_MAX) {
1546 DEV_ERR("%s: video format: %s is not supported\n", __func__,
1547 msm_hdmi_mode_2string(video_format));
1548 return;
1549 }
1550
1551 DEV_DBG("%s: EDID: format: %d [%s], %s\n", __func__,
1552 video_format, msm_hdmi_mode_2string(video_format),
1553 supported ? "Supported" : "Not-Supported");
1554
1555 if (!ret && supported) {
1556 /* todo: MHL */
1557 disp_mode_list[sink_data->num_of_elements].video_format =
1558 video_format;
1559 disp_mode_list[sink_data->num_of_elements].rgb_support =
1560 true;
1561 sink_data->num_of_elements++;
1562 }
1563} /* hdmi_edid_add_sink_video_format */
1564
1565static int hdmi_edid_get_display_vsd_3d_mode(const u8 *data_buf,
1566 struct hdmi_edid_sink_data *sink_data, u32 num_of_cea_blocks)
1567{
1568 u8 len, offset, present_multi_3d, hdmi_vic_len;
1569 int hdmi_3d_len;
1570 u16 structure_all, structure_mask;
1571 const u8 *vsd = num_of_cea_blocks ?
1572 hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
1573 VENDOR_SPECIFIC_DATA_BLOCK, &len) : NULL;
1574 int i;
1575
1576 if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE) {
1577 DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
1578 __func__);
1579 return -ENXIO;
1580 }
1581
1582 offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
1583 if (offset >= len - 1)
1584 return -ETOOSMALL;
1585
1586 present_multi_3d = (vsd[offset] & 0x60) >> 5;
1587
1588 offset += 1;
1589
1590 hdmi_vic_len = (vsd[offset] >> 5) & 0x7;
1591 hdmi_3d_len = vsd[offset] & 0x1F;
1592 DEV_DBG("%s: EDID[3D]: HDMI_VIC_LEN = %d, HDMI_3D_LEN = %d\n", __func__,
1593 hdmi_vic_len, hdmi_3d_len);
1594
1595 offset += (hdmi_vic_len + 1);
1596 if (offset >= len - 1)
1597 return -ETOOSMALL;
1598
1599 if (present_multi_3d == 1 || present_multi_3d == 2) {
1600 DEV_DBG("%s: EDID[3D]: multi 3D present (%d)\n", __func__,
1601 present_multi_3d);
1602 /* 3d_structure_all */
1603 structure_all = (vsd[offset] << 8) | vsd[offset + 1];
1604 offset += 2;
1605 if (offset >= len - 1)
1606 return -ETOOSMALL;
1607 hdmi_3d_len -= 2;
1608 if (present_multi_3d == 2) {
1609 /* 3d_structure_mask */
1610 structure_mask = (vsd[offset] << 8) | vsd[offset + 1];
1611 offset += 2;
1612 hdmi_3d_len -= 2;
1613 } else
1614 structure_mask = 0xffff;
1615
1616 i = 0;
1617 while (i < 16) {
1618 if (i >= sink_data->disp_multi_3d_mode_list_cnt)
1619 break;
1620
1621 if (!(structure_mask & BIT(i))) {
1622 ++i;
1623 continue;
1624 }
1625
1626 /* BIT0: FRAME PACKING */
1627 if (structure_all & BIT(0))
1628 hdmi_edid_add_sink_3d_format(sink_data,
1629 sink_data->
1630 disp_multi_3d_mode_list[i],
1631 FRAME_PACKING);
1632
1633 /* BIT6: TOP AND BOTTOM */
1634 if (structure_all & BIT(6))
1635 hdmi_edid_add_sink_3d_format(sink_data,
1636 sink_data->
1637 disp_multi_3d_mode_list[i],
1638 TOP_AND_BOTTOM);
1639
1640 /* BIT8: SIDE BY SIDE HALF */
1641 if (structure_all & BIT(8))
1642 hdmi_edid_add_sink_3d_format(sink_data,
1643 sink_data->
1644 disp_multi_3d_mode_list[i],
1645 SIDE_BY_SIDE_HALF);
1646
1647 ++i;
1648 }
1649 }
1650
1651 i = 0;
1652 while (hdmi_3d_len > 0) {
1653 if (offset >= len - 1)
1654 return -ETOOSMALL;
1655 DEV_DBG("%s: EDID: 3D_Structure_%d @ 0x%x: %02x\n",
1656 __func__, i + 1, offset, vsd[offset]);
1657 if ((vsd[offset] >> 4) >=
1658 sink_data->disp_multi_3d_mode_list_cnt) {
1659 if ((vsd[offset] & 0x0F) >= 8) {
1660 offset += 1;
1661 hdmi_3d_len -= 1;
1662 DEV_DBG("%s:EDID:3D_Detail_%d @ 0x%x: %02x\n",
1663 __func__, i + 1, offset,
1664 vsd[min_t(u32, offset, (len - 1))]);
1665 }
1666 i += 1;
1667 offset += 1;
1668 hdmi_3d_len -= 1;
1669 continue;
1670 }
1671
1672 switch (vsd[offset] & 0x0F) {
1673 case 0:
1674 /* 0000b: FRAME PACKING */
1675 hdmi_edid_add_sink_3d_format(sink_data,
1676 sink_data->
1677 disp_multi_3d_mode_list[vsd[offset] >> 4],
1678 FRAME_PACKING);
1679 break;
1680 case 6:
1681 /* 0110b: TOP AND BOTTOM */
1682 hdmi_edid_add_sink_3d_format(sink_data,
1683 sink_data->
1684 disp_multi_3d_mode_list[vsd[offset] >> 4],
1685 TOP_AND_BOTTOM);
1686 break;
1687 case 8:
1688 /* 1000b: SIDE BY SIDE HALF */
1689 hdmi_edid_add_sink_3d_format(sink_data,
1690 sink_data->
1691 disp_multi_3d_mode_list[vsd[offset] >> 4],
1692 SIDE_BY_SIDE_HALF);
1693 break;
1694 }
1695 if ((vsd[offset] & 0x0F) >= 8) {
1696 offset += 1;
1697 hdmi_3d_len -= 1;
1698 DEV_DBG("%s: EDID[3D]: 3D_Detail_%d @ 0x%x: %02x\n",
1699 __func__, i + 1, offset,
1700 vsd[min_t(u32, offset, (len - 1))]);
1701 }
1702 i += 1;
1703 offset += 1;
1704 hdmi_3d_len -= 1;
1705 }
1706 return 0;
1707} /* hdmi_edid_get_display_vsd_3d_mode */
1708
1709static void hdmi_edid_get_extended_video_formats(
1710 struct hdmi_edid_ctrl *edid_ctrl, const u8 *in_buf)
1711{
1712 u8 db_len, offset, i;
1713 u8 hdmi_vic_len;
1714 u32 video_format;
1715 const u8 *vsd = NULL;
1716
1717 if (!edid_ctrl) {
1718 DEV_ERR("%s: invalid input\n", __func__);
1719 return;
1720 }
1721
1722 vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
1723 VENDOR_SPECIFIC_DATA_BLOCK, &db_len);
1724
1725 if (vsd == NULL || db_len == 0 || db_len > MAX_DATA_BLOCK_SIZE) {
1726 DEV_DBG("%s: No/Invalid Vendor Specific Data Block\n",
1727 __func__);
1728 return;
1729 }
1730
1731 /* check if HDMI_Video_present flag is set or not */
1732 if (!(vsd[8] & BIT(5))) {
1733 DEV_DBG("%s: extended vfmts are not supported by the sink.\n",
1734 __func__);
1735 return;
1736 }
1737
1738 offset = HDMI_VSDB_3D_EVF_DATA_OFFSET(vsd);
1739
1740 hdmi_vic_len = vsd[offset + 1] >> 5;
1741 if (hdmi_vic_len) {
1742 DEV_DBG("%s: EDID: EVFRMT @ 0x%x of block 3, len = %02x\n",
1743 __func__, offset, hdmi_vic_len);
1744
1745 for (i = 0; i < hdmi_vic_len; i++) {
1746 video_format = HDMI_VFRMT_END + vsd[offset + 2 + i];
1747 hdmi_edid_add_sink_video_format(edid_ctrl,
1748 video_format);
1749 }
1750 }
1751} /* hdmi_edid_get_extended_video_formats */
1752
1753static void hdmi_edid_parse_et3(struct hdmi_edid_ctrl *edid_ctrl,
1754 const u8 *edid_blk0)
1755{
1756 u8 start = DTD_OFFSET, i = 0;
1757 struct hdmi_edid_sink_data *sink_data = NULL;
1758
1759 if (!edid_ctrl || !edid_blk0) {
1760 DEV_ERR("%s: invalid input\n", __func__);
1761 return;
1762 }
1763
1764 sink_data = &edid_ctrl->sink_data;
1765
1766 /* check if the EDID revision is 4 (version 1.4) */
1767 if (edid_blk0[REVISION_OFFSET] != EDID_REVISION_FOUR)
1768 return;
1769
1770 /* Check each of 4 - 18 bytes descriptors */
1771 while (i < DTD_MAX) {
1772 u8 iter = start;
1773 u32 header_1 = 0;
1774 u8 header_2 = 0;
1775
1776 header_1 = edid_blk0[iter++];
1777 header_1 = header_1 << 8 | edid_blk0[iter++];
1778 header_1 = header_1 << 8 | edid_blk0[iter++];
1779 header_1 = header_1 << 8 | edid_blk0[iter++];
1780 header_2 = edid_blk0[iter];
1781
1782 if (header_1 != 0x000000F7 || header_2 != 0x00)
1783 goto loop_end;
1784
1785 /* VESA DMT Standard Version (0x0A)*/
1786 iter++;
1787
1788 /* First set of supported formats */
1789 iter++;
1790 if (edid_blk0[iter] & BIT(3)) {
1791 pr_debug("%s: DMT 848x480@60\n", __func__);
1792 hdmi_edid_add_sink_video_format(edid_ctrl,
1793 HDMI_VFRMT_848x480p60_16_9);
1794 }
1795
1796 /* Second set of supported formats */
1797 iter++;
1798 if (edid_blk0[iter] & BIT(1)) {
1799 pr_debug("%s: DMT 1280x1024@60\n", __func__);
1800 hdmi_edid_add_sink_video_format(edid_ctrl,
1801 HDMI_VFRMT_1280x1024p60_5_4);
1802 }
1803
1804 if (edid_blk0[iter] & BIT(3)) {
1805 pr_debug("%s: DMT 1280x960@60\n", __func__);
1806 hdmi_edid_add_sink_video_format(edid_ctrl,
1807 HDMI_VFRMT_1280x960p60_4_3);
1808 }
1809
1810 /* Third set of supported formats */
1811 iter++;
1812 if (edid_blk0[iter] & BIT(1)) {
1813 pr_debug("%s: DMT 1400x1050@60\n", __func__);
1814 hdmi_edid_add_sink_video_format(edid_ctrl,
1815 HDMI_VFRMT_1400x1050p60_4_3);
1816 }
1817
1818 if (edid_blk0[iter] & BIT(5)) {
1819 pr_debug("%s: DMT 1440x900@60\n", __func__);
1820 hdmi_edid_add_sink_video_format(edid_ctrl,
1821 HDMI_VFRMT_1440x900p60_16_10);
1822 }
1823
1824 if (edid_blk0[iter] & BIT(7)) {
1825 pr_debug("%s: DMT 1360x768@60\n", __func__);
1826 hdmi_edid_add_sink_video_format(edid_ctrl,
1827 HDMI_VFRMT_1360x768p60_16_9);
1828 }
1829
1830 /* Fourth set of supported formats */
1831 iter++;
1832 if (edid_blk0[iter] & BIT(2)) {
1833 pr_debug("%s: DMT 1600x1200@60\n", __func__);
1834 hdmi_edid_add_sink_video_format(edid_ctrl,
1835 HDMI_VFRMT_1600x1200p60_4_3);
1836 }
1837
1838 if (edid_blk0[iter] & BIT(5)) {
1839 pr_debug("%s: DMT 1680x1050@60\n", __func__);
1840 hdmi_edid_add_sink_video_format(edid_ctrl,
1841 HDMI_VFRMT_1680x1050p60_16_10);
1842 }
1843
1844 /* Fifth set of supported formats */
1845 iter++;
1846 if (edid_blk0[iter] & BIT(0)) {
1847 pr_debug("%s: DMT 1920x1200@60\n", __func__);
1848 hdmi_edid_add_sink_video_format(edid_ctrl,
1849 HDMI_VFRMT_1920x1200p60_16_10);
1850 }
1851
1852loop_end:
1853 i++;
1854 start += DTD_SIZE;
1855 }
1856}
1857
1858static void hdmi_edid_get_display_mode(struct hdmi_edid_ctrl *edid_ctrl)
1859{
1860 u8 i = 0, offset = 0, std_blk = 0;
1861 u32 video_format = HDMI_VFRMT_640x480p60_4_3;
1862 u32 has480p = false;
1863 u8 len = 0;
1864 u8 num_of_cea_blocks;
1865 u8 *data_buf;
1866 int rc;
1867 const u8 *edid_blk0 = NULL;
1868 const u8 *edid_blk1 = NULL;
1869 const u8 *svd = NULL;
1870 u32 has60hz_mode = false;
1871 u32 has50hz_mode = false;
1872 bool read_block0_res = false;
1873 struct hdmi_edid_sink_data *sink_data = NULL;
1874
1875 if (!edid_ctrl) {
1876 DEV_ERR("%s: invalid input\n", __func__);
1877 return;
1878 }
1879
1880 data_buf = edid_ctrl->edid_buf;
1881 num_of_cea_blocks = edid_ctrl->cea_blks;
1882
1883 edid_blk0 = &data_buf[0x0];
1884 edid_blk1 = &data_buf[0x80];
1885 svd = num_of_cea_blocks ?
1886 hdmi_edid_find_block(data_buf+0x80, DBC_START_OFFSET,
1887 VIDEO_DATA_BLOCK, &len) : NULL;
1888
1889 if (num_of_cea_blocks && (len == 0 || len > MAX_DATA_BLOCK_SIZE)) {
1890 DEV_DBG("%s: fall back to block 0 res\n", __func__);
1891 svd = NULL;
1892 read_block0_res = true;
1893 }
1894
1895 sink_data = &edid_ctrl->sink_data;
1896
1897 sink_data->disp_multi_3d_mode_list_cnt = 0;
1898 if (svd != NULL) {
1899 ++svd;
1900 for (i = 0; i < len; ++i, ++svd) {
1901 /*
1902 * Subtract 1 because it is zero based in the driver,
1903 * while the Video identification code is 1 based in the
1904 * CEA_861D spec
1905 */
1906 video_format = (*svd & 0x7F);
1907 hdmi_edid_add_sink_video_format(edid_ctrl,
1908 video_format);
1909 /* Make a note of the preferred video format */
1910 if (i == 0)
1911 sink_data->preferred_video_format =
1912 video_format;
1913
1914 if (i < 16) {
1915 sink_data->disp_multi_3d_mode_list[i]
1916 = video_format;
1917 sink_data->disp_multi_3d_mode_list_cnt++;
1918 }
1919
1920 if (video_format <= HDMI_VFRMT_1920x1080p60_16_9 ||
1921 video_format == HDMI_VFRMT_2880x480p60_4_3 ||
1922 video_format == HDMI_VFRMT_2880x480p60_16_9)
1923 has60hz_mode = true;
1924
1925 if ((video_format >= HDMI_VFRMT_720x576p50_4_3 &&
1926 video_format <= HDMI_VFRMT_1920x1080p50_16_9) ||
1927 video_format == HDMI_VFRMT_2880x576p50_4_3 ||
1928 video_format == HDMI_VFRMT_2880x576p50_16_9 ||
1929 video_format == HDMI_VFRMT_1920x1250i50_16_9)
1930 has50hz_mode = true;
1931
1932 if (video_format == HDMI_VFRMT_640x480p60_4_3)
1933 has480p = true;
1934 }
1935 } else if (!num_of_cea_blocks || read_block0_res) {
1936 /* Detailed timing descriptors */
1937 u32 desc_offset = 0;
1938 /*
1939 * * Maximum 4 timing descriptor in block 0 - No CEA
1940 * extension in this case
1941 * * EDID_FIRST_TIMING_DESC[0x36] - 1st detailed timing
1942 * descriptor
1943 * * EDID_DETAIL_TIMING_DESC_BLCK_SZ[0x12] - Each detailed
1944 * timing descriptor has block size of 18
1945 */
1946 while (4 > i && 0 != edid_blk0[0x36+desc_offset]) {
1947 hdmi_edid_detail_desc(edid_ctrl,
1948 edid_blk0+0x36+desc_offset,
1949 &video_format);
1950
1951 DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
1952 __func__, __LINE__,
1953 msm_hdmi_mode_2string(video_format));
1954
1955 hdmi_edid_add_sink_video_format(edid_ctrl,
1956 video_format);
1957
1958 if (video_format == HDMI_VFRMT_640x480p60_4_3)
1959 has480p = true;
1960
1961 /* Make a note of the preferred video format */
1962 if (i == 0) {
1963 sink_data->preferred_video_format =
1964 video_format;
1965 }
1966 desc_offset += 0x12;
1967 ++i;
1968 }
1969 } else if (num_of_cea_blocks == 1) {
1970 u32 desc_offset = 0;
1971
1972 /*
1973 * Read from both block 0 and block 1
1974 * Read EDID block[0] as above
1975 */
1976 while (4 > i && 0 != edid_blk0[0x36+desc_offset]) {
1977 hdmi_edid_detail_desc(edid_ctrl,
1978 edid_blk0+0x36+desc_offset,
1979 &video_format);
1980
1981 DEV_DBG("[%s:%d] Block-0 Adding vid fmt = [%s]\n",
1982 __func__, __LINE__,
1983 msm_hdmi_mode_2string(video_format));
1984
1985 hdmi_edid_add_sink_video_format(edid_ctrl,
1986 video_format);
1987
1988 if (video_format == HDMI_VFRMT_640x480p60_4_3)
1989 has480p = true;
1990
1991 /* Make a note of the preferred video format */
1992 if (i == 0) {
1993 sink_data->preferred_video_format =
1994 video_format;
1995 }
1996 desc_offset += 0x12;
1997 ++i;
1998 }
1999
2000 /*
2001 * * Parse block 1 - CEA extension byte offset of first
2002 * detailed timing generation - offset is relevant to
2003 * the offset of block 1
2004 * * EDID_CEA_EXTENSION_FIRST_DESC[0x82]: Offset to CEA
2005 * extension first timing desc - indicate the offset of
2006 * the first detailed timing descriptor
2007 * * EDID_BLOCK_SIZE = 0x80 Each page size in the EDID ROM
2008 */
2009 desc_offset = edid_blk1[0x02];
2010 while (edid_blk1[desc_offset] != 0) {
2011 hdmi_edid_detail_desc(edid_ctrl,
2012 edid_blk1+desc_offset,
2013 &video_format);
2014
2015 DEV_DBG("[%s:%d] Block-1 Adding vid fmt = [%s]\n",
2016 __func__, __LINE__,
2017 msm_hdmi_mode_2string(video_format));
2018
2019 hdmi_edid_add_sink_video_format(edid_ctrl,
2020 video_format);
2021 if (video_format == HDMI_VFRMT_640x480p60_4_3)
2022 has480p = true;
2023
2024 /* Make a note of the preferred video format */
2025 if (i == 0) {
2026 sink_data->preferred_video_format =
2027 video_format;
2028 }
2029 desc_offset += 0x12;
2030 ++i;
2031 }
2032 }
2033
2034 std_blk = 0;
2035 offset = 0;
2036 while (std_blk < 8) {
2037 if ((edid_blk0[0x26 + offset] == 0x81) &&
2038 (edid_blk0[0x26 + offset + 1] == 0x80)) {
2039 pr_debug("%s: 108MHz: off=[%x] stdblk=[%x]\n",
2040 __func__, offset, std_blk);
2041 hdmi_edid_add_sink_video_format(edid_ctrl,
2042 HDMI_VFRMT_1280x1024p60_5_4);
2043 }
2044 if ((edid_blk0[0x26 + offset] == 0x61) &&
2045 (edid_blk0[0x26 + offset + 1] == 0x40)) {
2046 pr_debug("%s: 65MHz: off=[%x] stdblk=[%x]\n",
2047 __func__, offset, std_blk);
2048 hdmi_edid_add_sink_video_format(edid_ctrl,
2049 HDMI_VFRMT_1024x768p60_4_3);
2050 break;
2051 }
2052 offset += 2;
2053
2054 std_blk++;
2055 }
2056
2057 /* Established Timing I */
2058 if (edid_blk0[0x23] & BIT(0)) {
2059 pr_debug("%s: DMT: ETI: HDMI_VFRMT_800x600_4_3\n", __func__);
2060 hdmi_edid_add_sink_video_format(edid_ctrl,
2061 HDMI_VFRMT_800x600p60_4_3);
2062 }
2063
2064 /* Established Timing II */
2065 if (edid_blk0[0x24] & BIT(3)) {
2066 pr_debug("%s: DMT: ETII: HDMI_VFRMT_1024x768p60_4_3\n",
2067 __func__);
2068 hdmi_edid_add_sink_video_format(edid_ctrl,
2069 HDMI_VFRMT_1024x768p60_4_3);
2070 }
2071
2072 /* Established Timing III */
2073 hdmi_edid_parse_et3(edid_ctrl, data_buf);
2074
2075 hdmi_edid_get_extended_video_formats(edid_ctrl, data_buf+0x80);
2076
2077 /* mandaroty 3d format */
2078 if (edid_ctrl->present_3d) {
2079 if (has60hz_mode) {
2080 hdmi_edid_add_sink_3d_format(sink_data,
2081 HDMI_VFRMT_1920x1080p24_16_9,
2082 FRAME_PACKING | TOP_AND_BOTTOM);
2083 hdmi_edid_add_sink_3d_format(sink_data,
2084 HDMI_VFRMT_1280x720p60_16_9,
2085 FRAME_PACKING | TOP_AND_BOTTOM);
2086 hdmi_edid_add_sink_3d_format(sink_data,
2087 HDMI_VFRMT_1920x1080i60_16_9,
2088 SIDE_BY_SIDE_HALF);
2089 }
2090
2091 if (has50hz_mode) {
2092 hdmi_edid_add_sink_3d_format(sink_data,
2093 HDMI_VFRMT_1920x1080p24_16_9,
2094 FRAME_PACKING | TOP_AND_BOTTOM);
2095 hdmi_edid_add_sink_3d_format(sink_data,
2096 HDMI_VFRMT_1280x720p50_16_9,
2097 FRAME_PACKING | TOP_AND_BOTTOM);
2098 hdmi_edid_add_sink_3d_format(sink_data,
2099 HDMI_VFRMT_1920x1080i50_16_9,
2100 SIDE_BY_SIDE_HALF);
2101 }
2102
2103 /* 3d format described in Vendor Specific Data */
2104 rc = hdmi_edid_get_display_vsd_3d_mode(data_buf, sink_data,
2105 num_of_cea_blocks);
2106 if (!rc)
2107 pr_debug("%s: 3D formats in VSD\n", __func__);
2108 }
2109
2110 /*
2111 * Need to add default 640 by 480 timings, in case not described
2112 * in the EDID structure.
2113 * All DTV sink devices should support this mode
2114 */
2115 if (!has480p)
2116 hdmi_edid_add_sink_video_format(edid_ctrl,
2117 HDMI_VFRMT_640x480p60_4_3);
2118} /* hdmi_edid_get_display_mode */
2119
2120u32 hdmi_edid_get_raw_data(void *input, u8 *buf, u32 size)
2121{
2122 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *) input;
2123 u32 ret = 0;
2124 u32 buf_size;
2125
2126 if (!edid_ctrl || !buf) {
2127 DEV_ERR("%s: invalid input\n", __func__);
2128 ret = -EINVAL;
2129 goto end;
2130 }
2131
2132 buf_size = sizeof(edid_ctrl->edid_buf);
2133
2134 size = min(size, buf_size);
2135
2136 memcpy(buf, edid_ctrl->edid_buf, size);
2137
2138end:
2139 return ret;
2140}
2141
2142static void hdmi_edid_add_resv_timings(struct hdmi_edid_ctrl *edid_ctrl)
2143{
2144 int i = HDMI_VFRMT_RESERVE1;
2145
2146 while (i <= RESERVE_VFRMT_END) {
2147 if (hdmi_is_valid_resv_timing(i))
2148 hdmi_edid_add_sink_video_format(edid_ctrl, i);
2149 else
2150 break;
2151 i++;
2152 }
2153}
2154
2155int hdmi_edid_parser(void *input)
2156{
2157 u8 *edid_buf = NULL;
2158 u32 num_of_cea_blocks = 0;
2159 u16 ieee_reg_id;
2160 int status = 0;
2161 u32 i = 0;
2162 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2163
2164 if (!edid_ctrl) {
2165 DEV_ERR("%s: invalid input\n", __func__);
2166 status = -EINVAL;
2167 goto err_invalid_data;
2168 }
2169
2170 /* reset edid data for new hdmi connection */
2171 hdmi_edid_reset_parser(edid_ctrl);
2172
2173 edid_buf = edid_ctrl->edid_buf;
2174
2175 DEV_DBG("%s: === HDMI EDID BLOCK 0 ===\n", __func__);
2176 print_hex_dump(KERN_DEBUG, "HDMI EDID: ", DUMP_PREFIX_NONE, 16, 1,
2177 edid_buf, EDID_BLOCK_SIZE, false);
2178
2179 if (!hdmi_edid_check_header(edid_buf)) {
2180 status = -EPROTO;
2181 goto err_invalid_header;
2182 }
2183
2184 hdmi_edid_extract_vendor_id(edid_ctrl);
2185
2186 /* EDID_CEA_EXTENSION_FLAG[0x7E] - CEC extension byte */
2187 num_of_cea_blocks = edid_buf[EDID_BLOCK_SIZE - 2];
2188 DEV_DBG("%s: No. of CEA blocks is [%u]\n", __func__,
2189 num_of_cea_blocks);
2190
2191 /* Find out any CEA extension blocks following block 0 */
2192 if (num_of_cea_blocks == 0) {
2193 /* No CEA extension */
2194 edid_ctrl->sink_mode = SINK_MODE_DVI;
2195 DEV_DBG("HDMI DVI mode: %s\n",
2196 edid_ctrl->sink_mode ? "no" : "yes");
2197 goto bail;
2198 }
2199
2200 /* Find out if CEA extension blocks exceeding max limit */
2201 if (num_of_cea_blocks >= MAX_EDID_BLOCKS) {
2202 DEV_WARN("%s: HDMI EDID exceeded max CEA blocks limit\n",
2203 __func__);
2204 num_of_cea_blocks = MAX_EDID_BLOCKS - 1;
2205 }
2206
2207 /* check for valid CEA block */
2208 if (edid_buf[EDID_BLOCK_SIZE] != 2) {
2209 DEV_ERR("%s: Invalid CEA block\n", __func__);
2210 num_of_cea_blocks = 0;
2211 goto bail;
2212 }
2213
2214 /* goto to CEA extension edid block */
2215 edid_buf += EDID_BLOCK_SIZE;
2216
2217 ieee_reg_id = hdmi_edid_extract_ieee_reg_id(edid_ctrl, edid_buf);
2218 if (ieee_reg_id == EDID_IEEE_REG_ID)
2219 edid_ctrl->sink_mode = SINK_MODE_HDMI;
2220 else
2221 edid_ctrl->sink_mode = SINK_MODE_DVI;
2222
2223 hdmi_edid_extract_sink_caps(edid_ctrl, edid_buf);
2224 hdmi_edid_extract_latency_fields(edid_ctrl, edid_buf);
2225 hdmi_edid_extract_speaker_allocation_data(edid_ctrl, edid_buf);
2226 hdmi_edid_extract_audio_data_blocks(edid_ctrl, edid_buf);
2227 hdmi_edid_extract_3d_present(edid_ctrl, edid_buf);
2228 hdmi_edid_extract_extended_data_blocks(edid_ctrl, edid_buf);
2229
2230bail:
2231 for (i = 1; i <= num_of_cea_blocks; i++) {
2232 DEV_DBG("%s: === HDMI EDID BLOCK %d ===\n", __func__, i);
2233 print_hex_dump(KERN_DEBUG, "HDMI EDID: ", DUMP_PREFIX_NONE,
2234 16, 1, edid_ctrl->edid_buf + (i * EDID_BLOCK_SIZE),
2235 EDID_BLOCK_SIZE, false);
2236 }
2237
2238 edid_ctrl->cea_blks = num_of_cea_blocks;
2239
2240 hdmi_edid_get_display_mode(edid_ctrl);
2241
2242 if (edid_ctrl->keep_resv_timings)
2243 hdmi_edid_add_resv_timings(edid_ctrl);
2244
2245 return 0;
2246
2247err_invalid_header:
2248 edid_ctrl->sink_data.num_of_elements = 1;
2249 edid_ctrl->sink_data.disp_mode_list[0].video_format =
2250 edid_ctrl->video_resolution;
2251 edid_ctrl->sink_data.disp_mode_list[0].rgb_support = true;
2252err_invalid_data:
2253 return status;
2254} /* hdmi_edid_read */
2255
2256/*
2257 * If the sink specified support for both underscan/overscan then, by default,
2258 * set the underscan bit. Only checking underscan support for preferred
2259 * format and cea formats.
2260 */
2261u8 hdmi_edid_get_sink_scaninfo(void *input, u32 resolution)
2262{
2263 u8 scaninfo = 0;
2264 int use_ce_scan_info = true;
2265 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2266
2267 if (!edid_ctrl) {
2268 DEV_ERR("%s: invalid input\n", __func__);
2269 goto end;
2270 }
2271
2272 if (resolution == edid_ctrl->sink_data.preferred_video_format) {
2273 use_ce_scan_info = false;
2274 switch (edid_ctrl->pt_scan_info) {
2275 case 0:
2276 /*
2277 * Need to use the info specified for the corresponding
2278 * IT or CE format
2279 */
2280 DEV_DBG("%s: No underscan info for preferred V fmt\n",
2281 __func__);
2282 use_ce_scan_info = true;
2283 break;
2284 case 3:
2285 DEV_DBG("%s: Set underscan bit for preferred V fmt\n",
2286 __func__);
2287 scaninfo = BIT(1);
2288 break;
2289 default:
2290 DEV_DBG("%s: Underscan not set for preferred V fmt\n",
2291 __func__);
2292 break;
2293 }
2294 }
2295
2296 if (use_ce_scan_info) {
2297 if (edid_ctrl->ce_scan_info == 3) {
2298 DEV_DBG("%s: Setting underscan bit for CE video fmt\n",
2299 __func__);
2300 scaninfo |= BIT(1);
2301 } else {
2302 DEV_DBG("%s: Not setting underscan bit for CE V fmt\n",
2303 __func__);
2304 }
2305 }
2306
2307end:
2308 return scaninfo;
2309} /* hdmi_edid_get_sink_scaninfo */
2310
2311u32 hdmi_edid_get_sink_mode(void *input)
2312{
2313 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2314 bool sink_mode;
2315
2316 if (!edid_ctrl) {
2317 DEV_ERR("%s: invalid input\n", __func__);
2318 return 0;
2319 }
2320
2321 if (edid_ctrl->edid_override &&
2322 (edid_ctrl->override_data.sink_mode != -1))
2323 sink_mode = edid_ctrl->override_data.sink_mode;
2324 else
2325 sink_mode = edid_ctrl->sink_mode;
2326
2327 return sink_mode;
2328} /* hdmi_edid_get_sink_mode */
2329
2330bool hdmi_edid_is_s3d_mode_supported(void *input, u32 video_mode, u32 s3d_mode)
2331{
2332 int i;
2333 bool ret = false;
2334 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2335 struct hdmi_edid_sink_data *sink_data;
2336
2337 sink_data = &edid_ctrl->sink_data;
2338 for (i = 0; i < sink_data->num_of_elements; ++i) {
2339 if (sink_data->disp_mode_list[i].video_format != video_mode)
2340 continue;
2341 if (sink_data->disp_mode_list[i].video_3d_format &
2342 (1 << s3d_mode))
2343 ret = true;
2344 else
2345 DEV_DBG("%s: return false: vic=%d caps=%x s3d=%d\n",
2346 __func__, video_mode,
2347 sink_data->disp_mode_list[i].video_3d_format,
2348 s3d_mode);
2349 break;
2350 }
2351 return ret;
2352}
2353
2354bool hdmi_edid_get_scdc_support(void *input)
2355{
2356 struct hdmi_edid_ctrl *edid_ctrl = input;
2357 bool scdc_present;
2358
2359 if (!edid_ctrl) {
2360 DEV_ERR("%s: invalid input\n", __func__);
2361 return false;
2362 }
2363
2364 if (edid_ctrl->edid_override &&
2365 (edid_ctrl->override_data.scramble != -1))
2366 scdc_present = edid_ctrl->override_data.scramble;
2367 else
2368 scdc_present = edid_ctrl->sink_caps.scdc_present;
2369
2370 return scdc_present;
2371}
2372
2373/**
2374 * hdmi_edid_sink_scramble_override() - check if override has been enabled
2375 * @input: edid data
2376 *
2377 * Return true if scrambling override is enabled false otherwise.
2378 */
2379bool hdmi_edid_sink_scramble_override(void *input)
2380{
2381 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2382
2383 if (edid_ctrl->edid_override &&
2384 (edid_ctrl->override_data.scramble != -1))
2385 return true;
2386
2387 return false;
2388
2389}
2390
2391bool hdmi_edid_get_sink_scrambler_support(void *input)
2392{
2393 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2394 bool scramble_support;
2395
2396 if (!edid_ctrl) {
2397 DEV_ERR("%s: invalid input\n", __func__);
2398 return 0;
2399 }
2400
2401 if (edid_ctrl->edid_override &&
2402 (edid_ctrl->override_data.scramble != -1))
2403 scramble_support = edid_ctrl->override_data.scramble;
2404 else
2405 scramble_support = edid_ctrl->sink_caps.scramble_support;
2406
2407 return scramble_support;
2408}
2409
2410int hdmi_edid_get_audio_blk(void *input, struct msm_hdmi_audio_edid_blk *blk)
2411{
2412 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2413
2414 if (!edid_ctrl || !blk) {
2415 DEV_ERR("%s: invalid input\n", __func__);
2416 return -EINVAL;
2417 }
2418
2419 blk->audio_data_blk = edid_ctrl->audio_data_block;
2420 blk->audio_data_blk_size = edid_ctrl->adb_size;
2421
2422 blk->spk_alloc_data_blk = edid_ctrl->spkr_alloc_data_block;
2423 blk->spk_alloc_data_blk_size = edid_ctrl->sadb_size;
2424
2425 return 0;
2426} /* hdmi_edid_get_audio_blk */
2427
2428void hdmi_edid_set_video_resolution(void *input, u32 resolution, bool reset)
2429{
2430 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2431
2432 if (!edid_ctrl) {
2433 DEV_ERR("%s: invalid input\n", __func__);
2434 return;
2435 }
2436
2437 edid_ctrl->video_resolution = resolution;
2438
2439 if (reset) {
2440 edid_ctrl->default_vic = resolution;
2441 edid_ctrl->sink_data.num_of_elements = 1;
2442 edid_ctrl->sink_data.disp_mode_list[0].video_format =
2443 resolution;
2444 edid_ctrl->sink_data.disp_mode_list[0].rgb_support = true;
2445 }
2446} /* hdmi_edid_set_video_resolution */
2447
2448void hdmi_edid_deinit(void *input)
2449{
2450 struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
2451
2452 if (edid_ctrl) {
2453 if (edid_ctrl->init_data.kobj)
2454 sysfs_remove_group(edid_ctrl->init_data.kobj,
2455 &hdmi_edid_fs_attrs_group);
2456
2457 kfree(edid_ctrl);
2458 }
2459}
2460
2461void *hdmi_edid_init(struct hdmi_edid_init_data *idata)
2462{
2463 struct hdmi_edid_ctrl *edid_ctrl = NULL;
2464
2465 if (!idata) {
2466 DEV_ERR("%s: invalid input\n", __func__);
2467 goto error;
2468 }
2469
2470 edid_ctrl = kzalloc(sizeof(*edid_ctrl), GFP_KERNEL);
2471 if (!edid_ctrl)
2472 goto error;
2473
2474 edid_ctrl->init_data = *idata;
2475
2476 if (idata->kobj) {
2477 if (sysfs_create_group(idata->kobj,
2478 &hdmi_edid_fs_attrs_group))
2479 DEV_ERR("%s: EDID sysfs create failed\n",
2480 __func__);
2481 } else {
2482 DEV_DBG("%s: kobj not provided\n", __func__);
2483 }
2484
2485 /* provide edid buffer to the client */
2486 idata->buf = edid_ctrl->edid_buf;
2487 idata->buf_size = sizeof(edid_ctrl->edid_buf);
2488
2489 return (void *)edid_ctrl;
2490
2491error:
2492 kfree(edid_ctrl);
2493 return NULL;
2494}