From mboxrd@z Thu Jan 1 00:00:00 1970 From: laurent.pinchart@ideasonboard.com (Laurent Pinchart) Date: Wed, 04 Apr 2018 16:07:37 +0300 Subject: [PATCH v2 2/5] drm: bridge: add API to query the expected input formats of bridges In-Reply-To: <20180327130231.GO27746@w540> References: <20180326212447.7380-1-peda@axentia.se> <20180327130231.GO27746@w540> Message-ID: <1811029.jLvDxETu2H@avalon> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org Hello, First of all, thank you for the patch. This generates more discussion than I had anticipated, which is both good and bad. I'll comment through the e-mail, and try to explain both my initial idea, and also where it could lead us. On Tuesday, 27 March 2018 16:02:31 EEST jacopo mondi wrote: > On Tue, Mar 27, 2018 at 02:12:42PM +0200, Peter Rosin wrote: > > On 2018-03-27 11:47, jacopo mondi wrote: > >> On Mon, Mar 26, 2018 at 11:24:44PM +0200, Peter Rosin wrote: > >>> Bridges may affect the required bus output format of the encoder, in > >>> which case it may be wrong to use the output format of the panel or > >>> connector as is. Add infrastructure to address this problem. > >> > >> Bridges not only affect the format expected by the connector at the > >> end of the display pipeline, they may perform encoding/decoding > >> between protocols and their accepted input formats may be unrelated to > >> the connector at the end of the pipeline as there may an arbitrary > >> number of bridges in between. > >> > >> Eg. > >> > >> ENCODER CONNECTOR > >> > >> |DU LVDS| ->lvds-> |THC63| ->rgb-> |ADV7511| ->hdmi-> |HDMI connector| > >> > >> The fact that THC63 wants a specific LVDS input format is unrelated to > >> the format required by the HDMI connector at the end of the pipeline. > >> > >> I would just state here that bridges need a way to report their > >> accepted media bus formats, and this patch extends the DRM Bridge APIs > >> to implement that. > > > > Yes, I can add some words, but I would like to clear up the naming > > before re-spinning. > > > >>> Signed-off-by: Peter Rosin > >>> --- > >>> > >>> drivers/gpu/drm/drm_bridge.c | 32 ++++++++++++++++++++++++++++++++ > >>> include/drm/drm_bridge.h | 18 ++++++++++++++++++ > >> 2 files changed, 50 insertions(+) > >>> > >>> diff --git a/drivers/gpu/drm/drm_bridge.c > >>> b/drivers/gpu/drm/drm_bridge.c > >>> index 1638bfe9627c..f85e61b7416e 100644 > >>> --- a/drivers/gpu/drm/drm_bridge.c > >>> +++ b/drivers/gpu/drm/drm_bridge.c > >>> @@ -348,6 +348,38 @@ void drm_bridge_enable(struct drm_bridge *bridge) > >>> > >>> } > >>> EXPORT_SYMBOL(drm_bridge_enable); > >>> > >>> +/** > >>> + * drm_bridge_input_formats - get the expected bus input format of the > >>> bridge > >> > >> I may be biased by the V4L2 APIs, but this seems to me very much like > >> similar to g_fmt/s_fmt callbacks we have there. Bridges have an input > >> and > > > > g_fmt/s_fmt says nothing to me. Graphics format? Source Format? I have > > no idea if those guesses are even close? So, that seems like poor naming > > to me. The only reason I see to go that way is for the sake of > > consistency. > > Sorry, I wasn't clear here. > > To me this operation seems like a "get format" and I see space for > future implementation of "set format" operations and also > "enum_formats" to implement format negotiation between bridges... A bit of context is probably needed here to bridge (no pun intended) DRM and V4L2. On the V4L2 side we have an object, named v4l2_subdev, that is analogous to drm_bridge. A v4l2_subdev models a component in a video pipeline, using abstract operations in a similar fashion to the drm_bridge_funcs. There are, however, several major differences between drm_bridge and v4l2_subdev. drm_bridge models a particular kind of component, namely video encoders, decoders or transcoders. A bridge is thus based on the implicit notion of having a single input and a single output, neither of them exposed explicitly. v4l2_subdev models any type of component in a video pipeline and for that reason has a variable number of inputs and outputs. The inputs and outputs are exposed explicitly through the v4l2_subdev API (in terms of the number of inputs/outputs, their type, and how they interact with the v4l2_subdev operations). As drm_bridge models one particular kind of component, the bridge operations are tailored to the feature of those components. Not all operations are mandatory (pre_enable or post_disable are optional for instance), but they all apply to all bridges conceptually. As v4l2_subdev models any type of component, the subdev operations have to support a wide variety of device features. There are thus many more operations, and not all of them are applicable to all type of v4l2_subdev. Operations that don't make sense for a particular v4l2_subdev instance (think about video tuner control for a camera sensor for instance) are simply not implemented. The drm_bridge framework hardcodes an operational model for bridges. Operations are called in a particular order on all bridges in a chain. For instance the enable operation is called from source to sink (bridge closest to the display controller to bridge closest to the connector), while the disable operation is called from sink to source. The v4l2_subdev framework doesn't hardcode an operation model. It is up to the top-level V4L2 driver (equivalent to the display controller driver) to call subdev operations in order applicable for the use cases it needs to support. This being said, let's talk about formats. In V4L2 a v4l2_subdev exposes operations to explicitly configure formats on all inputs and outputs (generically called pads in V4L2). Three operations are supported: .get_fmt() to retrieve the current format, .set_fmt() to set a format, and enum_mbus_code() and .enum_frame_size() to enumerate supported formats (I won't go into details regarding why enumeration is split in two operations, that's irrelevant here). It is important to note that format enumeration is mostly static (it tells what a v4l2_subdev supports), while get and set operations are dynamic (getting and setting, and more generically negotiating, formats). DRM has an API to enumerate the formats supported by connectors (through the drm_connector->display_info.bus_formats field). There is no API exposed to userspace to pick the desired format, neither at the connector level, or for bridges in the pipeline (bridges are not exposed to userspace at all). There is also no in-kernel API to enumerate formats supported by bridges or to get/ set a bridge format. Display controller are expected to pick an output format suitable for the output pipeline based on the formats supported by the connector and the selected display mode, and bridges are expected to just work without needing to care about formats. This model is starting to show its shortcomings now that we need to support bridges that convert formats. In Jacopo's case, an LVDS decoder transforms LVDS RGB to parallel RGB, and the display controller needs to know which LVDS format to output based on what the bridge expects. In Peter's case, an LVDS encoder transfer 24-bit RGB to LVDS RGB, but has the LSBs tied to ground on the input side, and thus requires the display controller to output RGB565. Now that we're done with the introduction, let's move on, please see below. > >> an output formats, and that calls for something that takes that into > >> account, as well as they may have different input ports with different > >> accepted formats but I would for now simplify this to just 'g_fmt()' > > > > You mean rename the function to drm_bridge_g_fmt(), right? > > Yeah, something like "drm_bridge_get_format(next_bridge)" > > > As indicated above, I'm not that fond of it, but don't really care > > either. Maintainers? > > I do not care much about the name too ofc, I think the real meat is > below... > > >>> + * @bridge: bridge control structure > >>> + * @bus_formats: where to store a pointer to the bus input formats > >>> + * > >>> + * Calls the &drm_bridge_funcs.input_formats op for the frist bridge > >>> in the > >>> + * chain that has registered this op. > >> > >> I'm not sure passing the call down the pipeline is desirable. Each > >> component should make sure its output format is accepted as the next > >> bridge input format, passing the call to the next bridge is not > >> different that getting to the connector at the end of the pipeline and > >> return to the initial caller its supported format. Do you agree with > >> this? > > > > Not passing down the call does one of two things. Either all bridges have > > to implement the call or all users have to walk the pipeline "manually". > > I don't like either or those options, so I still think it is good to > > pass the call down the pipeline. > > > > *time passes* > > > > Oh, you do not think it is useful for the bridge to have a callback but > > still report "no format change", and that the call down to pipeline > > should only happen for bridges that have not implemented the op. But I > > do think that is useful, see below. > > > >>> + * > >>> + * Note that the bridge passed should normally be the bridge closest to > >>> the > >>> + * encoder, but possibly the bridge closest to an intermediate bridge > >>> in > >>> + * convoluted cases. > >>> + * > >> > >> As I see this, any bridge in the arbitrary long pipeline should call > >> this operation on next bridge if it supports different output formats. > >> Ie. I would not name here the encoder nor refer to the bridge position > >> in the pipeline. > > > > Ok, I can change that, it just seemed like a convoluted case to me. > > I mean, if this was a real issue and complicated pipelines were > > common, something along the lines of this patch series would be > > available already. Right? I guess not, but how the &#/%# have people > > been coping? > > > >>> + * RETURNS: > >>> + * The number of bus input formats the bridge accepts. Zero means that > >>> + * the chain of bridges are not converting the bus format and that the > >>> + * format of the drm_connector should be used. > >> > >> How do we get to the connector format from a bridge that has maybe > >> other components in between in the pipeline? > >> > >> If a bridge do not report any supported format, it won't implement > >> this callback and things will work as they work today. > > > > Unless the bridge optionally changes the format. If the bridge has no > > way to say "no format change" even with the callback in place, it > > has to juggle different ops structs, which seems like a big hammer. > > So, I'm in favor of calling down the pipeline in two cases. A) when > > a bridge does not implement the op and B) when the op returns zero. > > Why do you think the bridge format conversion plays a role here? > > Maybe here's where I lost you, possibly because of my limited > knowledge of the DRM realm and its actual use cases. > > As I see it, this new API allows two bridges to synchronize on which > image format or LVDS mode 'bridge' should output to 'next_bridge' > input. > > The "mode_set" callback walks all element of the display pipeline, > and when one component has to select which image format or LVDS mode > to output to its next kin, if the next one is a panel it inspects the > display_info field, it it's a bridge it uses this new API to get the > format it accepts. > > If the next bridge does not implement this callback, things work as they > do today (in our specific use case, by chance :) > > > Maintainers? > > Yes, let's scale to more knowledgeable people than me, as I gave my > opinion already but it is based on the single use case I know for > real. I think it's important here to take a step back and look where we come from, what we need, and where we want to go. The first part is easy. As explained above, the current state is that we know what formats a connector supports, and we have no other API whatsoever, neither to userspace or inside the kernel, to handle format in the display output pipeline. What we need is at least static format information. In the two cases described above the bridge connected to the display controller output requires a specific format (RGB565 for Peter, LVDS JEIDA for Jacopo). There is no need to walk to pipeline and query all bridges, we can get the necessary information from the first bridge in the chain. Where we want to go is the real question. We need at least static information, so we could expose it through a new bus_formats field in the drm_bridge structure, similar to the bus_formats field in the drm_display_info structure. This would solve the two problems at hand. However, such a solution wouldn't allow us to configure formats through the pipeline, and wouldn't allow us to query the format a bridge needs based on the format needed by the next bridge in the chain. It would thus be limited to specific cases, and one could argue that it would be too limited. A more generic solution might be better, to support dynamic negotiation of formats through the pipeline. I believe this would be needed in the long run anyway, so it's tempting to give it a try today. However, as we don't have any real use case yet, one might argue that we would design the API incorrectly, which I can't completely disagree with. Nonetheless, if we were to design such an API, I agree with Daniel that it should be based on bridge states. Such a solution would allow negotiation of formats through the pipeline (using a yet to be designed process), and would then allow the display controller to retrieve the negotiated format expected by the first bridge from the bridge state. I don't think we would design the API between the display controller and the first bridge wrong (it would just be a matter of reading the negotiated format from the first bridge's state, there's little room for design issues there), but the format negotiation through the pipeline would need more thoughts. One option (just thinking out loud) would be to start with the connector format, and then ask each bridge in the chain, from last to first, for the input format it needs to generate the expected output format. More complex schemes might be needed, especially when the connector supports multiple formats, or when a bridge can accept multiple input formats to generate a given output format. In those cases picking the first supported format could work, but it might not always lead to the optimal pipeline configuration. Another point I want to mention is that in Peter's case the LVDS encoder requires RGB888 at its input, but the PCB routing transforms RGB565 to RGB888 by shifting signals and tying the LSBs to ground. That information really belongs to DT as it isn't intrinsic to either the display controller or the LVDS encoder. I however wonder whether it should be expressed as a format, or in a different form. In V4L2 we have standardized bus-width and data-shift DT properties (see Documentation/devicetree/bindings/media/video-interfaces.txt) to expose how signals are connected in the PCB. This allows expressing transformations instead of hardcoding formats, which can be useful if the bridge can still accept multiple input formats. One example of this is raw camera sensors that can output multiple bayer patterns (BGGR, GBRG, GRBG or RGGB) with 10 bits per pixel, combined with a PCB that connects D[9:2] of the sensor to D[7:0] of the camera controller. BGGR10 would be turned into BGGR8, GBRG10 into GBRG8, and so on. The camera controller should thus not hardcode a particular format in DT as there are multiple options that can be selected at runtime. I can imagine a similar setup for the display, with a bridge configurable through I2C that could accept different formats, combined with the PCB performing some weird routing. Finally, still regarding Peter's case, the decision to output RGB565 instead of RGB888 (which the LVDS encoder expects) is due to PCB routing between the display controller and the LVDS encoder. This isn't a property of the LVDS encoder or the display controller, but of their hardware connection. This patch series uses a DT property in the LVDS encoder DT node to convey that information, but wouldn't it be equally correct (or incorrect :-)) to instead use a DT property in the display controller DT node ? > >>> + */ > >>> +int drm_bridge_input_formats(struct drm_bridge *bridge, > >>> + const u32 **bus_formats) > >>> +{ > >>> + int ret = 0; > >>> + > >>> + if (!bridge) > >>> + return 0; > >>> + > >>> + if (bridge->funcs->input_formats) > >>> + ret = bridge->funcs->input_formats(bridge, bus_formats); > >>> + > >>> + return ret ?: drm_bridge_input_formats(bridge->next, bus_formats); > >> > >> See my comment on the call propagation down in the pipeline. > >> > >>> +} > >>> +EXPORT_SYMBOL(drm_bridge_input_formats); > >>> + > >>> #ifdef CONFIG_OF > >>> /** > >>> * of_drm_find_bridge - find the bridge corresponding to the device > >>> node in > >>> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h > >>> index 682d01ba920c..ae8d3c4af0b8 100644 > >>> --- a/include/drm/drm_bridge.h > >>> +++ b/include/drm/drm_bridge.h > >>> @@ -220,6 +220,22 @@ struct drm_bridge_funcs { > >>> * The enable callback is optional. > >>> */ > >>> void (*enable)(struct drm_bridge *bridge); > >>> + > >>> + /** > >>> + * @input_formats: > >>> + * > >>> + * The callback reports the expected bus input formats of the > >>> bridge. > >>> + * > >>> + * The @input_formats callback is optional. The bridge is assumed to > >>> + * not convert the bus format if the callback is not installed. > >>> + * > >>> + * RETURNS: > >>> + * > >>> + * Zero if the bridge does not convert the bus format, otherwise the > >>> + * number of bus input formats returned in &bus_formats. > >>> + */ > >>> + int (*input_formats)(struct drm_bridge *bridge, > >>> + const u32 **bus_formats); > >> > >> Consider g_fmt() here as well, or a function name that captures that we > >> want to know the supported format (and possibly configure it as well > >> one day, if ever possible). > > > > The naming here should obviously follow the naming of the exported > > function. > > > >>> }; > >>> > >>> /** > >>> @@ -263,6 +279,8 @@ void drm_bridge_mode_set(struct drm_bridge *bridge, > >>> struct drm_display_mode *adjusted_mode); > >>> void drm_bridge_pre_enable(struct drm_bridge *bridge); > >>> void drm_bridge_enable(struct drm_bridge *bridge); > >>> +int drm_bridge_input_formats(struct drm_bridge *bridge, > >>> + const u32 **bus_formats); > >>> > >>> #ifdef CONFIG_DRM_PANEL_BRIDGE > >> struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel, -- Regards, Laurent Pinchart From mboxrd@z Thu Jan 1 00:00:00 1970 From: Laurent Pinchart Subject: Re: [PATCH v2 2/5] drm: bridge: add API to query the expected input formats of bridges Date: Wed, 04 Apr 2018 16:07:37 +0300 Message-ID: <1811029.jLvDxETu2H@avalon> References: <20180326212447.7380-1-peda@axentia.se> <20180327130231.GO27746@w540> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Return-path: In-Reply-To: <20180327130231.GO27746@w540> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" To: jacopo mondi Cc: Mark Rutland , Boris Brezillon , Alexandre Belloni , devicetree@vger.kernel.org, David Airlie , linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org, Nicolas Ferre , Rob Herring , Daniel Vetter , Peter Rosin , linux-arm-kernel@lists.infradead.org List-Id: devicetree@vger.kernel.org SGVsbG8sCgpGaXJzdCBvZiBhbGwsIHRoYW5rIHlvdSBmb3IgdGhlIHBhdGNoLiBUaGlzIGdlbmVy YXRlcyBtb3JlIGRpc2N1c3Npb24gdGhhbiBJIApoYWQgYW50aWNpcGF0ZWQsIHdoaWNoIGlzIGJv dGggZ29vZCBhbmQgYmFkLiBJJ2xsIGNvbW1lbnQgdGhyb3VnaCB0aGUgZS1tYWlsLCAKYW5kIHRy eSB0byBleHBsYWluIGJvdGggbXkgaW5pdGlhbCBpZGVhLCBhbmQgYWxzbyB3aGVyZSBpdCBjb3Vs ZCBsZWFkIHVzLgoKT24gVHVlc2RheSwgMjcgTWFyY2ggMjAxOCAxNjowMjozMSBFRVNUIGphY29w byBtb25kaSB3cm90ZToKPiBPbiBUdWUsIE1hciAyNywgMjAxOCBhdCAwMjoxMjo0MlBNICswMjAw LCBQZXRlciBSb3NpbiB3cm90ZToKPiA+IE9uIDIwMTgtMDMtMjcgMTE6NDcsIGphY29wbyBtb25k aSB3cm90ZToKPiA+PiBPbiBNb24sIE1hciAyNiwgMjAxOCBhdCAxMToyNDo0NFBNICswMjAwLCBQ ZXRlciBSb3NpbiB3cm90ZToKPiA+Pj4gQnJpZGdlcyBtYXkgYWZmZWN0IHRoZSByZXF1aXJlZCBi dXMgb3V0cHV0IGZvcm1hdCBvZiB0aGUgZW5jb2RlciwgaW4KPiA+Pj4gd2hpY2ggY2FzZSBpdCBt YXkgYmUgd3JvbmcgdG8gdXNlIHRoZSBvdXRwdXQgZm9ybWF0IG9mIHRoZSBwYW5lbCBvcgo+ID4+ PiBjb25uZWN0b3IgYXMgaXMuIEFkZCBpbmZyYXN0cnVjdHVyZSB0byBhZGRyZXNzIHRoaXMgcHJv YmxlbS4KPiA+PiAKPiA+PiBCcmlkZ2VzIG5vdCBvbmx5IGFmZmVjdCB0aGUgZm9ybWF0IGV4cGVj dGVkIGJ5IHRoZSBjb25uZWN0b3IgYXQgdGhlCj4gPj4gZW5kIG9mIHRoZSBkaXNwbGF5IHBpcGVs aW5lLCB0aGV5IG1heSBwZXJmb3JtIGVuY29kaW5nL2RlY29kaW5nCj4gPj4gYmV0d2VlbiBwcm90 b2NvbHMgYW5kIHRoZWlyIGFjY2VwdGVkIGlucHV0IGZvcm1hdHMgbWF5IGJlIHVucmVsYXRlZCB0 bwo+ID4+IHRoZSBjb25uZWN0b3IgYXQgdGhlIGVuZCBvZiB0aGUgcGlwZWxpbmUgYXMgdGhlcmUg bWF5IGFuIGFyYml0cmFyeQo+ID4+IG51bWJlciBvZiBicmlkZ2VzIGluIGJldHdlZW4uCj4gPj4g Cj4gPj4gRWcuCj4gPj4gCj4gPj4gRU5DT0RFUiAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgIENPTk5FQ1RPUgo+ID4+IAo+ID4+IHxEVSBMVkRTfCAtPmx2ZHMt PiB8VEhDNjN8IC0+cmdiLT4gfEFEVjc1MTF8IC0+aGRtaS0+IHxIRE1JIGNvbm5lY3RvcnwKPiA+ PiAKPiA+PiBUaGUgZmFjdCB0aGF0IFRIQzYzIHdhbnRzIGEgc3BlY2lmaWMgTFZEUyBpbnB1dCBm b3JtYXQgaXMgdW5yZWxhdGVkIHRvCj4gPj4gdGhlIGZvcm1hdCByZXF1aXJlZCBieSB0aGUgSERN SSBjb25uZWN0b3IgYXQgdGhlIGVuZCBvZiB0aGUgcGlwZWxpbmUuCj4gPj4gCj4gPj4gSSB3b3Vs ZCBqdXN0IHN0YXRlIGhlcmUgdGhhdCBicmlkZ2VzIG5lZWQgYSB3YXkgdG8gcmVwb3J0IHRoZWly Cj4gPj4gYWNjZXB0ZWQgbWVkaWEgYnVzIGZvcm1hdHMsIGFuZCB0aGlzIHBhdGNoIGV4dGVuZHMg dGhlIERSTSBCcmlkZ2UgQVBJcwo+ID4+IHRvIGltcGxlbWVudCB0aGF0Lgo+ID4gCj4gPiBZZXMs IEkgY2FuIGFkZCBzb21lIHdvcmRzLCBidXQgSSB3b3VsZCBsaWtlIHRvIGNsZWFyIHVwIHRoZSBu YW1pbmcKPiA+IGJlZm9yZSByZS1zcGlubmluZy4KPiA+IAo+ID4+PiBTaWduZWQtb2ZmLWJ5OiBQ ZXRlciBSb3NpbiA8cGVkYUBheGVudGlhLnNlPgo+ID4+PiAtLS0KPiA+Pj4gCj4gPj4+ICBkcml2 ZXJzL2dwdS9kcm0vZHJtX2JyaWRnZS5jIHwgMzIgKysrKysrKysrKysrKysrKysrKysrKysrKysr KysrKysKPiA+Pj4gIGluY2x1ZGUvZHJtL2RybV9icmlkZ2UuaCAgICAgfCAxOCArKysrKysrKysr KysrKysrKysKPiA+PiAgMiBmaWxlcyBjaGFuZ2VkLCA1MCBpbnNlcnRpb25zKCspCj4gPj4+IAo+ ID4+PiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9ncHUvZHJtL2RybV9icmlkZ2UuYwo+ID4+PiBiL2Ry aXZlcnMvZ3B1L2RybS9kcm1fYnJpZGdlLmMKPiA+Pj4gaW5kZXggMTYzOGJmZTk2MjdjLi5mODVl NjFiNzQxNmUgMTAwNjQ0Cj4gPj4+IC0tLSBhL2RyaXZlcnMvZ3B1L2RybS9kcm1fYnJpZGdlLmMK PiA+Pj4gKysrIGIvZHJpdmVycy9ncHUvZHJtL2RybV9icmlkZ2UuYwo+ID4+PiBAQCAtMzQ4LDYg KzM0OCwzOCBAQCB2b2lkIGRybV9icmlkZ2VfZW5hYmxlKHN0cnVjdCBkcm1fYnJpZGdlICpicmlk Z2UpCj4gPj4+IAo+ID4+PiAgfQo+ID4+PiAgRVhQT1JUX1NZTUJPTChkcm1fYnJpZGdlX2VuYWJs ZSk7Cj4gPj4+IAo+ID4+PiArLyoqCj4gPj4+ICsgKiBkcm1fYnJpZGdlX2lucHV0X2Zvcm1hdHMg LSBnZXQgdGhlIGV4cGVjdGVkIGJ1cyBpbnB1dCBmb3JtYXQgb2YgdGhlCj4gPj4+IGJyaWRnZQo+ ID4+IAo+ID4+IEkgbWF5IGJlIGJpYXNlZCBieSB0aGUgVjRMMiBBUElzLCBidXQgdGhpcyBzZWVt cyB0byBtZSB2ZXJ5IG11Y2ggbGlrZQo+ID4+IHNpbWlsYXIgdG8gZ19mbXQvc19mbXQgY2FsbGJh Y2tzIHdlIGhhdmUgdGhlcmUuIEJyaWRnZXMgaGF2ZSBhbiBpbnB1dAo+ID4+IGFuZAo+ID4gCj4g PiBnX2ZtdC9zX2ZtdCBzYXlzIG5vdGhpbmcgdG8gbWUuIEdyYXBoaWNzIGZvcm1hdD8gU291cmNl IEZvcm1hdD8gSSBoYXZlCj4gPiBubyBpZGVhIGlmIHRob3NlIGd1ZXNzZXMgYXJlIGV2ZW4gY2xv c2U/IFNvLCB0aGF0IHNlZW1zIGxpa2UgcG9vciBuYW1pbmcKPiA+IHRvIG1lLiBUaGUgb25seSBy ZWFzb24gSSBzZWUgdG8gZ28gdGhhdCB3YXkgaXMgZm9yIHRoZSBzYWtlIG9mCj4gPiBjb25zaXN0 ZW5jeS4KPiAKPiBTb3JyeSwgSSB3YXNuJ3QgY2xlYXIgaGVyZS4KPiAKPiBUbyBtZSB0aGlzIG9w ZXJhdGlvbiBzZWVtcyBsaWtlIGEgImdldCBmb3JtYXQiIGFuZCBJIHNlZSBzcGFjZSBmb3IKPiBm dXR1cmUgaW1wbGVtZW50YXRpb24gb2YgInNldCBmb3JtYXQiIG9wZXJhdGlvbnMgIGFuZCBhbHNv Cj4gImVudW1fZm9ybWF0cyIgdG8gaW1wbGVtZW50IGZvcm1hdCBuZWdvdGlhdGlvbiBiZXR3ZWVu IGJyaWRnZXMuLi4KCkEgYml0IG9mIGNvbnRleHQgaXMgcHJvYmFibHkgbmVlZGVkIGhlcmUgdG8g YnJpZGdlIChubyBwdW4gaW50ZW5kZWQpIERSTSBhbmQgClY0TDIuCgpPbiB0aGUgVjRMMiBzaWRl IHdlIGhhdmUgYW4gb2JqZWN0LCBuYW1lZCB2NGwyX3N1YmRldiwgdGhhdCBpcyBhbmFsb2dvdXMg dG8gCmRybV9icmlkZ2UuIEEgdjRsMl9zdWJkZXYgbW9kZWxzIGEgY29tcG9uZW50IGluIGEgdmlk ZW8gcGlwZWxpbmUsIHVzaW5nIAphYnN0cmFjdCBvcGVyYXRpb25zIGluIGEgc2ltaWxhciBmYXNo aW9uIHRvIHRoZSBkcm1fYnJpZGdlX2Z1bmNzLiBUaGVyZSBhcmUsIApob3dldmVyLCBzZXZlcmFs IG1ham9yIGRpZmZlcmVuY2VzIGJldHdlZW4gZHJtX2JyaWRnZSBhbmQgdjRsMl9zdWJkZXYuCgpk cm1fYnJpZGdlIG1vZGVscyBhIHBhcnRpY3VsYXIga2luZCBvZiBjb21wb25lbnQsIG5hbWVseSB2 aWRlbyBlbmNvZGVycywgCmRlY29kZXJzIG9yIHRyYW5zY29kZXJzLiBBIGJyaWRnZSBpcyB0aHVz IGJhc2VkIG9uIHRoZSBpbXBsaWNpdCBub3Rpb24gb2YgCmhhdmluZyBhIHNpbmdsZSBpbnB1dCBh bmQgYSBzaW5nbGUgb3V0cHV0LCBuZWl0aGVyIG9mIHRoZW0gZXhwb3NlZCBleHBsaWNpdGx5LgoK djRsMl9zdWJkZXYgbW9kZWxzIGFueSB0eXBlIG9mIGNvbXBvbmVudCBpbiBhIHZpZGVvIHBpcGVs aW5lIGFuZCBmb3IgdGhhdCAKcmVhc29uIGhhcyBhIHZhcmlhYmxlIG51bWJlciBvZiBpbnB1dHMg YW5kIG91dHB1dHMuIFRoZSBpbnB1dHMgYW5kIG91dHB1dHMgYXJlIApleHBvc2VkIGV4cGxpY2l0 bHkgdGhyb3VnaCB0aGUgdjRsMl9zdWJkZXYgQVBJIChpbiB0ZXJtcyBvZiB0aGUgbnVtYmVyIG9m IAppbnB1dHMvb3V0cHV0cywgdGhlaXIgdHlwZSwgYW5kIGhvdyB0aGV5IGludGVyYWN0IHdpdGgg dGhlIHY0bDJfc3ViZGV2IApvcGVyYXRpb25zKS4KCkFzIGRybV9icmlkZ2UgbW9kZWxzIG9uZSBw YXJ0aWN1bGFyIGtpbmQgb2YgY29tcG9uZW50LCB0aGUgYnJpZGdlIG9wZXJhdGlvbnMgCmFyZSB0 YWlsb3JlZCB0byB0aGUgZmVhdHVyZSBvZiB0aG9zZSBjb21wb25lbnRzLiBOb3QgYWxsIG9wZXJh dGlvbnMgYXJlIAptYW5kYXRvcnkgKHByZV9lbmFibGUgb3IgcG9zdF9kaXNhYmxlIGFyZSBvcHRp b25hbCBmb3IgaW5zdGFuY2UpLCBidXQgdGhleSBhbGwgCmFwcGx5IHRvIGFsbCBicmlkZ2VzIGNv bmNlcHR1YWxseS4KCkFzIHY0bDJfc3ViZGV2IG1vZGVscyBhbnkgdHlwZSBvZiBjb21wb25lbnQs IHRoZSBzdWJkZXYgb3BlcmF0aW9ucyBoYXZlIHRvIApzdXBwb3J0IGEgd2lkZSB2YXJpZXR5IG9m IGRldmljZSBmZWF0dXJlcy4gVGhlcmUgYXJlIHRodXMgbWFueSBtb3JlIApvcGVyYXRpb25zLCBh bmQgbm90IGFsbCBvZiB0aGVtIGFyZSBhcHBsaWNhYmxlIHRvIGFsbCB0eXBlIG9mIHY0bDJfc3Vi ZGV2LiAKT3BlcmF0aW9ucyB0aGF0IGRvbid0IG1ha2Ugc2Vuc2UgZm9yIGEgcGFydGljdWxhciB2 NGwyX3N1YmRldiBpbnN0YW5jZSAodGhpbmsgCmFib3V0IHZpZGVvIHR1bmVyIGNvbnRyb2wgZm9y IGEgY2FtZXJhIHNlbnNvciBmb3IgaW5zdGFuY2UpIGFyZSBzaW1wbHkgbm90IAppbXBsZW1lbnRl ZC4KClRoZSBkcm1fYnJpZGdlIGZyYW1ld29yayBoYXJkY29kZXMgYW4gb3BlcmF0aW9uYWwgbW9k ZWwgZm9yIGJyaWRnZXMuIApPcGVyYXRpb25zIGFyZSBjYWxsZWQgaW4gYSBwYXJ0aWN1bGFyIG9y ZGVyIG9uIGFsbCBicmlkZ2VzIGluIGEgY2hhaW4uIEZvciAKaW5zdGFuY2UgdGhlIGVuYWJsZSBv cGVyYXRpb24gaXMgY2FsbGVkIGZyb20gc291cmNlIHRvIHNpbmsgKGJyaWRnZSBjbG9zZXN0IHRv IAp0aGUgZGlzcGxheSBjb250cm9sbGVyIHRvIGJyaWRnZSBjbG9zZXN0IHRvIHRoZSBjb25uZWN0 b3IpLCB3aGlsZSB0aGUgZGlzYWJsZSAKb3BlcmF0aW9uIGlzIGNhbGxlZCBmcm9tIHNpbmsgdG8g c291cmNlLgoKVGhlIHY0bDJfc3ViZGV2IGZyYW1ld29yayBkb2Vzbid0IGhhcmRjb2RlIGFuIG9w ZXJhdGlvbiBtb2RlbC4gSXQgaXMgdXAgdG8gdGhlIAp0b3AtbGV2ZWwgVjRMMiBkcml2ZXIgKGVx dWl2YWxlbnQgdG8gdGhlIGRpc3BsYXkgY29udHJvbGxlciBkcml2ZXIpIHRvIGNhbGwgCnN1YmRl diBvcGVyYXRpb25zIGluIG9yZGVyIGFwcGxpY2FibGUgZm9yIHRoZSB1c2UgY2FzZXMgaXQgbmVl ZHMgdG8gc3VwcG9ydC4KClRoaXMgYmVpbmcgc2FpZCwgbGV0J3MgdGFsayBhYm91dCBmb3JtYXRz LiBJbiBWNEwyIGEgdjRsMl9zdWJkZXYgZXhwb3NlcyAKb3BlcmF0aW9ucyB0byBleHBsaWNpdGx5 IGNvbmZpZ3VyZSBmb3JtYXRzIG9uIGFsbCBpbnB1dHMgYW5kIG91dHB1dHMgCihnZW5lcmljYWxs eSBjYWxsZWQgcGFkcyBpbiBWNEwyKS4gVGhyZWUgb3BlcmF0aW9ucyBhcmUgc3VwcG9ydGVkOiAu Z2V0X2ZtdCgpIAp0byByZXRyaWV2ZSB0aGUgY3VycmVudCBmb3JtYXQsIC5zZXRfZm10KCkgdG8g c2V0IGEgZm9ybWF0LCBhbmQgCmVudW1fbWJ1c19jb2RlKCkgYW5kIC5lbnVtX2ZyYW1lX3NpemUo KSB0byBlbnVtZXJhdGUgc3VwcG9ydGVkIGZvcm1hdHMgKEkgCndvbid0IGdvIGludG8gZGV0YWls cyByZWdhcmRpbmcgd2h5IGVudW1lcmF0aW9uIGlzIHNwbGl0IGluIHR3byBvcGVyYXRpb25zLCAK dGhhdCdzIGlycmVsZXZhbnQgaGVyZSkuIEl0IGlzIGltcG9ydGFudCB0byBub3RlIHRoYXQgZm9y bWF0IGVudW1lcmF0aW9uIGlzIAptb3N0bHkgc3RhdGljIChpdCB0ZWxscyB3aGF0IGEgdjRsMl9z dWJkZXYgc3VwcG9ydHMpLCB3aGlsZSBnZXQgYW5kIHNldCAKb3BlcmF0aW9ucyBhcmUgZHluYW1p YyAoZ2V0dGluZyBhbmQgc2V0dGluZywgYW5kIG1vcmUgZ2VuZXJpY2FsbHkgbmVnb3RpYXRpbmcs IApmb3JtYXRzKS4KCkRSTSBoYXMgYW4gQVBJIHRvIGVudW1lcmF0ZSB0aGUgZm9ybWF0cyBzdXBw b3J0ZWQgYnkgY29ubmVjdG9ycyAodGhyb3VnaCB0aGUgCmRybV9jb25uZWN0b3ItPmRpc3BsYXlf aW5mby5idXNfZm9ybWF0cyBmaWVsZCkuIFRoZXJlIGlzIG5vIEFQSSBleHBvc2VkIHRvIAp1c2Vy c3BhY2UgdG8gcGljayB0aGUgZGVzaXJlZCBmb3JtYXQsIG5laXRoZXIgYXQgdGhlIGNvbm5lY3Rv ciBsZXZlbCwgb3IgZm9yIApicmlkZ2VzIGluIHRoZSBwaXBlbGluZSAoYnJpZGdlcyBhcmUgbm90 IGV4cG9zZWQgdG8gdXNlcnNwYWNlIGF0IGFsbCkuIFRoZXJlIAppcyBhbHNvIG5vIGluLWtlcm5l bCBBUEkgdG8gZW51bWVyYXRlIGZvcm1hdHMgc3VwcG9ydGVkIGJ5IGJyaWRnZXMgb3IgdG8gZ2V0 LwpzZXQgYSBicmlkZ2UgZm9ybWF0LiBEaXNwbGF5IGNvbnRyb2xsZXIgYXJlIGV4cGVjdGVkIHRv IHBpY2sgYW4gb3V0cHV0IGZvcm1hdCAKc3VpdGFibGUgZm9yIHRoZSBvdXRwdXQgcGlwZWxpbmUg YmFzZWQgb24gdGhlIGZvcm1hdHMgc3VwcG9ydGVkIGJ5IHRoZSAKY29ubmVjdG9yIGFuZCB0aGUg c2VsZWN0ZWQgZGlzcGxheSBtb2RlLCBhbmQgYnJpZGdlcyBhcmUgZXhwZWN0ZWQgdG8ganVzdCB3 b3JrIAp3aXRob3V0IG5lZWRpbmcgdG8gY2FyZSBhYm91dCBmb3JtYXRzLgoKVGhpcyBtb2RlbCBp cyBzdGFydGluZyB0byBzaG93IGl0cyBzaG9ydGNvbWluZ3Mgbm93IHRoYXQgd2UgbmVlZCB0byBz dXBwb3J0IApicmlkZ2VzIHRoYXQgY29udmVydCBmb3JtYXRzLiBJbiBKYWNvcG8ncyBjYXNlLCBh biBMVkRTIGRlY29kZXIgdHJhbnNmb3JtcyAKTFZEUyBSR0IgdG8gcGFyYWxsZWwgUkdCLCBhbmQg dGhlIGRpc3BsYXkgY29udHJvbGxlciBuZWVkcyB0byBrbm93IHdoaWNoIExWRFMgCmZvcm1hdCB0 byBvdXRwdXQgYmFzZWQgb24gd2hhdCB0aGUgYnJpZGdlIGV4cGVjdHMuIEluIFBldGVyJ3MgY2Fz ZSwgYW4gTFZEUyAKZW5jb2RlciB0cmFuc2ZlciAyNC1iaXQgUkdCIHRvIExWRFMgUkdCLCBidXQg aGFzIHRoZSBMU0JzIHRpZWQgdG8gZ3JvdW5kIG9uIAp0aGUgaW5wdXQgc2lkZSwgYW5kIHRodXMg cmVxdWlyZXMgdGhlIGRpc3BsYXkgY29udHJvbGxlciB0byBvdXRwdXQgUkdCNTY1LgoKTm93IHRo YXQgd2UncmUgZG9uZSB3aXRoIHRoZSBpbnRyb2R1Y3Rpb24sIGxldCdzIG1vdmUgb24sIHBsZWFz ZSBzZWUgYmVsb3cuCgo+ID4+IGFuIG91dHB1dCBmb3JtYXRzLCBhbmQgdGhhdCBjYWxscyBmb3Ig c29tZXRoaW5nIHRoYXQgdGFrZXMgdGhhdCBpbnRvCj4gPj4gYWNjb3VudCwgYXMgd2VsbCBhcyB0 aGV5IG1heSBoYXZlIGRpZmZlcmVudCBpbnB1dCBwb3J0cyB3aXRoIGRpZmZlcmVudAo+ID4+IGFj Y2VwdGVkIGZvcm1hdHMgYnV0IEkgd291bGQgZm9yIG5vdyBzaW1wbGlmeSB0aGlzIHRvIGp1c3Qg J2dfZm10KCknCj4gPiAKPiA+IFlvdSBtZWFuIHJlbmFtZSB0aGUgZnVuY3Rpb24gdG8gZHJtX2Jy aWRnZV9nX2ZtdCgpLCByaWdodD8KPiAKPiBZZWFoLCBzb21ldGhpbmcgbGlrZSAiZHJtX2JyaWRn ZV9nZXRfZm9ybWF0KG5leHRfYnJpZGdlKSIKPiAKPiA+IEFzIGluZGljYXRlZCBhYm92ZSwgSSdt IG5vdCB0aGF0IGZvbmQgb2YgaXQsIGJ1dCBkb24ndCByZWFsbHkgY2FyZQo+ID4gZWl0aGVyLiBN YWludGFpbmVycz8KPiAKPiBJIGRvIG5vdCBjYXJlIG11Y2ggYWJvdXQgdGhlIG5hbWUgdG9vIG9m YywgSSB0aGluayB0aGUgcmVhbCBtZWF0IGlzCj4gYmVsb3cuLi4KPiAKPiA+Pj4gKyAqIEBicmlk Z2U6IGJyaWRnZSBjb250cm9sIHN0cnVjdHVyZQo+ID4+PiArICogQGJ1c19mb3JtYXRzOiB3aGVy ZSB0byBzdG9yZSBhIHBvaW50ZXIgdG8gdGhlIGJ1cyBpbnB1dCBmb3JtYXRzCj4gPj4+ICsgKgo+ ID4+PiArICogQ2FsbHMgdGhlICZkcm1fYnJpZGdlX2Z1bmNzLmlucHV0X2Zvcm1hdHMgb3AgZm9y IHRoZSBmcmlzdCBicmlkZ2UKPiA+Pj4gaW4gdGhlCj4gPj4+ICsgKiBjaGFpbiB0aGF0IGhhcyBy ZWdpc3RlcmVkIHRoaXMgb3AuCj4gPj4gCj4gPj4gSSdtIG5vdCBzdXJlIHBhc3NpbmcgdGhlIGNh bGwgZG93biB0aGUgcGlwZWxpbmUgaXMgZGVzaXJhYmxlLiBFYWNoCj4gPj4gY29tcG9uZW50IHNo b3VsZCBtYWtlIHN1cmUgaXRzIG91dHB1dCBmb3JtYXQgaXMgYWNjZXB0ZWQgYXMgdGhlIG5leHQK PiA+PiBicmlkZ2UgaW5wdXQgZm9ybWF0LCBwYXNzaW5nIHRoZSBjYWxsIHRvIHRoZSBuZXh0IGJy aWRnZSBpcyBub3QKPiA+PiBkaWZmZXJlbnQgdGhhdCBnZXR0aW5nIHRvIHRoZSBjb25uZWN0b3Ig YXQgdGhlIGVuZCBvZiB0aGUgcGlwZWxpbmUgYW5kCj4gPj4gcmV0dXJuIHRvIHRoZSBpbml0aWFs IGNhbGxlciBpdHMgc3VwcG9ydGVkIGZvcm1hdC4gRG8geW91IGFncmVlIHdpdGgKPiA+PiB0aGlz Pwo+ID4gCj4gPiBOb3QgcGFzc2luZyBkb3duIHRoZSBjYWxsIGRvZXMgb25lIG9mIHR3byB0aGlu Z3MuIEVpdGhlciBhbGwgYnJpZGdlcyBoYXZlCj4gPiB0byBpbXBsZW1lbnQgdGhlIGNhbGwgb3Ig YWxsIHVzZXJzIGhhdmUgdG8gd2FsayB0aGUgcGlwZWxpbmUgIm1hbnVhbGx5Ii4KPiA+IEkgZG9u J3QgbGlrZSBlaXRoZXIgb3IgdGhvc2Ugb3B0aW9ucywgc28gSSBzdGlsbCB0aGluayBpdCBpcyBn b29kIHRvCj4gPiBwYXNzIHRoZSBjYWxsIGRvd24gdGhlIHBpcGVsaW5lLgo+ID4gCj4gPiAqdGlt ZSBwYXNzZXMqCj4gPiAKPiA+IE9oLCB5b3UgZG8gbm90IHRoaW5rIGl0IGlzIHVzZWZ1bCBmb3Ig dGhlIGJyaWRnZSB0byBoYXZlIGEgY2FsbGJhY2sgYnV0Cj4gPiBzdGlsbCByZXBvcnQgIm5vIGZv cm1hdCBjaGFuZ2UiLCBhbmQgdGhhdCB0aGUgY2FsbCBkb3duIHRvIHBpcGVsaW5lCj4gPiBzaG91 bGQgb25seSBoYXBwZW4gZm9yIGJyaWRnZXMgdGhhdCBoYXZlIG5vdCBpbXBsZW1lbnRlZCB0aGUg b3AuIEJ1dCBJCj4gPiBkbyB0aGluayB0aGF0IGlzIHVzZWZ1bCwgc2VlIGJlbG93Lgo+ID4gCj4g Pj4+ICsgKgo+ID4+PiArICogTm90ZSB0aGF0IHRoZSBicmlkZ2UgcGFzc2VkIHNob3VsZCBub3Jt YWxseSBiZSB0aGUgYnJpZGdlIGNsb3Nlc3QgdG8KPiA+Pj4gdGhlCj4gPj4+ICsgKiBlbmNvZGVy LCBidXQgcG9zc2libHkgdGhlIGJyaWRnZSBjbG9zZXN0IHRvIGFuIGludGVybWVkaWF0ZSBicmlk Z2UKPiA+Pj4gaW4KPiA+Pj4gKyAqIGNvbnZvbHV0ZWQgY2FzZXMuCj4gPj4+ICsgKgo+ID4+IAo+ ID4+IEFzIEkgc2VlIHRoaXMsIGFueSBicmlkZ2UgaW4gdGhlIGFyYml0cmFyeSBsb25nIHBpcGVs aW5lIHNob3VsZCBjYWxsCj4gPj4gdGhpcyBvcGVyYXRpb24gb24gbmV4dCBicmlkZ2UgaWYgaXQg c3VwcG9ydHMgZGlmZmVyZW50IG91dHB1dCBmb3JtYXRzLgo+ID4+IEllLiBJIHdvdWxkIG5vdCBu YW1lIGhlcmUgdGhlIGVuY29kZXIgbm9yIHJlZmVyIHRvIHRoZSBicmlkZ2UgcG9zaXRpb24KPiA+ PiBpbiB0aGUgcGlwZWxpbmUuCj4gPiAKPiA+IE9rLCBJIGNhbiBjaGFuZ2UgdGhhdCwgaXQganVz dCBzZWVtZWQgbGlrZSBhIGNvbnZvbHV0ZWQgY2FzZSB0byBtZS4KPiA+IEkgbWVhbiwgaWYgdGhp cyB3YXMgYSByZWFsIGlzc3VlIGFuZCBjb21wbGljYXRlZCBwaXBlbGluZXMgd2VyZQo+ID4gY29t bW9uLCBzb21ldGhpbmcgYWxvbmcgdGhlIGxpbmVzIG9mIHRoaXMgcGF0Y2ggc2VyaWVzIHdvdWxk IGJlCj4gPiBhdmFpbGFibGUgYWxyZWFkeS4gUmlnaHQ/IEkgZ3Vlc3Mgbm90LCBidXQgaG93IHRo ZSAmIy8lIyBoYXZlIHBlb3BsZQo+ID4gYmVlbiBjb3Bpbmc/Cj4gPiAKPiA+Pj4gKyAqIFJFVFVS TlM6Cj4gPj4+ICsgKiBUaGUgbnVtYmVyIG9mIGJ1cyBpbnB1dCBmb3JtYXRzIHRoZSBicmlkZ2Ug YWNjZXB0cy4gWmVybyBtZWFucyB0aGF0Cj4gPj4+ICsgKiB0aGUgY2hhaW4gb2YgYnJpZGdlcyBh cmUgbm90IGNvbnZlcnRpbmcgdGhlIGJ1cyBmb3JtYXQgYW5kIHRoYXQgdGhlCj4gPj4+ICsgKiBm b3JtYXQgb2YgdGhlIGRybV9jb25uZWN0b3Igc2hvdWxkIGJlIHVzZWQuCj4gPj4gCj4gPj4gSG93 IGRvIHdlIGdldCB0byB0aGUgY29ubmVjdG9yIGZvcm1hdCBmcm9tIGEgYnJpZGdlIHRoYXQgaGFz IG1heWJlCj4gPj4gb3RoZXIgY29tcG9uZW50cyBpbiBiZXR3ZWVuIGluIHRoZSBwaXBlbGluZT8K PiA+PiAKPiA+PiBJZiBhIGJyaWRnZSBkbyBub3QgcmVwb3J0IGFueSBzdXBwb3J0ZWQgZm9ybWF0 LCBpdCB3b24ndCBpbXBsZW1lbnQKPiA+PiB0aGlzIGNhbGxiYWNrIGFuZCB0aGluZ3Mgd2lsbCB3 b3JrIGFzIHRoZXkgd29yayB0b2RheS4KPiA+IAo+ID4gVW5sZXNzIHRoZSBicmlkZ2Ugb3B0aW9u YWxseSBjaGFuZ2VzIHRoZSBmb3JtYXQuIElmIHRoZSBicmlkZ2UgaGFzIG5vCj4gPiB3YXkgdG8g c2F5ICJubyBmb3JtYXQgY2hhbmdlIiBldmVuIHdpdGggdGhlIGNhbGxiYWNrIGluIHBsYWNlLCBp dAo+ID4gaGFzIHRvIGp1Z2dsZSBkaWZmZXJlbnQgb3BzIHN0cnVjdHMsIHdoaWNoIHNlZW1zIGxp a2UgYSBiaWcgaGFtbWVyLgo+ID4gU28sIEknbSBpbiBmYXZvciBvZiBjYWxsaW5nIGRvd24gdGhl IHBpcGVsaW5lIGluIHR3byBjYXNlcy4gQSkgd2hlbgo+ID4gYSBicmlkZ2UgZG9lcyBub3QgaW1w bGVtZW50IHRoZSBvcCBhbmQgQikgd2hlbiB0aGUgb3AgcmV0dXJucyB6ZXJvLgo+IAo+IFdoeSBk byB5b3UgdGhpbmsgdGhlIGJyaWRnZSBmb3JtYXQgY29udmVyc2lvbiBwbGF5cyBhIHJvbGUgaGVy ZT8KPiAKPiBNYXliZSBoZXJlJ3Mgd2hlcmUgSSBsb3N0IHlvdSwgcG9zc2libHkgYmVjYXVzZSBv ZiBteSBsaW1pdGVkCj4ga25vd2xlZGdlIG9mIHRoZSBEUk0gcmVhbG0gYW5kIGl0cyBhY3R1YWwg dXNlIGNhc2VzLgo+IAo+IEFzIEkgc2VlIGl0LCB0aGlzIG5ldyBBUEkgYWxsb3dzIHR3byBicmlk Z2VzIHRvIHN5bmNocm9uaXplIG9uIHdoaWNoCj4gaW1hZ2UgZm9ybWF0IG9yIExWRFMgbW9kZSAn YnJpZGdlJyBzaG91bGQgb3V0cHV0IHRvICduZXh0X2JyaWRnZScKPiBpbnB1dC4KPiAKPiBUaGUg Im1vZGVfc2V0IiBjYWxsYmFjayB3YWxrcyBhbGwgZWxlbWVudCBvZiB0aGUgZGlzcGxheSBwaXBl bGluZSwKPiBhbmQgd2hlbiBvbmUgY29tcG9uZW50IGhhcyB0byBzZWxlY3Qgd2hpY2ggaW1hZ2Ug Zm9ybWF0IG9yIExWRFMgbW9kZQo+IHRvIG91dHB1dCB0byBpdHMgbmV4dCBraW4sIGlmIHRoZSBu ZXh0IG9uZSBpcyBhIHBhbmVsIGl0IGluc3BlY3RzIHRoZQo+IGRpc3BsYXlfaW5mbyBmaWVsZCwg aXQgaXQncyBhIGJyaWRnZSBpdCB1c2VzIHRoaXMgbmV3IEFQSSB0byBnZXQgdGhlCj4gZm9ybWF0 IGl0IGFjY2VwdHMuCj4gCj4gSWYgdGhlIG5leHQgYnJpZGdlIGRvZXMgbm90IGltcGxlbWVudCB0 aGlzIGNhbGxiYWNrLCB0aGluZ3Mgd29yayBhcyB0aGV5Cj4gZG8gdG9kYXkgKGluIG91ciBzcGVj aWZpYyB1c2UgY2FzZSwgYnkgY2hhbmNlIDopCj4gCj4gPiBNYWludGFpbmVycz8KPiAKPiBZZXMs IGxldCdzIHNjYWxlIHRvIG1vcmUga25vd2xlZGdlYWJsZSBwZW9wbGUgdGhhbiBtZSwgYXMgSSBn YXZlIG15Cj4gb3BpbmlvbiBhbHJlYWR5IGJ1dCBpdCBpcyBiYXNlZCBvbiB0aGUgc2luZ2xlIHVz ZSBjYXNlIEkga25vdyBmb3IKPiByZWFsLgoKSSB0aGluayBpdCdzIGltcG9ydGFudCBoZXJlIHRv IHRha2UgYSBzdGVwIGJhY2sgYW5kIGxvb2sgd2hlcmUgd2UgY29tZSBmcm9tLCAKd2hhdCB3ZSBu ZWVkLCBhbmQgd2hlcmUgd2Ugd2FudCB0byBnby4KClRoZSBmaXJzdCBwYXJ0IGlzIGVhc3kuIEFz IGV4cGxhaW5lZCBhYm92ZSwgdGhlIGN1cnJlbnQgc3RhdGUgaXMgdGhhdCB3ZSBrbm93IAp3aGF0 IGZvcm1hdHMgYSBjb25uZWN0b3Igc3VwcG9ydHMsIGFuZCB3ZSBoYXZlIG5vIG90aGVyIEFQSSB3 aGF0c29ldmVyLCAKbmVpdGhlciB0byB1c2Vyc3BhY2Ugb3IgaW5zaWRlIHRoZSBrZXJuZWwsIHRv IGhhbmRsZSBmb3JtYXQgaW4gdGhlIGRpc3BsYXkgCm91dHB1dCBwaXBlbGluZS4KCldoYXQgd2Ug bmVlZCBpcyBhdCBsZWFzdCBzdGF0aWMgZm9ybWF0IGluZm9ybWF0aW9uLiBJbiB0aGUgdHdvIGNh c2VzIGRlc2NyaWJlZCAKYWJvdmUgdGhlIGJyaWRnZSBjb25uZWN0ZWQgdG8gdGhlIGRpc3BsYXkg Y29udHJvbGxlciBvdXRwdXQgcmVxdWlyZXMgYSAKc3BlY2lmaWMgZm9ybWF0IChSR0I1NjUgZm9y IFBldGVyLCBMVkRTIEpFSURBIGZvciBKYWNvcG8pLiBUaGVyZSBpcyBubyBuZWVkIHRvIAp3YWxr IHRvIHBpcGVsaW5lIGFuZCBxdWVyeSBhbGwgYnJpZGdlcywgd2UgY2FuIGdldCB0aGUgbmVjZXNz YXJ5IGluZm9ybWF0aW9uIApmcm9tIHRoZSBmaXJzdCBicmlkZ2UgaW4gdGhlIGNoYWluLgoKV2hl cmUgd2Ugd2FudCB0byBnbyBpcyB0aGUgcmVhbCBxdWVzdGlvbi4gV2UgbmVlZCBhdCBsZWFzdCBz dGF0aWMgaW5mb3JtYXRpb24sIApzbyB3ZSBjb3VsZCBleHBvc2UgaXQgdGhyb3VnaCBhIG5ldyBi dXNfZm9ybWF0cyBmaWVsZCBpbiB0aGUgZHJtX2JyaWRnZSAKc3RydWN0dXJlLCBzaW1pbGFyIHRv IHRoZSBidXNfZm9ybWF0cyBmaWVsZCBpbiB0aGUgZHJtX2Rpc3BsYXlfaW5mbyBzdHJ1Y3R1cmUu IApUaGlzIHdvdWxkIHNvbHZlIHRoZSB0d28gcHJvYmxlbXMgYXQgaGFuZC4gSG93ZXZlciwgc3Vj aCBhIHNvbHV0aW9uIHdvdWxkbid0IAphbGxvdyB1cyB0byBjb25maWd1cmUgZm9ybWF0cyB0aHJv dWdoIHRoZSBwaXBlbGluZSwgYW5kIHdvdWxkbid0IGFsbG93IHVzIHRvIApxdWVyeSB0aGUgZm9y bWF0IGEgYnJpZGdlIG5lZWRzIGJhc2VkIG9uIHRoZSBmb3JtYXQgbmVlZGVkIGJ5IHRoZSBuZXh0 IGJyaWRnZSAKaW4gdGhlIGNoYWluLiBJdCB3b3VsZCB0aHVzIGJlIGxpbWl0ZWQgdG8gc3BlY2lm aWMgY2FzZXMsIGFuZCBvbmUgY291bGQgYXJndWUgCnRoYXQgaXQgd291bGQgYmUgdG9vIGxpbWl0 ZWQuCgpBIG1vcmUgZ2VuZXJpYyBzb2x1dGlvbiBtaWdodCBiZSBiZXR0ZXIsIHRvIHN1cHBvcnQg ZHluYW1pYyBuZWdvdGlhdGlvbiBvZiAKZm9ybWF0cyB0aHJvdWdoIHRoZSBwaXBlbGluZS4gSSBi ZWxpZXZlIHRoaXMgd291bGQgYmUgbmVlZGVkIGluIHRoZSBsb25nIHJ1biAKYW55d2F5LCBzbyBp dCdzIHRlbXB0aW5nIHRvIGdpdmUgaXQgYSB0cnkgdG9kYXkuIEhvd2V2ZXIsIGFzIHdlIGRvbid0 IGhhdmUgYW55IApyZWFsIHVzZSBjYXNlIHlldCwgb25lIG1pZ2h0IGFyZ3VlIHRoYXQgd2Ugd291 bGQgZGVzaWduIHRoZSBBUEkgaW5jb3JyZWN0bHksIAp3aGljaCBJIGNhbid0IGNvbXBsZXRlbHkg ZGlzYWdyZWUgd2l0aC4gTm9uZXRoZWxlc3MsIGlmIHdlIHdlcmUgdG8gZGVzaWduIHN1Y2ggCmFu IEFQSSwgSSBhZ3JlZSB3aXRoIERhbmllbCB0aGF0IGl0IHNob3VsZCBiZSBiYXNlZCBvbiBicmlk Z2Ugc3RhdGVzLiBTdWNoIGEgCnNvbHV0aW9uIHdvdWxkIGFsbG93IG5lZ290aWF0aW9uIG9mIGZv cm1hdHMgdGhyb3VnaCB0aGUgcGlwZWxpbmUgKHVzaW5nIGEgeWV0IAp0byBiZSBkZXNpZ25lZCBw cm9jZXNzKSwgYW5kIHdvdWxkIHRoZW4gYWxsb3cgdGhlIGRpc3BsYXkgY29udHJvbGxlciB0byAK cmV0cmlldmUgdGhlIG5lZ290aWF0ZWQgZm9ybWF0IGV4cGVjdGVkIGJ5IHRoZSBmaXJzdCBicmlk Z2UgZnJvbSB0aGUgYnJpZGdlIApzdGF0ZS4KCkkgZG9uJ3QgdGhpbmsgd2Ugd291bGQgZGVzaWdu IHRoZSBBUEkgYmV0d2VlbiB0aGUgZGlzcGxheSBjb250cm9sbGVyIGFuZCB0aGUgCmZpcnN0IGJy aWRnZSB3cm9uZyAoaXQgd291bGQganVzdCBiZSBhIG1hdHRlciBvZiByZWFkaW5nIHRoZSBuZWdv dGlhdGVkIGZvcm1hdCAKZnJvbSB0aGUgZmlyc3QgYnJpZGdlJ3Mgc3RhdGUsIHRoZXJlJ3MgbGl0 dGxlIHJvb20gZm9yIGRlc2lnbiBpc3N1ZXMgdGhlcmUpLCAKYnV0IHRoZSBmb3JtYXQgbmVnb3Rp YXRpb24gdGhyb3VnaCB0aGUgcGlwZWxpbmUgd291bGQgbmVlZCBtb3JlIHRob3VnaHRzLiBPbmUg Cm9wdGlvbiAoanVzdCB0aGlua2luZyBvdXQgbG91ZCkgd291bGQgYmUgdG8gc3RhcnQgd2l0aCB0 aGUgY29ubmVjdG9yIGZvcm1hdCwgCmFuZCB0aGVuIGFzayBlYWNoIGJyaWRnZSBpbiB0aGUgY2hh aW4sIGZyb20gbGFzdCB0byBmaXJzdCwgZm9yIHRoZSBpbnB1dCAKZm9ybWF0IGl0IG5lZWRzIHRv IGdlbmVyYXRlIHRoZSBleHBlY3RlZCBvdXRwdXQgZm9ybWF0LiBNb3JlIGNvbXBsZXggc2NoZW1l cyAKbWlnaHQgYmUgbmVlZGVkLCBlc3BlY2lhbGx5IHdoZW4gdGhlIGNvbm5lY3RvciBzdXBwb3J0 cyBtdWx0aXBsZSBmb3JtYXRzLCBvciAKd2hlbiBhIGJyaWRnZSBjYW4gYWNjZXB0IG11bHRpcGxl IGlucHV0IGZvcm1hdHMgdG8gZ2VuZXJhdGUgYSBnaXZlbiBvdXRwdXQgCmZvcm1hdC4gSW4gdGhv c2UgY2FzZXMgcGlja2luZyB0aGUgZmlyc3Qgc3VwcG9ydGVkIGZvcm1hdCBjb3VsZCB3b3JrLCBi dXQgaXQgCm1pZ2h0IG5vdCBhbHdheXMgbGVhZCB0byB0aGUgb3B0aW1hbCBwaXBlbGluZSBjb25m aWd1cmF0aW9uLgoKQW5vdGhlciBwb2ludCBJIHdhbnQgdG8gbWVudGlvbiBpcyB0aGF0IGluIFBl dGVyJ3MgY2FzZSB0aGUgTFZEUyBlbmNvZGVyIApyZXF1aXJlcyBSR0I4ODggYXQgaXRzIGlucHV0 LCBidXQgdGhlIFBDQiByb3V0aW5nIHRyYW5zZm9ybXMgUkdCNTY1IHRvIFJHQjg4OCAKYnkgc2hp ZnRpbmcgc2lnbmFscyBhbmQgdHlpbmcgdGhlIExTQnMgdG8gZ3JvdW5kLiBUaGF0IGluZm9ybWF0 aW9uIHJlYWxseSAKYmVsb25ncyB0byBEVCBhcyBpdCBpc24ndCBpbnRyaW5zaWMgdG8gZWl0aGVy IHRoZSBkaXNwbGF5IGNvbnRyb2xsZXIgb3IgdGhlIApMVkRTIGVuY29kZXIuIEkgaG93ZXZlciB3 b25kZXIgd2hldGhlciBpdCBzaG91bGQgYmUgZXhwcmVzc2VkIGFzIGEgZm9ybWF0LCBvciAKaW4g YSBkaWZmZXJlbnQgZm9ybS4gSW4gVjRMMiB3ZSBoYXZlIHN0YW5kYXJkaXplZCBidXMtd2lkdGgg YW5kIGRhdGEtc2hpZnQgRFQgCnByb3BlcnRpZXMgKHNlZSBEb2N1bWVudGF0aW9uL2RldmljZXRy ZWUvYmluZGluZ3MvbWVkaWEvdmlkZW8taW50ZXJmYWNlcy50eHQpIAp0byBleHBvc2UgaG93IHNp Z25hbHMgYXJlIGNvbm5lY3RlZCBpbiB0aGUgUENCLiBUaGlzIGFsbG93cyBleHByZXNzaW5nIAp0 cmFuc2Zvcm1hdGlvbnMgaW5zdGVhZCBvZiBoYXJkY29kaW5nIGZvcm1hdHMsIHdoaWNoIGNhbiBi ZSB1c2VmdWwgaWYgdGhlIApicmlkZ2UgY2FuIHN0aWxsIGFjY2VwdCBtdWx0aXBsZSBpbnB1dCBm b3JtYXRzLiBPbmUgZXhhbXBsZSBvZiB0aGlzIGlzIHJhdyAKY2FtZXJhIHNlbnNvcnMgdGhhdCBj YW4gb3V0cHV0IG11bHRpcGxlIGJheWVyIHBhdHRlcm5zIChCR0dSLCBHQlJHLCBHUkJHIG9yIApS R0dCKSB3aXRoIDEwIGJpdHMgcGVyIHBpeGVsLCBjb21iaW5lZCB3aXRoIGEgUENCIHRoYXQgY29u bmVjdHMgRFs5OjJdIG9mIHRoZSAKc2Vuc29yIHRvIERbNzowXSBvZiB0aGUgY2FtZXJhIGNvbnRy b2xsZXIuIEJHR1IxMCB3b3VsZCBiZSB0dXJuZWQgaW50byBCR0dSOCwgCkdCUkcxMCBpbnRvIEdC Ukc4LCBhbmQgc28gb24uIFRoZSBjYW1lcmEgY29udHJvbGxlciBzaG91bGQgdGh1cyBub3QgaGFy ZGNvZGUgYSAKcGFydGljdWxhciBmb3JtYXQgaW4gRFQgYXMgdGhlcmUgYXJlIG11bHRpcGxlIG9w dGlvbnMgdGhhdCBjYW4gYmUgc2VsZWN0ZWQgYXQgCnJ1bnRpbWUuIEkgY2FuIGltYWdpbmUgYSBz aW1pbGFyIHNldHVwIGZvciB0aGUgZGlzcGxheSwgd2l0aCBhIGJyaWRnZSAKY29uZmlndXJhYmxl IHRocm91Z2ggSTJDIHRoYXQgY291bGQgYWNjZXB0IGRpZmZlcmVudCBmb3JtYXRzLCBjb21iaW5l ZCB3aXRoIAp0aGUgUENCIHBlcmZvcm1pbmcgc29tZSB3ZWlyZCByb3V0aW5nLgoKRmluYWxseSwg c3RpbGwgcmVnYXJkaW5nIFBldGVyJ3MgY2FzZSwgdGhlIGRlY2lzaW9uIHRvIG91dHB1dCBSR0I1 NjUgaW5zdGVhZCAKb2YgUkdCODg4ICh3aGljaCB0aGUgTFZEUyBlbmNvZGVyIGV4cGVjdHMpIGlz IGR1ZSB0byBQQ0Igcm91dGluZyBiZXR3ZWVuIHRoZSAKZGlzcGxheSBjb250cm9sbGVyIGFuZCB0 aGUgTFZEUyBlbmNvZGVyLiBUaGlzIGlzbid0IGEgcHJvcGVydHkgb2YgdGhlIExWRFMgCmVuY29k ZXIgb3IgdGhlIGRpc3BsYXkgY29udHJvbGxlciwgYnV0IG9mIHRoZWlyIGhhcmR3YXJlIGNvbm5l Y3Rpb24uIFRoaXMgCnBhdGNoIHNlcmllcyB1c2VzIGEgRFQgcHJvcGVydHkgaW4gdGhlIExWRFMg ZW5jb2RlciBEVCBub2RlIHRvIGNvbnZleSB0aGF0IAppbmZvcm1hdGlvbiwgYnV0IHdvdWxkbid0 IGl0IGJlIGVxdWFsbHkgY29ycmVjdCAob3IgaW5jb3JyZWN0IDotKSkgdG8gaW5zdGVhZCAKdXNl IGEgRFQgcHJvcGVydHkgaW4gdGhlIGRpc3BsYXkgY29udHJvbGxlciBEVCBub2RlID8KCj4gPj4+ ICsgKi8KPiA+Pj4gK2ludCBkcm1fYnJpZGdlX2lucHV0X2Zvcm1hdHMoc3RydWN0IGRybV9icmlk Z2UgKmJyaWRnZSwKPiA+Pj4gKwkJCSAgICAgY29uc3QgdTMyICoqYnVzX2Zvcm1hdHMpCj4gPj4+ ICt7Cj4gPj4+ICsJaW50IHJldCA9IDA7Cj4gPj4+ICsKPiA+Pj4gKwlpZiAoIWJyaWRnZSkKPiA+ Pj4gKwkJcmV0dXJuIDA7Cj4gPj4+ICsKPiA+Pj4gKwlpZiAoYnJpZGdlLT5mdW5jcy0+aW5wdXRf Zm9ybWF0cykKPiA+Pj4gKwkJcmV0ID0gYnJpZGdlLT5mdW5jcy0+aW5wdXRfZm9ybWF0cyhicmlk Z2UsIGJ1c19mb3JtYXRzKTsKPiA+Pj4gKwo+ID4+PiArCXJldHVybiByZXQgPzogZHJtX2JyaWRn ZV9pbnB1dF9mb3JtYXRzKGJyaWRnZS0+bmV4dCwgYnVzX2Zvcm1hdHMpOwo+ID4+IAo+ID4+IFNl ZSBteSBjb21tZW50IG9uIHRoZSBjYWxsIHByb3BhZ2F0aW9uIGRvd24gaW4gdGhlIHBpcGVsaW5l Lgo+ID4+IAo+ID4+PiArfQo+ID4+PiArRVhQT1JUX1NZTUJPTChkcm1fYnJpZGdlX2lucHV0X2Zv cm1hdHMpOwo+ID4+PiArCj4gPj4+ICAjaWZkZWYgQ09ORklHX09GCj4gPj4+ICAvKioKPiA+Pj4g ICAqIG9mX2RybV9maW5kX2JyaWRnZSAtIGZpbmQgdGhlIGJyaWRnZSBjb3JyZXNwb25kaW5nIHRv IHRoZSBkZXZpY2UKPiA+Pj4gICBub2RlIGluCj4gPj4+IGRpZmYgLS1naXQgYS9pbmNsdWRlL2Ry bS9kcm1fYnJpZGdlLmggYi9pbmNsdWRlL2RybS9kcm1fYnJpZGdlLmgKPiA+Pj4gaW5kZXggNjgy ZDAxYmE5MjBjLi5hZThkM2M0YWYwYjggMTAwNjQ0Cj4gPj4+IC0tLSBhL2luY2x1ZGUvZHJtL2Ry bV9icmlkZ2UuaAo+ID4+PiArKysgYi9pbmNsdWRlL2RybS9kcm1fYnJpZGdlLmgKPiA+Pj4gQEAg LTIyMCw2ICsyMjAsMjIgQEAgc3RydWN0IGRybV9icmlkZ2VfZnVuY3Mgewo+ID4+PiAgCSAqIFRo ZSBlbmFibGUgY2FsbGJhY2sgaXMgb3B0aW9uYWwuCj4gPj4+ICAJICovCj4gPj4+ICAJdm9pZCAo KmVuYWJsZSkoc3RydWN0IGRybV9icmlkZ2UgKmJyaWRnZSk7Cj4gPj4+ICsKPiA+Pj4gKwkvKioK PiA+Pj4gKwkgKiBAaW5wdXRfZm9ybWF0czoKPiA+Pj4gKwkgKgo+ID4+PiArCSAqIFRoZSBjYWxs YmFjayByZXBvcnRzIHRoZSBleHBlY3RlZCBidXMgaW5wdXQgZm9ybWF0cyBvZiB0aGUKPiA+Pj4g YnJpZGdlLgo+ID4+PiArCSAqCj4gPj4+ICsJICogVGhlIEBpbnB1dF9mb3JtYXRzIGNhbGxiYWNr IGlzIG9wdGlvbmFsLiBUaGUgYnJpZGdlIGlzIGFzc3VtZWQgdG8KPiA+Pj4gKwkgKiBub3QgY29u dmVydCB0aGUgYnVzIGZvcm1hdCBpZiB0aGUgY2FsbGJhY2sgaXMgbm90IGluc3RhbGxlZC4KPiA+ Pj4gKwkgKgo+ID4+PiArCSAqIFJFVFVSTlM6Cj4gPj4+ICsJICoKPiA+Pj4gKwkgKiBaZXJvIGlm IHRoZSBicmlkZ2UgZG9lcyBub3QgY29udmVydCB0aGUgYnVzIGZvcm1hdCwgb3RoZXJ3aXNlIHRo ZQo+ID4+PiArCSAqIG51bWJlciBvZiBidXMgaW5wdXQgZm9ybWF0cyByZXR1cm5lZCBpbiAmYnVz X2Zvcm1hdHMuCj4gPj4+ICsJICovCj4gPj4+ICsJaW50ICgqaW5wdXRfZm9ybWF0cykoc3RydWN0 IGRybV9icmlkZ2UgKmJyaWRnZSwKPiA+Pj4gKwkJCSAgICAgY29uc3QgdTMyICoqYnVzX2Zvcm1h dHMpOwo+ID4+IAo+ID4+IENvbnNpZGVyIGdfZm10KCkgaGVyZSBhcyB3ZWxsLCBvciBhIGZ1bmN0 aW9uIG5hbWUgdGhhdCBjYXB0dXJlcyB0aGF0IHdlCj4gPj4gd2FudCB0byBrbm93IHRoZSBzdXBw b3J0ZWQgZm9ybWF0IChhbmQgcG9zc2libHkgY29uZmlndXJlIGl0IGFzIHdlbGwKPiA+PiBvbmUg ZGF5LCBpZiBldmVyIHBvc3NpYmxlKS4KPiA+IAo+ID4gVGhlIG5hbWluZyBoZXJlIHNob3VsZCBv YnZpb3VzbHkgZm9sbG93IHRoZSBuYW1pbmcgb2YgdGhlIGV4cG9ydGVkCj4gPiBmdW5jdGlvbi4K PiA+IAo+ID4+PiAgfTsKPiA+Pj4gIAo+ID4+PiAgLyoqCj4gPj4+IEBAIC0yNjMsNiArMjc5LDgg QEAgdm9pZCBkcm1fYnJpZGdlX21vZGVfc2V0KHN0cnVjdCBkcm1fYnJpZGdlICpicmlkZ2UsCj4g Pj4+ICAJCQlzdHJ1Y3QgZHJtX2Rpc3BsYXlfbW9kZSAqYWRqdXN0ZWRfbW9kZSk7Cj4gPj4+ICB2 b2lkIGRybV9icmlkZ2VfcHJlX2VuYWJsZShzdHJ1Y3QgZHJtX2JyaWRnZSAqYnJpZGdlKTsKPiA+ Pj4gIHZvaWQgZHJtX2JyaWRnZV9lbmFibGUoc3RydWN0IGRybV9icmlkZ2UgKmJyaWRnZSk7Cj4g Pj4+ICtpbnQgZHJtX2JyaWRnZV9pbnB1dF9mb3JtYXRzKHN0cnVjdCBkcm1fYnJpZGdlICpicmlk Z2UsCj4gPj4+ICsJCQkgICAgIGNvbnN0IHUzMiAqKmJ1c19mb3JtYXRzKTsKPiA+Pj4gCj4gPj4+ ICAjaWZkZWYgQ09ORklHX0RSTV9QQU5FTF9CUklER0UKPiA+PiAgc3RydWN0IGRybV9icmlkZ2Ug KmRybV9wYW5lbF9icmlkZ2VfYWRkKHN0cnVjdCBkcm1fcGFuZWwgKnBhbmVsLAoKLS0gClJlZ2Fy ZHMsCgpMYXVyZW50IFBpbmNoYXJ0CgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fX19fX19fX19fCmRyaS1kZXZlbCBtYWlsaW5nIGxpc3QKZHJpLWRldmVsQGxpc3RzLmZy ZWVkZXNrdG9wLm9yZwpodHRwczovL2xpc3RzLmZyZWVkZXNrdG9wLm9yZy9tYWlsbWFuL2xpc3Rp bmZvL2RyaS1kZXZlbAo= From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751285AbeDDNHe (ORCPT ); Wed, 4 Apr 2018 09:07:34 -0400 Received: from galahad.ideasonboard.com ([185.26.127.97]:46042 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751216AbeDDNHa (ORCPT ); Wed, 4 Apr 2018 09:07:30 -0400 From: Laurent Pinchart To: jacopo mondi Cc: Peter Rosin , linux-kernel@vger.kernel.org, David Airlie , Rob Herring , Mark Rutland , Boris Brezillon , Nicolas Ferre , Alexandre Belloni , Archit Taneja , Andrzej Hajda , Daniel Vetter , Gustavo Padovan , Sean Paul , dri-devel@lists.freedesktop.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org Subject: Re: [PATCH v2 2/5] drm: bridge: add API to query the expected input formats of bridges Date: Wed, 04 Apr 2018 16:07:37 +0300 Message-ID: <1811029.jLvDxETu2H@avalon> Organization: Ideas on Board Oy In-Reply-To: <20180327130231.GO27746@w540> References: <20180326212447.7380-1-peda@axentia.se> <20180327130231.GO27746@w540> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hello, First of all, thank you for the patch. This generates more discussion than I had anticipated, which is both good and bad. I'll comment through the e-mail, and try to explain both my initial idea, and also where it could lead us. On Tuesday, 27 March 2018 16:02:31 EEST jacopo mondi wrote: > On Tue, Mar 27, 2018 at 02:12:42PM +0200, Peter Rosin wrote: > > On 2018-03-27 11:47, jacopo mondi wrote: > >> On Mon, Mar 26, 2018 at 11:24:44PM +0200, Peter Rosin wrote: > >>> Bridges may affect the required bus output format of the encoder, in > >>> which case it may be wrong to use the output format of the panel or > >>> connector as is. Add infrastructure to address this problem. > >> > >> Bridges not only affect the format expected by the connector at the > >> end of the display pipeline, they may perform encoding/decoding > >> between protocols and their accepted input formats may be unrelated to > >> the connector at the end of the pipeline as there may an arbitrary > >> number of bridges in between. > >> > >> Eg. > >> > >> ENCODER CONNECTOR > >> > >> |DU LVDS| ->lvds-> |THC63| ->rgb-> |ADV7511| ->hdmi-> |HDMI connector| > >> > >> The fact that THC63 wants a specific LVDS input format is unrelated to > >> the format required by the HDMI connector at the end of the pipeline. > >> > >> I would just state here that bridges need a way to report their > >> accepted media bus formats, and this patch extends the DRM Bridge APIs > >> to implement that. > > > > Yes, I can add some words, but I would like to clear up the naming > > before re-spinning. > > > >>> Signed-off-by: Peter Rosin > >>> --- > >>> > >>> drivers/gpu/drm/drm_bridge.c | 32 ++++++++++++++++++++++++++++++++ > >>> include/drm/drm_bridge.h | 18 ++++++++++++++++++ > >> 2 files changed, 50 insertions(+) > >>> > >>> diff --git a/drivers/gpu/drm/drm_bridge.c > >>> b/drivers/gpu/drm/drm_bridge.c > >>> index 1638bfe9627c..f85e61b7416e 100644 > >>> --- a/drivers/gpu/drm/drm_bridge.c > >>> +++ b/drivers/gpu/drm/drm_bridge.c > >>> @@ -348,6 +348,38 @@ void drm_bridge_enable(struct drm_bridge *bridge) > >>> > >>> } > >>> EXPORT_SYMBOL(drm_bridge_enable); > >>> > >>> +/** > >>> + * drm_bridge_input_formats - get the expected bus input format of the > >>> bridge > >> > >> I may be biased by the V4L2 APIs, but this seems to me very much like > >> similar to g_fmt/s_fmt callbacks we have there. Bridges have an input > >> and > > > > g_fmt/s_fmt says nothing to me. Graphics format? Source Format? I have > > no idea if those guesses are even close? So, that seems like poor naming > > to me. The only reason I see to go that way is for the sake of > > consistency. > > Sorry, I wasn't clear here. > > To me this operation seems like a "get format" and I see space for > future implementation of "set format" operations and also > "enum_formats" to implement format negotiation between bridges... A bit of context is probably needed here to bridge (no pun intended) DRM and V4L2. On the V4L2 side we have an object, named v4l2_subdev, that is analogous to drm_bridge. A v4l2_subdev models a component in a video pipeline, using abstract operations in a similar fashion to the drm_bridge_funcs. There are, however, several major differences between drm_bridge and v4l2_subdev. drm_bridge models a particular kind of component, namely video encoders, decoders or transcoders. A bridge is thus based on the implicit notion of having a single input and a single output, neither of them exposed explicitly. v4l2_subdev models any type of component in a video pipeline and for that reason has a variable number of inputs and outputs. The inputs and outputs are exposed explicitly through the v4l2_subdev API (in terms of the number of inputs/outputs, their type, and how they interact with the v4l2_subdev operations). As drm_bridge models one particular kind of component, the bridge operations are tailored to the feature of those components. Not all operations are mandatory (pre_enable or post_disable are optional for instance), but they all apply to all bridges conceptually. As v4l2_subdev models any type of component, the subdev operations have to support a wide variety of device features. There are thus many more operations, and not all of them are applicable to all type of v4l2_subdev. Operations that don't make sense for a particular v4l2_subdev instance (think about video tuner control for a camera sensor for instance) are simply not implemented. The drm_bridge framework hardcodes an operational model for bridges. Operations are called in a particular order on all bridges in a chain. For instance the enable operation is called from source to sink (bridge closest to the display controller to bridge closest to the connector), while the disable operation is called from sink to source. The v4l2_subdev framework doesn't hardcode an operation model. It is up to the top-level V4L2 driver (equivalent to the display controller driver) to call subdev operations in order applicable for the use cases it needs to support. This being said, let's talk about formats. In V4L2 a v4l2_subdev exposes operations to explicitly configure formats on all inputs and outputs (generically called pads in V4L2). Three operations are supported: .get_fmt() to retrieve the current format, .set_fmt() to set a format, and enum_mbus_code() and .enum_frame_size() to enumerate supported formats (I won't go into details regarding why enumeration is split in two operations, that's irrelevant here). It is important to note that format enumeration is mostly static (it tells what a v4l2_subdev supports), while get and set operations are dynamic (getting and setting, and more generically negotiating, formats). DRM has an API to enumerate the formats supported by connectors (through the drm_connector->display_info.bus_formats field). There is no API exposed to userspace to pick the desired format, neither at the connector level, or for bridges in the pipeline (bridges are not exposed to userspace at all). There is also no in-kernel API to enumerate formats supported by bridges or to get/ set a bridge format. Display controller are expected to pick an output format suitable for the output pipeline based on the formats supported by the connector and the selected display mode, and bridges are expected to just work without needing to care about formats. This model is starting to show its shortcomings now that we need to support bridges that convert formats. In Jacopo's case, an LVDS decoder transforms LVDS RGB to parallel RGB, and the display controller needs to know which LVDS format to output based on what the bridge expects. In Peter's case, an LVDS encoder transfer 24-bit RGB to LVDS RGB, but has the LSBs tied to ground on the input side, and thus requires the display controller to output RGB565. Now that we're done with the introduction, let's move on, please see below. > >> an output formats, and that calls for something that takes that into > >> account, as well as they may have different input ports with different > >> accepted formats but I would for now simplify this to just 'g_fmt()' > > > > You mean rename the function to drm_bridge_g_fmt(), right? > > Yeah, something like "drm_bridge_get_format(next_bridge)" > > > As indicated above, I'm not that fond of it, but don't really care > > either. Maintainers? > > I do not care much about the name too ofc, I think the real meat is > below... > > >>> + * @bridge: bridge control structure > >>> + * @bus_formats: where to store a pointer to the bus input formats > >>> + * > >>> + * Calls the &drm_bridge_funcs.input_formats op for the frist bridge > >>> in the > >>> + * chain that has registered this op. > >> > >> I'm not sure passing the call down the pipeline is desirable. Each > >> component should make sure its output format is accepted as the next > >> bridge input format, passing the call to the next bridge is not > >> different that getting to the connector at the end of the pipeline and > >> return to the initial caller its supported format. Do you agree with > >> this? > > > > Not passing down the call does one of two things. Either all bridges have > > to implement the call or all users have to walk the pipeline "manually". > > I don't like either or those options, so I still think it is good to > > pass the call down the pipeline. > > > > *time passes* > > > > Oh, you do not think it is useful for the bridge to have a callback but > > still report "no format change", and that the call down to pipeline > > should only happen for bridges that have not implemented the op. But I > > do think that is useful, see below. > > > >>> + * > >>> + * Note that the bridge passed should normally be the bridge closest to > >>> the > >>> + * encoder, but possibly the bridge closest to an intermediate bridge > >>> in > >>> + * convoluted cases. > >>> + * > >> > >> As I see this, any bridge in the arbitrary long pipeline should call > >> this operation on next bridge if it supports different output formats. > >> Ie. I would not name here the encoder nor refer to the bridge position > >> in the pipeline. > > > > Ok, I can change that, it just seemed like a convoluted case to me. > > I mean, if this was a real issue and complicated pipelines were > > common, something along the lines of this patch series would be > > available already. Right? I guess not, but how the &#/%# have people > > been coping? > > > >>> + * RETURNS: > >>> + * The number of bus input formats the bridge accepts. Zero means that > >>> + * the chain of bridges are not converting the bus format and that the > >>> + * format of the drm_connector should be used. > >> > >> How do we get to the connector format from a bridge that has maybe > >> other components in between in the pipeline? > >> > >> If a bridge do not report any supported format, it won't implement > >> this callback and things will work as they work today. > > > > Unless the bridge optionally changes the format. If the bridge has no > > way to say "no format change" even with the callback in place, it > > has to juggle different ops structs, which seems like a big hammer. > > So, I'm in favor of calling down the pipeline in two cases. A) when > > a bridge does not implement the op and B) when the op returns zero. > > Why do you think the bridge format conversion plays a role here? > > Maybe here's where I lost you, possibly because of my limited > knowledge of the DRM realm and its actual use cases. > > As I see it, this new API allows two bridges to synchronize on which > image format or LVDS mode 'bridge' should output to 'next_bridge' > input. > > The "mode_set" callback walks all element of the display pipeline, > and when one component has to select which image format or LVDS mode > to output to its next kin, if the next one is a panel it inspects the > display_info field, it it's a bridge it uses this new API to get the > format it accepts. > > If the next bridge does not implement this callback, things work as they > do today (in our specific use case, by chance :) > > > Maintainers? > > Yes, let's scale to more knowledgeable people than me, as I gave my > opinion already but it is based on the single use case I know for > real. I think it's important here to take a step back and look where we come from, what we need, and where we want to go. The first part is easy. As explained above, the current state is that we know what formats a connector supports, and we have no other API whatsoever, neither to userspace or inside the kernel, to handle format in the display output pipeline. What we need is at least static format information. In the two cases described above the bridge connected to the display controller output requires a specific format (RGB565 for Peter, LVDS JEIDA for Jacopo). There is no need to walk to pipeline and query all bridges, we can get the necessary information from the first bridge in the chain. Where we want to go is the real question. We need at least static information, so we could expose it through a new bus_formats field in the drm_bridge structure, similar to the bus_formats field in the drm_display_info structure. This would solve the two problems at hand. However, such a solution wouldn't allow us to configure formats through the pipeline, and wouldn't allow us to query the format a bridge needs based on the format needed by the next bridge in the chain. It would thus be limited to specific cases, and one could argue that it would be too limited. A more generic solution might be better, to support dynamic negotiation of formats through the pipeline. I believe this would be needed in the long run anyway, so it's tempting to give it a try today. However, as we don't have any real use case yet, one might argue that we would design the API incorrectly, which I can't completely disagree with. Nonetheless, if we were to design such an API, I agree with Daniel that it should be based on bridge states. Such a solution would allow negotiation of formats through the pipeline (using a yet to be designed process), and would then allow the display controller to retrieve the negotiated format expected by the first bridge from the bridge state. I don't think we would design the API between the display controller and the first bridge wrong (it would just be a matter of reading the negotiated format from the first bridge's state, there's little room for design issues there), but the format negotiation through the pipeline would need more thoughts. One option (just thinking out loud) would be to start with the connector format, and then ask each bridge in the chain, from last to first, for the input format it needs to generate the expected output format. More complex schemes might be needed, especially when the connector supports multiple formats, or when a bridge can accept multiple input formats to generate a given output format. In those cases picking the first supported format could work, but it might not always lead to the optimal pipeline configuration. Another point I want to mention is that in Peter's case the LVDS encoder requires RGB888 at its input, but the PCB routing transforms RGB565 to RGB888 by shifting signals and tying the LSBs to ground. That information really belongs to DT as it isn't intrinsic to either the display controller or the LVDS encoder. I however wonder whether it should be expressed as a format, or in a different form. In V4L2 we have standardized bus-width and data-shift DT properties (see Documentation/devicetree/bindings/media/video-interfaces.txt) to expose how signals are connected in the PCB. This allows expressing transformations instead of hardcoding formats, which can be useful if the bridge can still accept multiple input formats. One example of this is raw camera sensors that can output multiple bayer patterns (BGGR, GBRG, GRBG or RGGB) with 10 bits per pixel, combined with a PCB that connects D[9:2] of the sensor to D[7:0] of the camera controller. BGGR10 would be turned into BGGR8, GBRG10 into GBRG8, and so on. The camera controller should thus not hardcode a particular format in DT as there are multiple options that can be selected at runtime. I can imagine a similar setup for the display, with a bridge configurable through I2C that could accept different formats, combined with the PCB performing some weird routing. Finally, still regarding Peter's case, the decision to output RGB565 instead of RGB888 (which the LVDS encoder expects) is due to PCB routing between the display controller and the LVDS encoder. This isn't a property of the LVDS encoder or the display controller, but of their hardware connection. This patch series uses a DT property in the LVDS encoder DT node to convey that information, but wouldn't it be equally correct (or incorrect :-)) to instead use a DT property in the display controller DT node ? > >>> + */ > >>> +int drm_bridge_input_formats(struct drm_bridge *bridge, > >>> + const u32 **bus_formats) > >>> +{ > >>> + int ret = 0; > >>> + > >>> + if (!bridge) > >>> + return 0; > >>> + > >>> + if (bridge->funcs->input_formats) > >>> + ret = bridge->funcs->input_formats(bridge, bus_formats); > >>> + > >>> + return ret ?: drm_bridge_input_formats(bridge->next, bus_formats); > >> > >> See my comment on the call propagation down in the pipeline. > >> > >>> +} > >>> +EXPORT_SYMBOL(drm_bridge_input_formats); > >>> + > >>> #ifdef CONFIG_OF > >>> /** > >>> * of_drm_find_bridge - find the bridge corresponding to the device > >>> node in > >>> diff --git a/include/drm/drm_bridge.h b/include/drm/drm_bridge.h > >>> index 682d01ba920c..ae8d3c4af0b8 100644 > >>> --- a/include/drm/drm_bridge.h > >>> +++ b/include/drm/drm_bridge.h > >>> @@ -220,6 +220,22 @@ struct drm_bridge_funcs { > >>> * The enable callback is optional. > >>> */ > >>> void (*enable)(struct drm_bridge *bridge); > >>> + > >>> + /** > >>> + * @input_formats: > >>> + * > >>> + * The callback reports the expected bus input formats of the > >>> bridge. > >>> + * > >>> + * The @input_formats callback is optional. The bridge is assumed to > >>> + * not convert the bus format if the callback is not installed. > >>> + * > >>> + * RETURNS: > >>> + * > >>> + * Zero if the bridge does not convert the bus format, otherwise the > >>> + * number of bus input formats returned in &bus_formats. > >>> + */ > >>> + int (*input_formats)(struct drm_bridge *bridge, > >>> + const u32 **bus_formats); > >> > >> Consider g_fmt() here as well, or a function name that captures that we > >> want to know the supported format (and possibly configure it as well > >> one day, if ever possible). > > > > The naming here should obviously follow the naming of the exported > > function. > > > >>> }; > >>> > >>> /** > >>> @@ -263,6 +279,8 @@ void drm_bridge_mode_set(struct drm_bridge *bridge, > >>> struct drm_display_mode *adjusted_mode); > >>> void drm_bridge_pre_enable(struct drm_bridge *bridge); > >>> void drm_bridge_enable(struct drm_bridge *bridge); > >>> +int drm_bridge_input_formats(struct drm_bridge *bridge, > >>> + const u32 **bus_formats); > >>> > >>> #ifdef CONFIG_DRM_PANEL_BRIDGE > >> struct drm_bridge *drm_panel_bridge_add(struct drm_panel *panel, -- Regards, Laurent Pinchart