Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: Add the necessary bits to support bus format negotiation

drm_bridge_state is extended to describe the input and output bus
configurations. These bus configurations are exposed through the
drm_bus_cfg struct which encodes the configuration of a physical
bus between two components in an output pipeline, usually between
two bridges, an encoder and a bridge, or a bridge and a connector.

The bus configuration is stored in drm_bridge_state separately for
the input and output buses, as seen from the point of view of each
bridge. The bus configuration of a bridge output is usually identical
to the configuration of the next bridge's input, but may differ if
the signals are modified between the two bridges, for instance by an
inverter on the board. The input and output configurations of a
bridge may differ if the bridge modifies the signals internally,
for instance by performing format conversion, or*modifying signals
polarities.

Bus format negotiation is automated by the core, drivers just have
to implement the ->atomic_get_{output,input}_bus_fmts() hooks if they
want to take part to this negotiation. Negotiation happens in reverse
order, starting from the last element of the chain (the one directly
connected to the display) up to the first element of the chain (the one
connected to the encoder).
During this negotiation all supported formats are tested until we find
one that works, meaning that the formats array should be in decreasing
preference order (assuming the driver has a preference order).

Note that the bus format negotiation works even if some elements in the
chain don't implement the ->atomic_get_{output,input}_bus_fmts() hooks.
In that case, the core advertises only MEDIA_BUS_FMT_FIXED and lets
the previous bridge element decide what to do (most of the time, bridge
drivers will pick a default bus format or extract this piece of
information from somewhere else, like a FW property).

v10:
* Add changelog to the commit message

v9:
* No changes

v8:
* Fix a test in drm_atomic_bridge_chain_select_bus_fmts() (Reported by
Jonas)

v7:
* Adapt the code to deal with the fact that not all bridges in the
chain have a bridge state

v5 -> v6:
* No changes

v4:
* Enhance the doc
* Fix typos
* Rename some parameters/fields
* Reword the commit message

v3:
* Fix the commit message (Reported by Laurent)
* Document the fact that bus formats should not be directly modified by
drivers (Suggested by Laurent)
* Document the fact that format order matters (Suggested by Laurent)
* Propagate bus flags by default
* Document the fact that drivers can tweak bus flags if needed
* Let ->atomic_get_{output,input}_bus_fmts() allocate the bus format
array (Suggested by Laurent)
* Add a drm_atomic_helper_bridge_propagate_bus_fmt()
* Mandate that bridge drivers return accurate input_fmts even if they
are known to be the first element in the bridge chain

v2:
* Rework things to support more complex use cases

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
[narmstrong: fixed doc in include/drm/drm_bridge.h:69 fmt->format]
Reviewed-by: Jernej Skrabec <jernej.skrabec@siol.net>
Tested-by: Jonas Karlman <jonas@kwiboo.se>
Link: https://patchwork.freedesktop.org/patch/msgid/20200128135514.108171-7-boris.brezillon@collabora.com

+425 -1
+41
drivers/gpu/drm/drm_atomic_helper.c
··· 3536 3536 return ret; 3537 3537 } 3538 3538 EXPORT_SYMBOL(drm_atomic_helper_legacy_gamma_set); 3539 + 3540 + /** 3541 + * drm_atomic_helper_bridge_propagate_bus_fmt() - Propagate output format to 3542 + * the input end of a bridge 3543 + * @bridge: bridge control structure 3544 + * @bridge_state: new bridge state 3545 + * @crtc_state: new CRTC state 3546 + * @conn_state: new connector state 3547 + * @output_fmt: tested output bus format 3548 + * @num_input_fmts: will contain the size of the returned array 3549 + * 3550 + * This helper is a pluggable implementation of the 3551 + * &drm_bridge_funcs.atomic_get_input_bus_fmts operation for bridges that don't 3552 + * modify the bus configuration between their input and their output. It 3553 + * returns an array of input formats with a single element set to @output_fmt. 3554 + * 3555 + * RETURNS: 3556 + * a valid format array of size @num_input_fmts, or NULL if the allocation 3557 + * failed 3558 + */ 3559 + u32 * 3560 + drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, 3561 + struct drm_bridge_state *bridge_state, 3562 + struct drm_crtc_state *crtc_state, 3563 + struct drm_connector_state *conn_state, 3564 + u32 output_fmt, 3565 + unsigned int *num_input_fmts) 3566 + { 3567 + u32 *input_fmts; 3568 + 3569 + input_fmts = kzalloc(sizeof(*input_fmts), GFP_KERNEL); 3570 + if (!input_fmts) { 3571 + *num_input_fmts = 0; 3572 + return NULL; 3573 + } 3574 + 3575 + *num_input_fmts = 1; 3576 + input_fmts[0] = output_fmt; 3577 + return input_fmts; 3578 + } 3579 + EXPORT_SYMBOL(drm_atomic_helper_bridge_propagate_bus_fmt);
+252 -1
drivers/gpu/drm/drm_bridge.c
··· 628 628 return 0; 629 629 } 630 630 631 + static int select_bus_fmt_recursive(struct drm_bridge *first_bridge, 632 + struct drm_bridge *cur_bridge, 633 + struct drm_crtc_state *crtc_state, 634 + struct drm_connector_state *conn_state, 635 + u32 out_bus_fmt) 636 + { 637 + struct drm_bridge_state *cur_state; 638 + unsigned int num_in_bus_fmts, i; 639 + struct drm_bridge *prev_bridge; 640 + u32 *in_bus_fmts; 641 + int ret; 642 + 643 + prev_bridge = drm_bridge_get_prev_bridge(cur_bridge); 644 + cur_state = drm_atomic_get_new_bridge_state(crtc_state->state, 645 + cur_bridge); 646 + 647 + /* 648 + * If bus format negotiation is not supported by this bridge, let's 649 + * pass MEDIA_BUS_FMT_FIXED to the previous bridge in the chain and 650 + * hope that it can handle this situation gracefully (by providing 651 + * appropriate default values). 652 + */ 653 + if (!cur_bridge->funcs->atomic_get_input_bus_fmts) { 654 + if (cur_bridge != first_bridge) { 655 + ret = select_bus_fmt_recursive(first_bridge, 656 + prev_bridge, crtc_state, 657 + conn_state, 658 + MEDIA_BUS_FMT_FIXED); 659 + if (ret) 660 + return ret; 661 + } 662 + 663 + /* 664 + * Driver does not implement the atomic state hooks, but that's 665 + * fine, as long as it does not access the bridge state. 666 + */ 667 + if (cur_state) { 668 + cur_state->input_bus_cfg.format = MEDIA_BUS_FMT_FIXED; 669 + cur_state->output_bus_cfg.format = out_bus_fmt; 670 + } 671 + 672 + return 0; 673 + } 674 + 675 + /* 676 + * If the driver implements ->atomic_get_input_bus_fmts() it 677 + * should also implement the atomic state hooks. 678 + */ 679 + if (WARN_ON(!cur_state)) 680 + return -EINVAL; 681 + 682 + in_bus_fmts = cur_bridge->funcs->atomic_get_input_bus_fmts(cur_bridge, 683 + cur_state, 684 + crtc_state, 685 + conn_state, 686 + out_bus_fmt, 687 + &num_in_bus_fmts); 688 + if (!num_in_bus_fmts) 689 + return -ENOTSUPP; 690 + else if (!in_bus_fmts) 691 + return -ENOMEM; 692 + 693 + if (first_bridge == cur_bridge) { 694 + cur_state->input_bus_cfg.format = in_bus_fmts[0]; 695 + cur_state->output_bus_cfg.format = out_bus_fmt; 696 + kfree(in_bus_fmts); 697 + return 0; 698 + } 699 + 700 + for (i = 0; i < num_in_bus_fmts; i++) { 701 + ret = select_bus_fmt_recursive(first_bridge, prev_bridge, 702 + crtc_state, conn_state, 703 + in_bus_fmts[i]); 704 + if (ret != -ENOTSUPP) 705 + break; 706 + } 707 + 708 + if (!ret) { 709 + cur_state->input_bus_cfg.format = in_bus_fmts[i]; 710 + cur_state->output_bus_cfg.format = out_bus_fmt; 711 + } 712 + 713 + kfree(in_bus_fmts); 714 + return ret; 715 + } 716 + 717 + /* 718 + * This function is called by &drm_atomic_bridge_chain_check() just before 719 + * calling &drm_bridge_funcs.atomic_check() on all elements of the chain. 720 + * It performs bus format negotiation between bridge elements. The negotiation 721 + * happens in reverse order, starting from the last element in the chain up to 722 + * @bridge. 723 + * 724 + * Negotiation starts by retrieving supported output bus formats on the last 725 + * bridge element and testing them one by one. The test is recursive, meaning 726 + * that for each tested output format, the whole chain will be walked backward, 727 + * and each element will have to choose an input bus format that can be 728 + * transcoded to the requested output format. When a bridge element does not 729 + * support transcoding into a specific output format -ENOTSUPP is returned and 730 + * the next bridge element will have to try a different format. If none of the 731 + * combinations worked, -ENOTSUPP is returned and the atomic modeset will fail. 732 + * 733 + * This implementation is relying on 734 + * &drm_bridge_funcs.atomic_get_output_bus_fmts() and 735 + * &drm_bridge_funcs.atomic_get_input_bus_fmts() to gather supported 736 + * input/output formats. 737 + * 738 + * When &drm_bridge_funcs.atomic_get_output_bus_fmts() is not implemented by 739 + * the last element of the chain, &drm_atomic_bridge_chain_select_bus_fmts() 740 + * tries a single format: &drm_connector.display_info.bus_formats[0] if 741 + * available, MEDIA_BUS_FMT_FIXED otherwise. 742 + * 743 + * When &drm_bridge_funcs.atomic_get_input_bus_fmts() is not implemented, 744 + * &drm_atomic_bridge_chain_select_bus_fmts() skips the negotiation on the 745 + * bridge element that lacks this hook and asks the previous element in the 746 + * chain to try MEDIA_BUS_FMT_FIXED. It's up to bridge drivers to decide what 747 + * to do in that case (fail if they want to enforce bus format negotiation, or 748 + * provide a reasonable default if they need to support pipelines where not 749 + * all elements support bus format negotiation). 750 + */ 751 + static int 752 + drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge, 753 + struct drm_crtc_state *crtc_state, 754 + struct drm_connector_state *conn_state) 755 + { 756 + struct drm_connector *conn = conn_state->connector; 757 + struct drm_encoder *encoder = bridge->encoder; 758 + struct drm_bridge_state *last_bridge_state; 759 + unsigned int i, num_out_bus_fmts; 760 + struct drm_bridge *last_bridge; 761 + u32 *out_bus_fmts; 762 + int ret = 0; 763 + 764 + last_bridge = list_last_entry(&encoder->bridge_chain, 765 + struct drm_bridge, chain_node); 766 + last_bridge_state = drm_atomic_get_new_bridge_state(crtc_state->state, 767 + last_bridge); 768 + 769 + if (last_bridge->funcs->atomic_get_output_bus_fmts) { 770 + const struct drm_bridge_funcs *funcs = last_bridge->funcs; 771 + 772 + /* 773 + * If the driver implements ->atomic_get_output_bus_fmts() it 774 + * should also implement the atomic state hooks. 775 + */ 776 + if (WARN_ON(!last_bridge_state)) 777 + return -EINVAL; 778 + 779 + out_bus_fmts = funcs->atomic_get_output_bus_fmts(last_bridge, 780 + last_bridge_state, 781 + crtc_state, 782 + conn_state, 783 + &num_out_bus_fmts); 784 + if (!num_out_bus_fmts) 785 + return -ENOTSUPP; 786 + else if (!out_bus_fmts) 787 + return -ENOMEM; 788 + } else { 789 + num_out_bus_fmts = 1; 790 + out_bus_fmts = kmalloc(sizeof(*out_bus_fmts), GFP_KERNEL); 791 + if (!out_bus_fmts) 792 + return -ENOMEM; 793 + 794 + if (conn->display_info.num_bus_formats && 795 + conn->display_info.bus_formats) 796 + out_bus_fmts[0] = conn->display_info.bus_formats[0]; 797 + else 798 + out_bus_fmts[0] = MEDIA_BUS_FMT_FIXED; 799 + } 800 + 801 + for (i = 0; i < num_out_bus_fmts; i++) { 802 + ret = select_bus_fmt_recursive(bridge, last_bridge, crtc_state, 803 + conn_state, out_bus_fmts[i]); 804 + if (ret != -ENOTSUPP) 805 + break; 806 + } 807 + 808 + kfree(out_bus_fmts); 809 + 810 + return ret; 811 + } 812 + 813 + static void 814 + drm_atomic_bridge_propagate_bus_flags(struct drm_bridge *bridge, 815 + struct drm_connector *conn, 816 + struct drm_atomic_state *state) 817 + { 818 + struct drm_bridge_state *bridge_state, *next_bridge_state; 819 + struct drm_bridge *next_bridge; 820 + u32 output_flags = 0; 821 + 822 + bridge_state = drm_atomic_get_new_bridge_state(state, bridge); 823 + 824 + /* No bridge state attached to this bridge => nothing to propagate. */ 825 + if (!bridge_state) 826 + return; 827 + 828 + next_bridge = drm_bridge_get_next_bridge(bridge); 829 + 830 + /* 831 + * Let's try to apply the most common case here, that is, propagate 832 + * display_info flags for the last bridge, and propagate the input 833 + * flags of the next bridge element to the output end of the current 834 + * bridge when the bridge is not the last one. 835 + * There are exceptions to this rule, like when signal inversion is 836 + * happening at the board level, but that's something drivers can deal 837 + * with from their &drm_bridge_funcs.atomic_check() implementation by 838 + * simply overriding the flags value we've set here. 839 + */ 840 + if (!next_bridge) { 841 + output_flags = conn->display_info.bus_flags; 842 + } else { 843 + next_bridge_state = drm_atomic_get_new_bridge_state(state, 844 + next_bridge); 845 + /* 846 + * No bridge state attached to the next bridge, just leave the 847 + * flags to 0. 848 + */ 849 + if (next_bridge_state) 850 + output_flags = next_bridge_state->input_bus_cfg.flags; 851 + } 852 + 853 + bridge_state->output_bus_cfg.flags = output_flags; 854 + 855 + /* 856 + * Propage the output flags to the input end of the bridge. Again, it's 857 + * not necessarily what all bridges want, but that's what most of them 858 + * do, and by doing that by default we avoid forcing drivers to 859 + * duplicate the "dummy propagation" logic. 860 + */ 861 + bridge_state->input_bus_cfg.flags = output_flags; 862 + } 863 + 631 864 /** 632 865 * drm_atomic_bridge_chain_check() - Do an atomic check on the bridge chain 633 866 * @bridge: bridge control structure 634 867 * @crtc_state: new CRTC state 635 868 * @conn_state: new connector state 636 869 * 637 - * Calls &drm_bridge_funcs.atomic_check() (falls back on 870 + * First trigger a bus format negotiation before calling 871 + * &drm_bridge_funcs.atomic_check() (falls back on 638 872 * &drm_bridge_funcs.mode_fixup()) op for all the bridges in the encoder chain, 639 873 * starting from the last bridge to the first. These are called before calling 640 874 * &drm_encoder_helper_funcs.atomic_check() ··· 880 646 struct drm_crtc_state *crtc_state, 881 647 struct drm_connector_state *conn_state) 882 648 { 649 + struct drm_connector *conn = conn_state->connector; 883 650 struct drm_encoder *encoder; 884 651 struct drm_bridge *iter; 652 + int ret; 885 653 886 654 if (!bridge) 887 655 return 0; 888 656 657 + ret = drm_atomic_bridge_chain_select_bus_fmts(bridge, crtc_state, 658 + conn_state); 659 + if (ret) 660 + return ret; 661 + 889 662 encoder = bridge->encoder; 890 663 list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { 891 664 int ret; 665 + 666 + /* 667 + * Bus flags are propagated by default. If a bridge needs to 668 + * tweak the input bus flags for any reason, it should happen 669 + * in its &drm_bridge_funcs.atomic_check() implementation such 670 + * that preceding bridges in the chain can propagate the new 671 + * bus flags. 672 + */ 673 + drm_atomic_bridge_propagate_bus_flags(iter, conn, 674 + crtc_state->state); 892 675 893 676 ret = drm_atomic_bridge_check(iter, crtc_state, conn_state); 894 677 if (ret)
+42
include/drm/drm_atomic.h
··· 996 996 } 997 997 998 998 /** 999 + * struct drm_bus_cfg - bus configuration 1000 + * 1001 + * This structure stores the configuration of a physical bus between two 1002 + * components in an output pipeline, usually between two bridges, an encoder 1003 + * and a bridge, or a bridge and a connector. 1004 + * 1005 + * The bus configuration is stored in &drm_bridge_state separately for the 1006 + * input and output buses, as seen from the point of view of each bridge. The 1007 + * bus configuration of a bridge output is usually identical to the 1008 + * configuration of the next bridge's input, but may differ if the signals are 1009 + * modified between the two bridges, for instance by an inverter on the board. 1010 + * The input and output configurations of a bridge may differ if the bridge 1011 + * modifies the signals internally, for instance by performing format 1012 + * conversion, or modifying signals polarities. 1013 + */ 1014 + struct drm_bus_cfg { 1015 + /** 1016 + * @format: format used on this bus (one of the MEDIA_BUS_FMT_* format) 1017 + * 1018 + * This field should not be directly modified by drivers 1019 + * (&drm_atomic_bridge_chain_select_bus_fmts() takes care of the bus 1020 + * format negotiation). 1021 + */ 1022 + u32 format; 1023 + 1024 + /** 1025 + * @flags: DRM_BUS_* flags used on this bus 1026 + */ 1027 + u32 flags; 1028 + }; 1029 + 1030 + /** 999 1031 * struct drm_bridge_state - Atomic bridge state object 1000 1032 */ 1001 1033 struct drm_bridge_state { ··· 1040 1008 * @bridge: the bridge this state refers to 1041 1009 */ 1042 1010 struct drm_bridge *bridge; 1011 + 1012 + /** 1013 + * @input_bus_cfg: input bus configuration 1014 + */ 1015 + struct drm_bus_cfg input_bus_cfg; 1016 + 1017 + /** 1018 + * @output_bus_cfg: input bus configuration 1019 + */ 1020 + struct drm_bus_cfg output_bus_cfg; 1043 1021 }; 1044 1022 1045 1023 static inline struct drm_bridge_state *
+8
include/drm/drm_atomic_helper.h
··· 224 224 return old_plane_state->crtc && !new_plane_state->crtc; 225 225 } 226 226 227 + u32 * 228 + drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, 229 + struct drm_bridge_state *bridge_state, 230 + struct drm_crtc_state *crtc_state, 231 + struct drm_connector_state *conn_state, 232 + u32 output_fmt, 233 + unsigned int *num_input_fmts); 234 + 227 235 #endif /* DRM_ATOMIC_HELPER_H_ */
+82
include/drm/drm_bridge.h
··· 371 371 struct drm_bridge_state *state); 372 372 373 373 /** 374 + * @atomic_get_output_bus_fmts: 375 + * 376 + * Return the supported bus formats on the output end of a bridge. 377 + * The returned array must be allocated with kmalloc() and will be 378 + * freed by the caller. If the allocation fails, NULL should be 379 + * returned. num_output_fmts must be set to the returned array size. 380 + * Formats listed in the returned array should be listed in decreasing 381 + * preference order (the core will try all formats until it finds one 382 + * that works). 383 + * 384 + * This method is only called on the last element of the bridge chain 385 + * as part of the bus format negotiation process that happens in 386 + * &drm_atomic_bridge_chain_select_bus_fmts(). 387 + * This method is optional. When not implemented, the core will 388 + * fall back to &drm_connector.display_info.bus_formats[0] if 389 + * &drm_connector.display_info.num_bus_formats > 0, 390 + * or to MEDIA_BUS_FMT_FIXED otherwise. 391 + */ 392 + u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge, 393 + struct drm_bridge_state *bridge_state, 394 + struct drm_crtc_state *crtc_state, 395 + struct drm_connector_state *conn_state, 396 + unsigned int *num_output_fmts); 397 + 398 + /** 399 + * @atomic_get_input_bus_fmts: 400 + * 401 + * Return the supported bus formats on the input end of a bridge for 402 + * a specific output bus format. 403 + * 404 + * The returned array must be allocated with kmalloc() and will be 405 + * freed by the caller. If the allocation fails, NULL should be 406 + * returned. num_output_fmts must be set to the returned array size. 407 + * Formats listed in the returned array should be listed in decreasing 408 + * preference order (the core will try all formats until it finds one 409 + * that works). When the format is not supported NULL should be 410 + * returned and *num_output_fmts should be set to 0. 411 + * 412 + * This method is called on all elements of the bridge chain as part of 413 + * the bus format negotiation process that happens in 414 + * &drm_atomic_bridge_chain_select_bus_fmts(). 415 + * This method is optional. When not implemented, the core will bypass 416 + * bus format negotiation on this element of the bridge without 417 + * failing, and the previous element in the chain will be passed 418 + * MEDIA_BUS_FMT_FIXED as its output bus format. 419 + * 420 + * Bridge drivers that need to support being linked to bridges that are 421 + * not supporting bus format negotiation should handle the 422 + * output_fmt == MEDIA_BUS_FMT_FIXED case appropriately, by selecting a 423 + * sensible default value or extracting this information from somewhere 424 + * else (FW property, &drm_display_mode, &drm_display_info, ...) 425 + * 426 + * Note: Even if input format selection on the first bridge has no 427 + * impact on the negotiation process (bus format negotiation stops once 428 + * we reach the first element of the chain), drivers are expected to 429 + * return accurate input formats as the input format may be used to 430 + * configure the CRTC output appropriately. 431 + */ 432 + u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge, 433 + struct drm_bridge_state *bridge_state, 434 + struct drm_crtc_state *crtc_state, 435 + struct drm_connector_state *conn_state, 436 + u32 output_fmt, 437 + unsigned int *num_input_fmts); 438 + 439 + /** 374 440 * @atomic_check: 375 441 * 376 442 * This method is responsible for checking bridge state correctness. ··· 449 383 * This method is optional. &drm_bridge_funcs.mode_fixup() is not 450 384 * called when &drm_bridge_funcs.atomic_check() is implemented, so only 451 385 * one of them should be provided. 386 + * 387 + * If drivers need to tweak &drm_bridge_state.input_bus_cfg.flags or 388 + * &drm_bridge_state.output_bus_cfg.flags it should should happen in 389 + * this function. By default the &drm_bridge_state.output_bus_cfg.flags 390 + * field is set to the next bridge 391 + * &drm_bridge_state.input_bus_cfg.flags value or 392 + * &drm_connector.display_info.bus_flags if the bridge is the last 393 + * element in the chain. 452 394 * 453 395 * RETURNS: 454 396 * zero if the check passed, a negative error code otherwise. ··· 651 577 struct drm_atomic_state *state); 652 578 void drm_atomic_bridge_chain_enable(struct drm_bridge *bridge, 653 579 struct drm_atomic_state *state); 580 + 581 + u32 * 582 + drm_atomic_helper_bridge_propagate_bus_fmt(struct drm_bridge *bridge, 583 + struct drm_bridge_state *bridge_state, 584 + struct drm_crtc_state *crtc_state, 585 + struct drm_connector_state *conn_state, 586 + u32 output_fmt, 587 + unsigned int *num_input_fmts); 654 588 655 589 #ifdef CONFIG_DRM_PANEL_BRIDGE 656 590 struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel);