aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_edid.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r--drivers/gpu/drm/drm_edid.c314
1 files changed, 281 insertions, 33 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 830f7501cb4d..fb7cf0e796f6 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -458,6 +458,15 @@ static const struct drm_display_mode drm_dmt_modes[] = {
458 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) }, 458 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC) },
459}; 459};
460 460
461/*
462 * These more or less come from the DMT spec. The 720x400 modes are
463 * inferred from historical 80x25 practice. The 640x480@67 and 832x624@75
464 * modes are old-school Mac modes. The EDID spec says the 1152x864@75 mode
465 * should be 1152x870, again for the Mac, but instead we use the x864 DMT
466 * mode.
467 *
468 * The DMT modes have been fact-checked; the rest are mild guesses.
469 */
461static const struct drm_display_mode edid_est_modes[] = { 470static const struct drm_display_mode edid_est_modes[] = {
462 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840, 471 { DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
463 968, 1056, 0, 600, 601, 605, 628, 0, 472 968, 1056, 0, 600, 601, 605, 628, 0,
@@ -560,7 +569,7 @@ static const struct minimode est3_modes[] = {
560 { 1600, 1200, 75, 0 }, 569 { 1600, 1200, 75, 0 },
561 { 1600, 1200, 85, 0 }, 570 { 1600, 1200, 85, 0 },
562 { 1792, 1344, 60, 0 }, 571 { 1792, 1344, 60, 0 },
563 { 1792, 1344, 85, 0 }, 572 { 1792, 1344, 75, 0 },
564 { 1856, 1392, 60, 0 }, 573 { 1856, 1392, 60, 0 },
565 { 1856, 1392, 75, 0 }, 574 { 1856, 1392, 75, 0 },
566 { 1920, 1200, 60, 1 }, 575 { 1920, 1200, 60, 1 },
@@ -1264,6 +1273,18 @@ struct edid *drm_get_edid(struct drm_connector *connector,
1264} 1273}
1265EXPORT_SYMBOL(drm_get_edid); 1274EXPORT_SYMBOL(drm_get_edid);
1266 1275
1276/**
1277 * drm_edid_duplicate - duplicate an EDID and the extensions
1278 * @edid: EDID to duplicate
1279 *
1280 * Return duplicate edid or NULL on allocation failure.
1281 */
1282struct edid *drm_edid_duplicate(const struct edid *edid)
1283{
1284 return kmemdup(edid, (edid->extensions + 1) * EDID_LENGTH, GFP_KERNEL);
1285}
1286EXPORT_SYMBOL(drm_edid_duplicate);
1287
1267/*** EDID parsing ***/ 1288/*** EDID parsing ***/
1268 1289
1269/** 1290/**
@@ -1308,7 +1329,7 @@ static u32 edid_get_quirks(struct edid *edid)
1308} 1329}
1309 1330
1310#define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay) 1331#define MODE_SIZE(m) ((m)->hdisplay * (m)->vdisplay)
1311#define MODE_REFRESH_DIFF(m,r) (abs((m)->vrefresh - target_refresh)) 1332#define MODE_REFRESH_DIFF(c,t) (abs((c) - (t)))
1312 1333
1313/** 1334/**
1314 * edid_fixup_preferred - set preferred modes based on quirk list 1335 * edid_fixup_preferred - set preferred modes based on quirk list
@@ -1323,6 +1344,7 @@ static void edid_fixup_preferred(struct drm_connector *connector,
1323{ 1344{
1324 struct drm_display_mode *t, *cur_mode, *preferred_mode; 1345 struct drm_display_mode *t, *cur_mode, *preferred_mode;
1325 int target_refresh = 0; 1346 int target_refresh = 0;
1347 int cur_vrefresh, preferred_vrefresh;
1326 1348
1327 if (list_empty(&connector->probed_modes)) 1349 if (list_empty(&connector->probed_modes))
1328 return; 1350 return;
@@ -1345,10 +1367,14 @@ static void edid_fixup_preferred(struct drm_connector *connector,
1345 if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode)) 1367 if (MODE_SIZE(cur_mode) > MODE_SIZE(preferred_mode))
1346 preferred_mode = cur_mode; 1368 preferred_mode = cur_mode;
1347 1369
1370 cur_vrefresh = cur_mode->vrefresh ?
1371 cur_mode->vrefresh : drm_mode_vrefresh(cur_mode);
1372 preferred_vrefresh = preferred_mode->vrefresh ?
1373 preferred_mode->vrefresh : drm_mode_vrefresh(preferred_mode);
1348 /* At a given size, try to get closest to target refresh */ 1374 /* At a given size, try to get closest to target refresh */
1349 if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) && 1375 if ((MODE_SIZE(cur_mode) == MODE_SIZE(preferred_mode)) &&
1350 MODE_REFRESH_DIFF(cur_mode, target_refresh) < 1376 MODE_REFRESH_DIFF(cur_vrefresh, target_refresh) <
1351 MODE_REFRESH_DIFF(preferred_mode, target_refresh)) { 1377 MODE_REFRESH_DIFF(preferred_vrefresh, target_refresh)) {
1352 preferred_mode = cur_mode; 1378 preferred_mode = cur_mode;
1353 } 1379 }
1354 } 1380 }
@@ -2068,7 +2094,7 @@ drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing)
2068 u8 *est = ((u8 *)timing) + 5; 2094 u8 *est = ((u8 *)timing) + 5;
2069 2095
2070 for (i = 0; i < 6; i++) { 2096 for (i = 0; i < 6; i++) {
2071 for (j = 7; j > 0; j--) { 2097 for (j = 7; j >= 0; j--) {
2072 m = (i * 8) + (7 - j); 2098 m = (i * 8) + (7 - j);
2073 if (m >= ARRAY_SIZE(est3_modes)) 2099 if (m >= ARRAY_SIZE(est3_modes))
2074 break; 2100 break;
@@ -2404,7 +2430,7 @@ u8 drm_match_cea_mode(const struct drm_display_mode *to_match)
2404 2430
2405 if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) || 2431 if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
2406 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) && 2432 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
2407 drm_mode_equal_no_clocks(to_match, cea_mode)) 2433 drm_mode_equal_no_clocks_no_stereo(to_match, cea_mode))
2408 return mode + 1; 2434 return mode + 1;
2409 } 2435 }
2410 return 0; 2436 return 0;
@@ -2453,7 +2479,7 @@ static u8 drm_match_hdmi_mode(const struct drm_display_mode *to_match)
2453 2479
2454 if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) || 2480 if ((KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock1) ||
2455 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) && 2481 KHZ2PICOS(to_match->clock) == KHZ2PICOS(clock2)) &&
2456 drm_mode_equal_no_clocks(to_match, hdmi_mode)) 2482 drm_mode_equal_no_clocks_no_stereo(to_match, hdmi_mode))
2457 return mode + 1; 2483 return mode + 1;
2458 } 2484 }
2459 return 0; 2485 return 0;
@@ -2507,6 +2533,9 @@ add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid)
2507 if (!newmode) 2533 if (!newmode)
2508 continue; 2534 continue;
2509 2535
2536 /* Carry over the stereo flags */
2537 newmode->flags |= mode->flags & DRM_MODE_FLAG_3D_MASK;
2538
2510 /* 2539 /*
2511 * The current mode could be either variant. Make 2540 * The current mode could be either variant. Make
2512 * sure to pick the "other" clock for the new mode. 2541 * sure to pick the "other" clock for the new mode.
@@ -2553,20 +2582,151 @@ do_cea_modes(struct drm_connector *connector, const u8 *db, u8 len)
2553 return modes; 2582 return modes;
2554} 2583}
2555 2584
2585struct stereo_mandatory_mode {
2586 int width, height, vrefresh;
2587 unsigned int flags;
2588};
2589
2590static const struct stereo_mandatory_mode stereo_mandatory_modes[] = {
2591 { 1920, 1080, 24, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
2592 { 1920, 1080, 24, DRM_MODE_FLAG_3D_FRAME_PACKING },
2593 { 1920, 1080, 50,
2594 DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
2595 { 1920, 1080, 60,
2596 DRM_MODE_FLAG_INTERLACE | DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF },
2597 { 1280, 720, 50, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
2598 { 1280, 720, 50, DRM_MODE_FLAG_3D_FRAME_PACKING },
2599 { 1280, 720, 60, DRM_MODE_FLAG_3D_TOP_AND_BOTTOM },
2600 { 1280, 720, 60, DRM_MODE_FLAG_3D_FRAME_PACKING }
2601};
2602
2603static bool
2604stereo_match_mandatory(const struct drm_display_mode *mode,
2605 const struct stereo_mandatory_mode *stereo_mode)
2606{
2607 unsigned int interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE;
2608
2609 return mode->hdisplay == stereo_mode->width &&
2610 mode->vdisplay == stereo_mode->height &&
2611 interlaced == (stereo_mode->flags & DRM_MODE_FLAG_INTERLACE) &&
2612 drm_mode_vrefresh(mode) == stereo_mode->vrefresh;
2613}
2614
2615static int add_hdmi_mandatory_stereo_modes(struct drm_connector *connector)
2616{
2617 struct drm_device *dev = connector->dev;
2618 const struct drm_display_mode *mode;
2619 struct list_head stereo_modes;
2620 int modes = 0, i;
2621
2622 INIT_LIST_HEAD(&stereo_modes);
2623
2624 list_for_each_entry(mode, &connector->probed_modes, head) {
2625 for (i = 0; i < ARRAY_SIZE(stereo_mandatory_modes); i++) {
2626 const struct stereo_mandatory_mode *mandatory;
2627 struct drm_display_mode *new_mode;
2628
2629 if (!stereo_match_mandatory(mode,
2630 &stereo_mandatory_modes[i]))
2631 continue;
2632
2633 mandatory = &stereo_mandatory_modes[i];
2634 new_mode = drm_mode_duplicate(dev, mode);
2635 if (!new_mode)
2636 continue;
2637
2638 new_mode->flags |= mandatory->flags;
2639 list_add_tail(&new_mode->head, &stereo_modes);
2640 modes++;
2641 }
2642 }
2643
2644 list_splice_tail(&stereo_modes, &connector->probed_modes);
2645
2646 return modes;
2647}
2648
2649static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
2650{
2651 struct drm_device *dev = connector->dev;
2652 struct drm_display_mode *newmode;
2653
2654 vic--; /* VICs start at 1 */
2655 if (vic >= ARRAY_SIZE(edid_4k_modes)) {
2656 DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
2657 return 0;
2658 }
2659
2660 newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]);
2661 if (!newmode)
2662 return 0;
2663
2664 drm_mode_probed_add(connector, newmode);
2665
2666 return 1;
2667}
2668
2669static int add_3d_struct_modes(struct drm_connector *connector, u16 structure,
2670 const u8 *video_db, u8 video_len, u8 video_index)
2671{
2672 struct drm_device *dev = connector->dev;
2673 struct drm_display_mode *newmode;
2674 int modes = 0;
2675 u8 cea_mode;
2676
2677 if (video_db == NULL || video_index > video_len)
2678 return 0;
2679
2680 /* CEA modes are numbered 1..127 */
2681 cea_mode = (video_db[video_index] & 127) - 1;
2682 if (cea_mode >= ARRAY_SIZE(edid_cea_modes))
2683 return 0;
2684
2685 if (structure & (1 << 0)) {
2686 newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
2687 if (newmode) {
2688 newmode->flags |= DRM_MODE_FLAG_3D_FRAME_PACKING;
2689 drm_mode_probed_add(connector, newmode);
2690 modes++;
2691 }
2692 }
2693 if (structure & (1 << 6)) {
2694 newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
2695 if (newmode) {
2696 newmode->flags |= DRM_MODE_FLAG_3D_TOP_AND_BOTTOM;
2697 drm_mode_probed_add(connector, newmode);
2698 modes++;
2699 }
2700 }
2701 if (structure & (1 << 8)) {
2702 newmode = drm_mode_duplicate(dev, &edid_cea_modes[cea_mode]);
2703 if (newmode) {
2704 newmode->flags = DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF;
2705 drm_mode_probed_add(connector, newmode);
2706 modes++;
2707 }
2708 }
2709
2710 return modes;
2711}
2712
2556/* 2713/*
2557 * do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block 2714 * do_hdmi_vsdb_modes - Parse the HDMI Vendor Specific data block
2558 * @connector: connector corresponding to the HDMI sink 2715 * @connector: connector corresponding to the HDMI sink
2559 * @db: start of the CEA vendor specific block 2716 * @db: start of the CEA vendor specific block
2560 * @len: length of the CEA block payload, ie. one can access up to db[len] 2717 * @len: length of the CEA block payload, ie. one can access up to db[len]
2561 * 2718 *
2562 * Parses the HDMI VSDB looking for modes to add to @connector. 2719 * Parses the HDMI VSDB looking for modes to add to @connector. This function
2720 * also adds the stereo 3d modes when applicable.
2563 */ 2721 */
2564static int 2722static int
2565do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len) 2723do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len,
2724 const u8 *video_db, u8 video_len)
2566{ 2725{
2567 struct drm_device *dev = connector->dev; 2726 int modes = 0, offset = 0, i, multi_present = 0;
2568 int modes = 0, offset = 0, i; 2727 u8 vic_len, hdmi_3d_len = 0;
2569 u8 vic_len; 2728 u16 mask;
2729 u16 structure_all;
2570 2730
2571 if (len < 8) 2731 if (len < 8)
2572 goto out; 2732 goto out;
@@ -2585,30 +2745,56 @@ do_hdmi_vsdb_modes(struct drm_connector *connector, const u8 *db, u8 len)
2585 2745
2586 /* the declared length is not long enough for the 2 first bytes 2746 /* the declared length is not long enough for the 2 first bytes
2587 * of additional video format capabilities */ 2747 * of additional video format capabilities */
2588 offset += 2; 2748 if (len < (8 + offset + 2))
2589 if (len < (8 + offset))
2590 goto out; 2749 goto out;
2591 2750
2751 /* 3D_Present */
2752 offset++;
2753 if (db[8 + offset] & (1 << 7)) {
2754 modes += add_hdmi_mandatory_stereo_modes(connector);
2755
2756 /* 3D_Multi_present */
2757 multi_present = (db[8 + offset] & 0x60) >> 5;
2758 }
2759
2760 offset++;
2592 vic_len = db[8 + offset] >> 5; 2761 vic_len = db[8 + offset] >> 5;
2762 hdmi_3d_len = db[8 + offset] & 0x1f;
2593 2763
2594 for (i = 0; i < vic_len && len >= (9 + offset + i); i++) { 2764 for (i = 0; i < vic_len && len >= (9 + offset + i); i++) {
2595 struct drm_display_mode *newmode;
2596 u8 vic; 2765 u8 vic;
2597 2766
2598 vic = db[9 + offset + i]; 2767 vic = db[9 + offset + i];
2768 modes += add_hdmi_mode(connector, vic);
2769 }
2770 offset += 1 + vic_len;
2599 2771
2600 vic--; /* VICs start at 1 */ 2772 if (!(multi_present == 1 || multi_present == 2))
2601 if (vic >= ARRAY_SIZE(edid_4k_modes)) { 2773 goto out;
2602 DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
2603 continue;
2604 }
2605 2774
2606 newmode = drm_mode_duplicate(dev, &edid_4k_modes[vic]); 2775 if ((multi_present == 1 && len < (9 + offset)) ||
2607 if (!newmode) 2776 (multi_present == 2 && len < (11 + offset)))
2608 continue; 2777 goto out;
2609 2778
2610 drm_mode_probed_add(connector, newmode); 2779 if ((multi_present == 1 && hdmi_3d_len < 2) ||
2611 modes++; 2780 (multi_present == 2 && hdmi_3d_len < 4))
2781 goto out;
2782
2783 /* 3D_Structure_ALL */
2784 structure_all = (db[8 + offset] << 8) | db[9 + offset];
2785
2786 /* check if 3D_MASK is present */
2787 if (multi_present == 2)
2788 mask = (db[10 + offset] << 8) | db[11 + offset];
2789 else
2790 mask = 0xffff;
2791
2792 for (i = 0; i < 16; i++) {
2793 if (mask & (1 << i))
2794 modes += add_3d_struct_modes(connector,
2795 structure_all,
2796 video_db,
2797 video_len, i);
2612 } 2798 }
2613 2799
2614out: 2800out:
@@ -2668,8 +2854,8 @@ static int
2668add_cea_modes(struct drm_connector *connector, struct edid *edid) 2854add_cea_modes(struct drm_connector *connector, struct edid *edid)
2669{ 2855{
2670 const u8 *cea = drm_find_cea_extension(edid); 2856 const u8 *cea = drm_find_cea_extension(edid);
2671 const u8 *db; 2857 const u8 *db, *hdmi = NULL, *video = NULL;
2672 u8 dbl; 2858 u8 dbl, hdmi_len, video_len = 0;
2673 int modes = 0; 2859 int modes = 0;
2674 2860
2675 if (cea && cea_revision(cea) >= 3) { 2861 if (cea && cea_revision(cea) >= 3) {
@@ -2682,13 +2868,26 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
2682 db = &cea[i]; 2868 db = &cea[i];
2683 dbl = cea_db_payload_len(db); 2869 dbl = cea_db_payload_len(db);
2684 2870
2685 if (cea_db_tag(db) == VIDEO_BLOCK) 2871 if (cea_db_tag(db) == VIDEO_BLOCK) {
2686 modes += do_cea_modes(connector, db + 1, dbl); 2872 video = db + 1;
2687 else if (cea_db_is_hdmi_vsdb(db)) 2873 video_len = dbl;
2688 modes += do_hdmi_vsdb_modes(connector, db, dbl); 2874 modes += do_cea_modes(connector, video, dbl);
2875 }
2876 else if (cea_db_is_hdmi_vsdb(db)) {
2877 hdmi = db;
2878 hdmi_len = dbl;
2879 }
2689 } 2880 }
2690 } 2881 }
2691 2882
2883 /*
2884 * We parse the HDMI VSDB after having added the cea modes as we will
2885 * be patching their flags when the sink supports stereo 3D.
2886 */
2887 if (hdmi)
2888 modes += do_hdmi_vsdb_modes(connector, hdmi, hdmi_len, video,
2889 video_len);
2890
2692 return modes; 2891 return modes;
2693} 2892}
2694 2893
@@ -3288,6 +3487,19 @@ int drm_add_modes_noedid(struct drm_connector *connector,
3288} 3487}
3289EXPORT_SYMBOL(drm_add_modes_noedid); 3488EXPORT_SYMBOL(drm_add_modes_noedid);
3290 3489
3490void drm_set_preferred_mode(struct drm_connector *connector,
3491 int hpref, int vpref)
3492{
3493 struct drm_display_mode *mode;
3494
3495 list_for_each_entry(mode, &connector->probed_modes, head) {
3496 if (drm_mode_width(mode) == hpref &&
3497 drm_mode_height(mode) == vpref)
3498 mode->type |= DRM_MODE_TYPE_PREFERRED;
3499 }
3500}
3501EXPORT_SYMBOL(drm_set_preferred_mode);
3502
3291/** 3503/**
3292 * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with 3504 * drm_hdmi_avi_infoframe_from_display_mode() - fill an HDMI AVI infoframe with
3293 * data from a DRM display mode 3505 * data from a DRM display mode
@@ -3321,6 +3533,33 @@ drm_hdmi_avi_infoframe_from_display_mode(struct hdmi_avi_infoframe *frame,
3321} 3533}
3322EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode); 3534EXPORT_SYMBOL(drm_hdmi_avi_infoframe_from_display_mode);
3323 3535
3536static enum hdmi_3d_structure
3537s3d_structure_from_display_mode(const struct drm_display_mode *mode)
3538{
3539 u32 layout = mode->flags & DRM_MODE_FLAG_3D_MASK;
3540
3541 switch (layout) {
3542 case DRM_MODE_FLAG_3D_FRAME_PACKING:
3543 return HDMI_3D_STRUCTURE_FRAME_PACKING;
3544 case DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE:
3545 return HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE;
3546 case DRM_MODE_FLAG_3D_LINE_ALTERNATIVE:
3547 return HDMI_3D_STRUCTURE_LINE_ALTERNATIVE;
3548 case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL:
3549 return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL;
3550 case DRM_MODE_FLAG_3D_L_DEPTH:
3551 return HDMI_3D_STRUCTURE_L_DEPTH;
3552 case DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH:
3553 return HDMI_3D_STRUCTURE_L_DEPTH_GFX_GFX_DEPTH;
3554 case DRM_MODE_FLAG_3D_TOP_AND_BOTTOM:
3555 return HDMI_3D_STRUCTURE_TOP_AND_BOTTOM;
3556 case DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF:
3557 return HDMI_3D_STRUCTURE_SIDE_BY_SIDE_HALF;
3558 default:
3559 return HDMI_3D_STRUCTURE_INVALID;
3560 }
3561}
3562
3324/** 3563/**
3325 * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with 3564 * drm_hdmi_vendor_infoframe_from_display_mode() - fill an HDMI infoframe with
3326 * data from a DRM display mode 3565 * data from a DRM display mode
@@ -3338,20 +3577,29 @@ drm_hdmi_vendor_infoframe_from_display_mode(struct hdmi_vendor_infoframe *frame,
3338 const struct drm_display_mode *mode) 3577 const struct drm_display_mode *mode)
3339{ 3578{
3340 int err; 3579 int err;
3580 u32 s3d_flags;
3341 u8 vic; 3581 u8 vic;
3342 3582
3343 if (!frame || !mode) 3583 if (!frame || !mode)
3344 return -EINVAL; 3584 return -EINVAL;
3345 3585
3346 vic = drm_match_hdmi_mode(mode); 3586 vic = drm_match_hdmi_mode(mode);
3347 if (!vic) 3587 s3d_flags = mode->flags & DRM_MODE_FLAG_3D_MASK;
3588
3589 if (!vic && !s3d_flags)
3590 return -EINVAL;
3591
3592 if (vic && s3d_flags)
3348 return -EINVAL; 3593 return -EINVAL;
3349 3594
3350 err = hdmi_vendor_infoframe_init(frame); 3595 err = hdmi_vendor_infoframe_init(frame);
3351 if (err < 0) 3596 if (err < 0)
3352 return err; 3597 return err;
3353 3598
3354 frame->vic = vic; 3599 if (vic)
3600 frame->vic = vic;
3601 else
3602 frame->s3d_struct = s3d_structure_from_display_mode(mode);
3355 3603
3356 return 0; 3604 return 0;
3357} 3605}