diff options
Diffstat (limited to 'drivers/gpu/drm/drm_edid.c')
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index e2acfdbf7d3c..b6807e881a60 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -2511,6 +2511,65 @@ void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) | |||
2511 | EXPORT_SYMBOL(drm_edid_to_eld); | 2511 | EXPORT_SYMBOL(drm_edid_to_eld); |
2512 | 2512 | ||
2513 | /** | 2513 | /** |
2514 | * drm_edid_to_sad - extracts SADs from EDID | ||
2515 | * @edid: EDID to parse | ||
2516 | * @sads: pointer that will be set to the extracted SADs | ||
2517 | * | ||
2518 | * Looks for CEA EDID block and extracts SADs (Short Audio Descriptors) from it. | ||
2519 | * Note: returned pointer needs to be kfreed | ||
2520 | * | ||
2521 | * Return number of found SADs or negative number on error. | ||
2522 | */ | ||
2523 | int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads) | ||
2524 | { | ||
2525 | int count = 0; | ||
2526 | int i, start, end, dbl; | ||
2527 | u8 *cea; | ||
2528 | |||
2529 | cea = drm_find_cea_extension(edid); | ||
2530 | if (!cea) { | ||
2531 | DRM_DEBUG_KMS("SAD: no CEA Extension found\n"); | ||
2532 | return -ENOENT; | ||
2533 | } | ||
2534 | |||
2535 | if (cea_revision(cea) < 3) { | ||
2536 | DRM_DEBUG_KMS("SAD: wrong CEA revision\n"); | ||
2537 | return -ENOTSUPP; | ||
2538 | } | ||
2539 | |||
2540 | if (cea_db_offsets(cea, &start, &end)) { | ||
2541 | DRM_DEBUG_KMS("SAD: invalid data block offsets\n"); | ||
2542 | return -EPROTO; | ||
2543 | } | ||
2544 | |||
2545 | for_each_cea_db(cea, i, start, end) { | ||
2546 | u8 *db = &cea[i]; | ||
2547 | |||
2548 | if (cea_db_tag(db) == AUDIO_BLOCK) { | ||
2549 | int j; | ||
2550 | dbl = cea_db_payload_len(db); | ||
2551 | |||
2552 | count = dbl / 3; /* SAD is 3B */ | ||
2553 | *sads = kcalloc(count, sizeof(**sads), GFP_KERNEL); | ||
2554 | if (!*sads) | ||
2555 | return -ENOMEM; | ||
2556 | for (j = 0; j < count; j++) { | ||
2557 | u8 *sad = &db[1 + j * 3]; | ||
2558 | |||
2559 | (*sads)[j].format = (sad[0] & 0x78) >> 3; | ||
2560 | (*sads)[j].channels = sad[0] & 0x7; | ||
2561 | (*sads)[j].freq = sad[1] & 0x7F; | ||
2562 | (*sads)[j].byte2 = sad[2]; | ||
2563 | } | ||
2564 | break; | ||
2565 | } | ||
2566 | } | ||
2567 | |||
2568 | return count; | ||
2569 | } | ||
2570 | EXPORT_SYMBOL(drm_edid_to_sad); | ||
2571 | |||
2572 | /** | ||
2514 | * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond | 2573 | * drm_av_sync_delay - HDMI/DP sink audio-video sync delay in millisecond |
2515 | * @connector: connector associated with the HDMI/DP sink | 2574 | * @connector: connector associated with the HDMI/DP sink |
2516 | * @mode: the display mode | 2575 | * @mode: the display mode |