199100Siedowse// SPDX-License-Identifier: GPL-2.0-only OR MIT 299100Siedowse/* Copyright 2021 Alyssa Rosenzweig <alyssa@rosenzweig.io> */ 3319182Sngie 499100Siedowse#include <linux/kernel.h> 599100Siedowse#include <linux/err.h> 6219804Skib#include <linux/math.h> 7116754Siedowse#include <linux/string.h> 8163851Spjd#include <linux/slab.h> 9267226Skib 10267226Skib#include <sound/pcm.h> // for sound format masks 11267226Skib 1299100Siedowse#include "parser.h" 13165450Syar#include "trace.h" 1499100Siedowse 15165450Syar#define DCP_PARSE_HEADER 0xd3 1699100Siedowse 1799100Siedowseenum dcp_parse_type { 18 DCP_TYPE_DICTIONARY = 1, 19 DCP_TYPE_ARRAY = 2, 20 DCP_TYPE_INT64 = 4, 21 DCP_TYPE_STRING = 9, 22 DCP_TYPE_BLOB = 10, 23 DCP_TYPE_BOOL = 11 24}; 25 26struct dcp_parse_tag { 27 unsigned int size : 24; 28 enum dcp_parse_type type : 5; 29 unsigned int padding : 2; 30 bool last : 1; 31} __packed; 32 33static const void *parse_bytes(struct dcp_parse_ctx *ctx, size_t count) 34{ 35 const void *ptr = ctx->blob + ctx->pos; 36 37 if (ctx->pos + count > ctx->len) 38 return ERR_PTR(-EINVAL); 39 40 ctx->pos += count; 41 return ptr; 42} 43 44static const u32 *parse_u32(struct dcp_parse_ctx *ctx) 45{ 46 return parse_bytes(ctx, sizeof(u32)); 47} 48 49static const struct dcp_parse_tag *parse_tag(struct dcp_parse_ctx *ctx) 50{ 51 const struct dcp_parse_tag *tag; 52 53 /* Align to 32-bits */ 54 ctx->pos = round_up(ctx->pos, 4); 55 56 tag = parse_bytes(ctx, sizeof(struct dcp_parse_tag)); 57 58 if (IS_ERR(tag)) 59 return tag; 60 61 if (tag->padding) 62 return ERR_PTR(-EINVAL); 63 64 return tag; 65} 66 67static const struct dcp_parse_tag *parse_tag_of_type(struct dcp_parse_ctx *ctx, 68 enum dcp_parse_type type) 69{ 70 const struct dcp_parse_tag *tag = parse_tag(ctx); 71 72 if (IS_ERR(tag)) 73 return tag; 74 75 if (tag->type != type) 76 return ERR_PTR(-EINVAL); 77 78 return tag; 79} 80 81static int skip(struct dcp_parse_ctx *handle) 82{ 83 const struct dcp_parse_tag *tag = parse_tag(handle); 84 int ret = 0; 85 int i; 86 87 if (IS_ERR(tag)) 88 return PTR_ERR(tag); 89 90 switch (tag->type) { 91 case DCP_TYPE_DICTIONARY: 92 for (i = 0; i < tag->size; ++i) { 93 ret |= skip(handle); /* key */ 94 ret |= skip(handle); /* value */ 95 } 96 97 return ret; 98 99 case DCP_TYPE_ARRAY: 100 for (i = 0; i < tag->size; ++i) 101 ret |= skip(handle); 102 103 return ret; 104 105 case DCP_TYPE_INT64: 106 handle->pos += sizeof(s64); 107 return 0; 108 109 case DCP_TYPE_STRING: 110 case DCP_TYPE_BLOB: 111 handle->pos += tag->size; 112 return 0; 113 114 case DCP_TYPE_BOOL: 115 return 0; 116 117 default: 118 return -EINVAL; 119 } 120} 121 122static int skip_pair(struct dcp_parse_ctx *handle) 123{ 124 int ret; 125 126 ret = skip(handle); 127 if (ret) 128 return ret; 129 130 return skip(handle); 131} 132 133static bool consume_string(struct dcp_parse_ctx *ctx, const char *specimen) 134{ 135 const struct dcp_parse_tag *tag; 136 const char *key; 137 ctx->pos = round_up(ctx->pos, 4); 138 139 if (ctx->pos + sizeof(*tag) + strlen(specimen) - 1 > ctx->len) 140 return false; 141 tag = ctx->blob + ctx->pos; 142 key = ctx->blob + ctx->pos + sizeof(*tag); 143 if (tag->padding) 144 return false; 145 146 if (tag->type != DCP_TYPE_STRING || 147 tag->size != strlen(specimen) || 148 strncmp(key, specimen, tag->size)) 149 return false; 150 151 skip(ctx); 152 return true; 153} 154 155/* Caller must free the result */ 156static char *parse_string(struct dcp_parse_ctx *handle) 157{ 158 const struct dcp_parse_tag *tag = parse_tag_of_type(handle, DCP_TYPE_STRING); 159 const char *in; 160 char *out; 161 162 if (IS_ERR(tag)) 163 return (void *)tag; 164 165 in = parse_bytes(handle, tag->size); 166 if (IS_ERR(in)) 167 return (void *)in; 168 169 out = kmalloc(tag->size + 1, GFP_KERNEL); 170 171 memcpy(out, in, tag->size); 172 out[tag->size] = '\0'; 173 return out; 174} 175 176static int parse_int(struct dcp_parse_ctx *handle, s64 *value) 177{ 178 const void *tag = parse_tag_of_type(handle, DCP_TYPE_INT64); 179 const s64 *in; 180 181 if (IS_ERR(tag)) 182 return PTR_ERR(tag); 183 184 in = parse_bytes(handle, sizeof(s64)); 185 186 if (IS_ERR(in)) 187 return PTR_ERR(in); 188 189 memcpy(value, in, sizeof(*value)); 190 return 0; 191} 192 193static int parse_bool(struct dcp_parse_ctx *handle, bool *b) 194{ 195 const struct dcp_parse_tag *tag = parse_tag_of_type(handle, DCP_TYPE_BOOL); 196 197 if (IS_ERR(tag)) 198 return PTR_ERR(tag); 199 200 *b = !!tag->size; 201 return 0; 202} 203 204static int parse_blob(struct dcp_parse_ctx *handle, size_t size, u8 const **blob) 205{ 206 const struct dcp_parse_tag *tag = parse_tag_of_type(handle, DCP_TYPE_BLOB); 207 const u8 *out; 208 209 if (IS_ERR(tag)) 210 return PTR_ERR(tag); 211 212 if (tag->size < size) 213 return -EINVAL; 214 215 out = parse_bytes(handle, tag->size); 216 217 if (IS_ERR(out)) 218 return PTR_ERR(out); 219 220 *blob = out; 221 return 0; 222} 223 224struct iterator { 225 struct dcp_parse_ctx *handle; 226 u32 idx, len; 227}; 228 229static int iterator_begin(struct dcp_parse_ctx *handle, struct iterator *it, 230 bool dict) 231{ 232 const struct dcp_parse_tag *tag; 233 enum dcp_parse_type type = dict ? DCP_TYPE_DICTIONARY : DCP_TYPE_ARRAY; 234 235 *it = (struct iterator) { 236 .handle = handle, 237 .idx = 0 238 }; 239 240 tag = parse_tag_of_type(it->handle, type); 241 if (IS_ERR(tag)) 242 return PTR_ERR(tag); 243 244 it->len = tag->size; 245 return 0; 246} 247 248#define dcp_parse_foreach_in_array(handle, it) \ 249 for (iterator_begin(handle, &it, false); it.idx < it.len; ++it.idx) 250#define dcp_parse_foreach_in_dict(handle, it) \ 251 for (iterator_begin(handle, &it, true); it.idx < it.len; ++it.idx) 252 253int parse(const void *blob, size_t size, struct dcp_parse_ctx *ctx) 254{ 255 const u32 *header; 256 257 *ctx = (struct dcp_parse_ctx) { 258 .blob = blob, 259 .len = size, 260 .pos = 0, 261 }; 262 263 header = parse_u32(ctx); 264 if (IS_ERR(header)) 265 return PTR_ERR(header); 266 267 if (*header != DCP_PARSE_HEADER) 268 return -EINVAL; 269 270 return 0; 271} 272 273static int parse_dimension(struct dcp_parse_ctx *handle, struct dimension *dim) 274{ 275 struct iterator it; 276 int ret = 0; 277 278 dcp_parse_foreach_in_dict(handle, it) { 279 char *key = parse_string(it.handle); 280 281 if (IS_ERR(key)) 282 ret = PTR_ERR(key); 283 else if (!strcmp(key, "Active")) 284 ret = parse_int(it.handle, &dim->active); 285 else if (!strcmp(key, "Total")) 286 ret = parse_int(it.handle, &dim->total); 287 else if (!strcmp(key, "FrontPorch")) 288 ret = parse_int(it.handle, &dim->front_porch); 289 else if (!strcmp(key, "SyncWidth")) 290 ret = parse_int(it.handle, &dim->sync_width); 291 else if (!strcmp(key, "PreciseSyncRate")) 292 ret = parse_int(it.handle, &dim->precise_sync_rate); 293 else 294 skip(it.handle); 295 296 if (!IS_ERR_OR_NULL(key)) 297 kfree(key); 298 299 if (ret) 300 return ret; 301 } 302 303 return 0; 304} 305 306struct color_mode { 307 s64 colorimetry; 308 s64 depth; 309 s64 dynamic_range; 310 s64 eotf; 311 s64 id; 312 s64 pixel_encoding; 313 s64 score; 314}; 315 316static int fill_color_mode(struct dcp_color_mode *color, 317 struct color_mode *cmode) 318{ 319 if (color->score >= cmode->score) 320 return 0; 321 322 if (cmode->colorimetry < 0 || cmode->colorimetry >= DCP_COLORIMETRY_COUNT) 323 return -EINVAL; 324 if (cmode->depth < 8 || cmode->depth > 12) 325 return -EINVAL; 326 if (cmode->dynamic_range < 0 || cmode->dynamic_range >= DCP_COLOR_YCBCR_RANGE_COUNT) 327 return -EINVAL; 328 if (cmode->eotf < 0 || cmode->eotf >= DCP_EOTF_COUNT) 329 return -EINVAL; 330 if (cmode->pixel_encoding < 0 || cmode->pixel_encoding >= DCP_COLOR_FORMAT_COUNT) 331 return -EINVAL; 332 333 color->score = cmode->score; 334 color->id = cmode->id; 335 color->eotf = cmode->eotf; 336 color->format = cmode->pixel_encoding; 337 color->colorimetry = cmode->colorimetry; 338 color->range = cmode->dynamic_range; 339 color->depth = cmode->depth; 340 341 return 0; 342} 343 344static int parse_color_modes(struct dcp_parse_ctx *handle, 345 struct dcp_display_mode *out) 346{ 347 struct iterator outer_it; 348 int ret = 0; 349 out->sdr_444.score = -1; 350 out->sdr_rgb.score = -1; 351 out->best.score = -1; 352 353 dcp_parse_foreach_in_array(handle, outer_it) { 354 struct iterator it; 355 bool is_virtual = true; 356 struct color_mode cmode; 357 358 dcp_parse_foreach_in_dict(handle, it) { 359 char *key = parse_string(it.handle); 360 361 if (IS_ERR(key)) 362 ret = PTR_ERR(key); 363 else if (!strcmp(key, "Colorimetry")) 364 ret = parse_int(it.handle, &cmode.colorimetry); 365 else if (!strcmp(key, "Depth")) 366 ret = parse_int(it.handle, &cmode.depth); 367 else if (!strcmp(key, "DynamicRange")) 368 ret = parse_int(it.handle, &cmode.dynamic_range); 369 else if (!strcmp(key, "EOTF")) 370 ret = parse_int(it.handle, &cmode.eotf); 371 else if (!strcmp(key, "ID")) 372 ret = parse_int(it.handle, &cmode.id); 373 else if (!strcmp(key, "IsVirtual")) 374 ret = parse_bool(it.handle, &is_virtual); 375 else if (!strcmp(key, "PixelEncoding")) 376 ret = parse_int(it.handle, &cmode.pixel_encoding); 377 else if (!strcmp(key, "Score")) 378 ret = parse_int(it.handle, &cmode.score); 379 else 380 skip(it.handle); 381 382 if (!IS_ERR_OR_NULL(key)) 383 kfree(key); 384 385 if (ret) 386 return ret; 387 } 388 389 /* Skip virtual or partial entries */ 390 if (is_virtual || cmode.score < 0 || cmode.id < 0) 391 continue; 392 393 trace_iomfb_color_mode(handle->dcp, cmode.id, cmode.score, 394 cmode.depth, cmode.colorimetry, 395 cmode.eotf, cmode.dynamic_range, 396 cmode.pixel_encoding); 397 398 if (cmode.eotf == DCP_EOTF_SDR_GAMMA) { 399 if (cmode.pixel_encoding == DCP_COLOR_FORMAT_RGB && 400 cmode.depth <= 10) 401 fill_color_mode(&out->sdr_rgb, &cmode); 402 else if (cmode.pixel_encoding == DCP_COLOR_FORMAT_YCBCR444 && 403 cmode.depth <= 10) 404 fill_color_mode(&out->sdr_444, &cmode); 405 fill_color_mode(&out->sdr, &cmode); 406 } 407 fill_color_mode(&out->best, &cmode); 408 } 409 410 return 0; 411} 412 413/* 414 * Calculate the pixel clock for a mode given the 16:16 fixed-point refresh 415 * rate. The pixel clock is the refresh rate times the pixel count. DRM 416 * specifies the clock in kHz. The intermediate result may overflow a u32, so 417 * use a u64 where required. 418 */ 419static u32 calculate_clock(struct dimension *horiz, struct dimension *vert) 420{ 421 u32 pixels = horiz->total * vert->total; 422 u64 clock = mul_u32_u32(pixels, vert->precise_sync_rate); 423 424 return DIV_ROUND_CLOSEST_ULL(clock >> 16, 1000); 425} 426 427static int parse_mode(struct dcp_parse_ctx *handle, 428 struct dcp_display_mode *out, s64 *score, int width_mm, 429 int height_mm, unsigned notch_height) 430{ 431 int ret = 0; 432 struct iterator it; 433 struct dimension horiz, vert; 434 s64 id = -1; 435 s64 best_color_mode = -1; 436 bool is_virtual = false; 437 struct drm_display_mode *mode = &out->mode; 438 439 dcp_parse_foreach_in_dict(handle, it) { 440 char *key = parse_string(it.handle); 441 442 if (IS_ERR(key)) 443 ret = PTR_ERR(key); 444 else if (is_virtual) 445 skip(it.handle); 446 else if (!strcmp(key, "HorizontalAttributes")) 447 ret = parse_dimension(it.handle, &horiz); 448 else if (!strcmp(key, "VerticalAttributes")) 449 ret = parse_dimension(it.handle, &vert); 450 else if (!strcmp(key, "ColorModes")) 451 ret = parse_color_modes(it.handle, out); 452 else if (!strcmp(key, "ID")) 453 ret = parse_int(it.handle, &id); 454 else if (!strcmp(key, "IsVirtual")) 455 ret = parse_bool(it.handle, &is_virtual); 456 else if (!strcmp(key, "Score")) 457 ret = parse_int(it.handle, score); 458 else 459 skip(it.handle); 460 461 if (!IS_ERR_OR_NULL(key)) 462 kfree(key); 463 464 if (ret) { 465 trace_iomfb_parse_mode_fail(id, &horiz, &vert, best_color_mode, is_virtual, *score); 466 return ret; 467 } 468 } 469 if (out->sdr_rgb.score >= 0) 470 best_color_mode = out->sdr_rgb.id; 471 else if (out->sdr_444.score >= 0) 472 best_color_mode = out->sdr_444.id; 473 else if (out->sdr.score >= 0) 474 best_color_mode = out->sdr.id; 475 else if (out->best.score >= 0) 476 best_color_mode = out->best.id; 477 478 trace_iomfb_parse_mode_success(id, &horiz, &vert, best_color_mode, 479 is_virtual, *score); 480 481 /* 482 * Reject modes without valid color mode. 483 */ 484 if (best_color_mode < 0) 485 return -EINVAL; 486 487 /* 488 * We need to skip virtual modes. In some cases, virtual modes are "too 489 * big" for the monitor and can cause breakage. It is unclear why the 490 * DCP reports these modes at all. Treat as a recoverable error. 491 */ 492 if (is_virtual) 493 return -EINVAL; 494 495 /* 496 * HACK: 497 * Ignore the 120 Hz mode on j314/j316 (identified by resolution). 498 * DCP limits normal swaps to 60 Hz anyway and the 120 Hz mode might 499 * cause choppiness with X11. 500 * Just downscoring it and thus making the 60 Hz mode the preferred mode 501 * seems not enough for some user space. 502 */ 503 if (vert.precise_sync_rate >> 16 == 120 && 504 ((horiz.active == 3024 && vert.active == 1964) || 505 (horiz.active == 3456 && vert.active == 2234))) 506 return -EINVAL; 507 508 /* 509 * HACK: reject refresh modes with a pixel clock above 926484,480 kHz 510 * (bandwidth limit reported by dcp). This allows 4k 100Hz and 511 * 5k 60Hz but not much beyond. 512 * DSC setup seems to require additional steps 513 */ 514 if (calculate_clock(&horiz, &vert) > 926484) { 515 pr_info("dcp: rejecting mode %lldx%lld@%lld.%03lld (pixel clk:%d)\n", 516 horiz.active, vert.active, vert.precise_sync_rate >> 16, 517 ((1000 * vert.precise_sync_rate) >> 16) % 1000, 518 calculate_clock(&horiz, &vert)); 519 return -EINVAL; 520 } 521 522 vert.active -= notch_height; 523 vert.sync_width += notch_height; 524 525 /* From here we must succeed. Start filling out the mode. */ 526 *mode = (struct drm_display_mode) { 527 .type = DRM_MODE_TYPE_DRIVER, 528 .clock = calculate_clock(&horiz, &vert), 529 530 .vdisplay = vert.active, 531 .vsync_start = vert.active + vert.front_porch, 532 .vsync_end = vert.active + vert.front_porch + vert.sync_width, 533 .vtotal = vert.total, 534 535 .hdisplay = horiz.active, 536 .hsync_start = horiz.active + horiz.front_porch, 537 .hsync_end = horiz.active + horiz.front_porch + 538 horiz.sync_width, 539 .htotal = horiz.total, 540 541 .width_mm = width_mm, 542 .height_mm = height_mm, 543 }; 544 545 drm_mode_set_name(mode); 546 547 out->timing_mode_id = id; 548 out->color_mode_id = best_color_mode; 549 550 trace_iomfb_timing_mode(handle->dcp, id, *score, horiz.active, 551 vert.active, vert.precise_sync_rate, 552 best_color_mode); 553 554 return 0; 555} 556 557struct dcp_display_mode *enumerate_modes(struct dcp_parse_ctx *handle, 558 unsigned int *count, int width_mm, 559 int height_mm, unsigned notch_height) 560{ 561 struct iterator it; 562 int ret; 563 struct dcp_display_mode *mode, *modes; 564 struct dcp_display_mode *best_mode = NULL; 565 s64 score, best_score = -1; 566 567 ret = iterator_begin(handle, &it, false); 568 569 if (ret) 570 return ERR_PTR(ret); 571 572 /* Start with a worst case allocation */ 573 modes = kmalloc_array(it.len, sizeof(*modes), GFP_KERNEL); 574 *count = 0; 575 576 if (!modes) 577 return ERR_PTR(-ENOMEM); 578 579 for (; it.idx < it.len; ++it.idx) { 580 mode = &modes[*count]; 581 ret = parse_mode(it.handle, mode, &score, width_mm, height_mm, notch_height); 582 583 /* Errors for a single mode are recoverable -- just skip it. */ 584 if (ret) 585 continue; 586 587 /* Process a successful mode */ 588 (*count)++; 589 590 if (score > best_score) { 591 best_score = score; 592 best_mode = mode; 593 } 594 } 595 596 if (best_mode != NULL) 597 best_mode->mode.type |= DRM_MODE_TYPE_PREFERRED; 598 599 return modes; 600} 601 602int parse_display_attributes(struct dcp_parse_ctx *handle, int *width_mm, 603 int *height_mm) 604{ 605 int ret = 0; 606 struct iterator it; 607 s64 width_cm = 0, height_cm = 0; 608 609 dcp_parse_foreach_in_dict(handle, it) { 610 char *key = parse_string(it.handle); 611 612 if (IS_ERR(key)) 613 ret = PTR_ERR(key); 614 else if (!strcmp(key, "MaxHorizontalImageSize")) 615 ret = parse_int(it.handle, &width_cm); 616 else if (!strcmp(key, "MaxVerticalImageSize")) 617 ret = parse_int(it.handle, &height_cm); 618 else 619 skip(it.handle); 620 621 if (!IS_ERR_OR_NULL(key)) 622 kfree(key); 623 624 if (ret) 625 return ret; 626 } 627 628 /* 1cm = 10mm */ 629 *width_mm = 10 * width_cm; 630 *height_mm = 10 * height_cm; 631 632 return 0; 633} 634 635int parse_epic_service_init(struct dcp_parse_ctx *handle, const char **name, 636 const char **class, s64 *unit) 637{ 638 int ret = 0; 639 struct iterator it; 640 bool parsed_unit = false; 641 bool parsed_name = false; 642 bool parsed_class = false; 643 644 *name = ERR_PTR(-ENOENT); 645 *class = ERR_PTR(-ENOENT); 646 647 dcp_parse_foreach_in_dict(handle, it) { 648 char *key = parse_string(it.handle); 649 650 if (IS_ERR(key)) { 651 ret = PTR_ERR(key); 652 break; 653 } 654 655 if (!strcmp(key, "EPICName")) { 656 *name = parse_string(it.handle); 657 if (IS_ERR(*name)) 658 ret = PTR_ERR(*name); 659 else 660 parsed_name = true; 661 } else if (!strcmp(key, "EPICProviderClass")) { 662 *class = parse_string(it.handle); 663 if (IS_ERR(*class)) 664 ret = PTR_ERR(*class); 665 else 666 parsed_class = true; 667 } else if (!strcmp(key, "EPICUnit")) { 668 ret = parse_int(it.handle, unit); 669 if (!ret) 670 parsed_unit = true; 671 } else { 672 skip(it.handle); 673 } 674 675 kfree(key); 676 if (ret) 677 break; 678 } 679 680 if (!parsed_unit || !parsed_name || !parsed_class) 681 ret = -ENOENT; 682 683 if (ret) { 684 if (!IS_ERR(*name)) { 685 kfree(*name); 686 *name = ERR_PTR(ret); 687 } 688 if (!IS_ERR(*class)) { 689 kfree(*class); 690 *class = ERR_PTR(ret); 691 } 692 } 693 694 return ret; 695} 696 697static int parse_sample_rate_bit(struct dcp_parse_ctx *handle, unsigned int *ratebit) 698{ 699 s64 rate; 700 int ret = parse_int(handle, &rate); 701 702 if (ret) 703 return ret; 704 705 *ratebit = snd_pcm_rate_to_rate_bit(rate); 706 if (*ratebit == SNDRV_PCM_RATE_KNOT) { 707 /* 708 * The rate wasn't recognized, and unless we supply 709 * a supplementary constraint, the SNDRV_PCM_RATE_KNOT bit 710 * will allow any rate. So clear it. 711 */ 712 *ratebit = 0; 713 } 714 715 return 0; 716} 717 718static int parse_sample_fmtbit(struct dcp_parse_ctx *handle, u64 *fmtbit) 719{ 720 s64 sample_size; 721 int ret = parse_int(handle, &sample_size); 722 723 if (ret) 724 return ret; 725 726 switch (sample_size) { 727 case 16: 728 *fmtbit = SNDRV_PCM_FMTBIT_S16; 729 break; 730 case 20: 731 *fmtbit = SNDRV_PCM_FMTBIT_S20; 732 break; 733 case 24: 734 *fmtbit = SNDRV_PCM_FMTBIT_S24; 735 break; 736 case 32: 737 *fmtbit = SNDRV_PCM_FMTBIT_S32; 738 break; 739 default: 740 *fmtbit = 0; 741 break; 742 } 743 744 return 0; 745} 746 747static struct { 748 const char *label; 749 u8 type; 750} chan_position_names[] = { 751 { "Front Left", SNDRV_CHMAP_FL }, 752 { "Front Right", SNDRV_CHMAP_FR }, 753 { "Rear Left", SNDRV_CHMAP_RL }, 754 { "Rear Right", SNDRV_CHMAP_RR }, 755 { "Front Center", SNDRV_CHMAP_FC }, 756 { "Low Frequency Effects", SNDRV_CHMAP_LFE }, 757 { "Rear Center", SNDRV_CHMAP_RC }, 758 { "Front Left Center", SNDRV_CHMAP_FLC }, 759 { "Front Right Center", SNDRV_CHMAP_FRC }, 760 { "Rear Left Center", SNDRV_CHMAP_RLC }, 761 { "Rear Right Center", SNDRV_CHMAP_RRC }, 762 { "Front Left Wide", SNDRV_CHMAP_FLW }, 763 { "Front Right Wide", SNDRV_CHMAP_FRW }, 764 { "Front Left High", SNDRV_CHMAP_FLH }, 765 { "Front Center High", SNDRV_CHMAP_FCH }, 766 { "Front Right High", SNDRV_CHMAP_FRH }, 767 { "Top Center", SNDRV_CHMAP_TC }, 768}; 769 770static void append_chmap(struct snd_pcm_chmap_elem *chmap, u8 type) 771{ 772 if (!chmap || chmap->channels >= ARRAY_SIZE(chmap->map)) 773 return; 774 775 chmap->map[chmap->channels] = type; 776 chmap->channels++; 777} 778 779static int parse_chmap(struct dcp_parse_ctx *handle, struct snd_pcm_chmap_elem *chmap) 780{ 781 struct iterator it; 782 int i, ret; 783 784 if (!chmap) { 785 skip(handle); 786 return 0; 787 } 788 789 chmap->channels = 0; 790 791 dcp_parse_foreach_in_array(handle, it) { 792 for (i = 0; i < ARRAY_SIZE(chan_position_names); i++) 793 if (consume_string(it.handle, chan_position_names[i].label)) 794 break; 795 796 if (i == ARRAY_SIZE(chan_position_names)) { 797 ret = skip(it.handle); 798 if (ret) 799 return ret; 800 801 append_chmap(chmap, SNDRV_CHMAP_UNKNOWN); 802 continue; 803 } 804 805 append_chmap(chmap, chan_position_names[i].type); 806 } 807 808 return 0; 809} 810 811static int parse_chan_layout_element(struct dcp_parse_ctx *handle, 812 unsigned int *nchans_out, 813 struct snd_pcm_chmap_elem *chmap) 814{ 815 struct iterator it; 816 int ret; 817 s64 nchans = 0; 818 819 dcp_parse_foreach_in_dict(handle, it) { 820 if (consume_string(it.handle, "ActiveChannelCount")) 821 ret = parse_int(it.handle, &nchans); 822 else if (consume_string(it.handle, "ChannelLayout")) 823 ret = parse_chmap(it.handle, chmap); 824 else 825 ret = skip_pair(it.handle); 826 827 if (ret) 828 return ret; 829 } 830 831 if (nchans_out) 832 *nchans_out = nchans; 833 834 return 0; 835} 836 837static int parse_nchans_mask(struct dcp_parse_ctx *handle, unsigned int *mask) 838{ 839 struct iterator it; 840 int ret; 841 842 *mask = 0; 843 844 dcp_parse_foreach_in_array(handle, it) { 845 int nchans; 846 847 ret = parse_chan_layout_element(it.handle, &nchans, NULL); 848 if (ret) 849 return ret; 850 *mask |= 1 << nchans; 851 } 852 853 return 0; 854} 855 856static int parse_avep_element(struct dcp_parse_ctx *handle, 857 struct dcp_sound_format_mask *sieve, 858 struct dcp_sound_format_mask *hits) 859{ 860 struct dcp_sound_format_mask mask = {0, 0, 0}; 861 struct iterator it; 862 int ret; 863 864 dcp_parse_foreach_in_dict(handle, it) { 865 if (consume_string(handle, "StreamSampleRate")) 866 ret = parse_sample_rate_bit(it.handle, &mask.rates); 867 else if (consume_string(handle, "SampleSize")) 868 ret = parse_sample_fmtbit(it.handle, &mask.formats); 869 else if (consume_string(handle, "AudioChannelLayoutElements")) 870 ret = parse_nchans_mask(it.handle, &mask.nchans); 871 else 872 ret = skip_pair(it.handle); 873 874 if (ret) 875 return ret; 876 } 877 878 trace_avep_sound_mode(handle->dcp, mask.rates, mask.formats, mask.nchans); 879 880 if (!(mask.rates & sieve->rates) || !(mask.formats & sieve->formats) || 881 !(mask.nchans & sieve->nchans)) 882 return 0; 883 884 if (hits) { 885 hits->rates |= mask.rates; 886 hits->formats |= mask.formats; 887 hits->nchans |= mask.nchans; 888 } 889 890 return 1; 891} 892 893static int parse_mode_in_avep_element(struct dcp_parse_ctx *handle, 894 unsigned int selected_nchans, 895 struct snd_pcm_chmap_elem *chmap, 896 struct dcp_sound_cookie *cookie) 897{ 898 struct iterator it; 899 struct dcp_parse_ctx save_handle; 900 int ret; 901 902 dcp_parse_foreach_in_dict(handle, it) { 903 if (consume_string(it.handle, "AudioChannelLayoutElements")) { 904 struct iterator inner_it; 905 int nchans; 906 907 dcp_parse_foreach_in_array(it.handle, inner_it) { 908 save_handle = *it.handle; 909 ret = parse_chan_layout_element(inner_it.handle, 910 &nchans, NULL); 911 if (ret) 912 return ret; 913 914 if (nchans != selected_nchans) 915 continue; 916 917 /* 918 * Now that we know this layout matches the 919 * selected channel number, reread the element 920 * and fill in the channel map. 921 */ 922 *inner_it.handle = save_handle; 923 ret = parse_chan_layout_element(inner_it.handle, 924 NULL, chmap); 925 if (ret) 926 return ret; 927 } 928 } else if (consume_string(it.handle, "ElementData")) { 929 const u8 *blob; 930 931 ret = parse_blob(it.handle, sizeof(*cookie), &blob); 932 if (ret) 933 return ret; 934 935 if (cookie) 936 memcpy(cookie, blob, sizeof(*cookie)); 937 } else { 938 ret = skip_pair(it.handle); 939 if (ret) 940 return ret; 941 } 942 } 943 944 return 0; 945} 946 947int parse_sound_constraints(struct dcp_parse_ctx *handle, 948 struct dcp_sound_format_mask *sieve, 949 struct dcp_sound_format_mask *hits) 950{ 951 int ret; 952 struct iterator it; 953 954 if (hits) { 955 hits->rates = 0; 956 hits->formats = 0; 957 hits->nchans = 0; 958 } 959 960 dcp_parse_foreach_in_array(handle, it) { 961 ret = parse_avep_element(it.handle, sieve, hits); 962 963 if (ret < 0) 964 return ret; 965 } 966 967 return 0; 968} 969EXPORT_SYMBOL_GPL(parse_sound_constraints); 970 971int parse_sound_mode(struct dcp_parse_ctx *handle, 972 struct dcp_sound_format_mask *sieve, 973 struct snd_pcm_chmap_elem *chmap, 974 struct dcp_sound_cookie *cookie) 975{ 976 struct dcp_parse_ctx save_handle; 977 struct iterator it; 978 int ret; 979 980 dcp_parse_foreach_in_array(handle, it) { 981 save_handle = *it.handle; 982 ret = parse_avep_element(it.handle, sieve, NULL); 983 984 if (!ret) 985 continue; 986 987 if (ret < 0) 988 return ret; 989 990 ret = parse_mode_in_avep_element(&save_handle, __ffs(sieve->nchans), 991 chmap, cookie); 992 if (ret < 0) 993 return ret; 994 return 1; 995 } 996 997 return 0; 998} 999EXPORT_SYMBOL_GPL(parse_sound_mode); 1000 1001int parse_system_log_mnits(struct dcp_parse_ctx *handle, struct dcp_system_ev_mnits *entry) 1002{ 1003 struct iterator it; 1004 int ret; 1005 s64 mnits = -1; 1006 s64 idac = -1; 1007 s64 timestamp = -1; 1008 bool type_match = false; 1009 1010 dcp_parse_foreach_in_dict(handle, it) { 1011 char *key = parse_string(it.handle); 1012 if (IS_ERR(key)) { 1013 ret = PTR_ERR(key); 1014 } else if (!strcmp(key, "mNits")) { 1015 ret = parse_int(it.handle, &mnits); 1016 } else if (!strcmp(key, "iDAC")) { 1017 ret = parse_int(it.handle, &idac); 1018 } else if (!strcmp(key, "logEvent")) { 1019 const char * value = parse_string(it.handle); 1020 if (!IS_ERR_OR_NULL(value)) { 1021 type_match = strcmp(value, "Display (Event Forward)") == 0; 1022 kfree(value); 1023 } 1024 } else if (!strcmp(key, "timestamp")) { 1025 ret = parse_int(it.handle, ×tamp); 1026 } else { 1027 skip(it.handle); 1028 } 1029 1030 if (!IS_ERR_OR_NULL(key)) 1031 kfree(key); 1032 1033 if (ret) { 1034 pr_err("dcp parser: failed to parse mNits sys event\n"); 1035 return ret; 1036 } 1037 } 1038 1039 if (!type_match || mnits < 0 || idac < 0 || timestamp < 0) 1040 return -EINVAL; 1041 1042 entry->millinits = mnits; 1043 entry->idac = idac; 1044 entry->timestamp = timestamp; 1045 1046 return 0; 1047} 1048