Re: [PATCH 2/3] dt-bindings: display: panel: Add binding document for Xinpeng XPP055C272
Hi Heiko. On Mon, Dec 09, 2019 at 03:42:07PM +0100, Heiko Stuebner wrote: > From: Heiko Stuebner > > The XPP055C272 is a 5.5" 720x1280 DSI display. Can we get the size info included in the title in the binding? Then all relavant info is in the binding, and no git digging is needed. > > Signed-off-by: Heiko Stuebner > --- > .../display/panel/xinpeng,xpp055c272.yaml | 45 +++ > 1 file changed, 45 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml > > diff --git > a/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml > b/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml > new file mode 100644 > index ..4515d44d189b > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/xinpeng,xpp055c272.yaml > @@ -0,0 +1,45 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/sony,acx424akp.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Xinpeng XPP055C272 720x1280 DSI panel > + > +maintainers: > + - Heiko Stuebner > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > +const: xinpeng,xpp055c272 > + reg: true > + backlight: true > + port: true > + reset-gpios: true > + iovcc-supply: > + description: regulator that supplies the iovcc voltage > + vci-supply: > + description: regulator that supplies the vci voltage > + > +required: > + - compatible > + - reg One would assume the display also required power to operate. > + > +additionalProperties: false > + > +examples: > + - | > +dsi@ff45 { > +panel@0 { > +compatible = "xinpeng,xpp055c272"; > +reg = <0>; > +backlight = <&backlight>; > +iovcc-supply = <&vcc_1v8>; > +vci-supply = <&vcc3v3_lcd>; > +}; > +}; > + > +... With the few things mentioned above fixed: Reviewed-by: Sam Ravnborg ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 205853] amdgpu kernel bug: kernel null pointer dereference
https://bugzilla.kernel.org/show_bug.cgi?id=205853 --- Comment #3 from Janpieter Sollie (janpieter.sol...@dommel.be) --- the issue seems to be in the DC driver: booting the amdgpu kernel module with "dc=0" reduces the output to: [7.050414] amdgpu :0a:00.0: [drm:amdgpu_ib_ring_tests [amdgpu]] *ERROR* IB test failed on uvd (-110). [7.151761] [drm:process_one_work] *ERROR* ib ring test failed (-110). -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/3] dt-bindings: Add vendor prefix for Xinpeng Technology
Hi Heiko. On Mon, Dec 09, 2019 at 03:42:06PM +0100, Heiko Stuebner wrote: > From: Heiko Stuebner > > Shenzhen Xinpeng Technology Co., Ltd produces for example display panels. > > Signed-off-by: Heiko Stuebner > --- > Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml > b/Documentation/devicetree/bindings/vendor-prefixes.yaml > index 6046f4555852..85e7c26a05c7 100644 > --- a/Documentation/devicetree/bindings/vendor-prefixes.yaml > +++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml > @@ -1056,6 +1056,8 @@ patternProperties: > description: Extreme Engineering Solutions (X-ES) >"^xillybus,.*": > description: Xillybus Ltd. > + "^xinpeng,.*": > +description: Shenzhen Xinpeng Technology Co., Ltd >"^xlnx,.*": > description: Xilinx >"^xunlong,.*": Looks good. Acked-by: Sam Ravnborg ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 205853] amdgpu kernel bug: kernel null pointer dereference
https://bugzilla.kernel.org/show_bug.cgi?id=205853 --- Comment #2 from Janpieter Sollie (janpieter.sol...@dommel.be) --- Created attachment 286281 --> https://bugzilla.kernel.org/attachment.cgi?id=286281&action=edit kernel config file -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 205853] amdgpu kernel bug: kernel null pointer dereference
https://bugzilla.kernel.org/show_bug.cgi?id=205853 --- Comment #1 from Janpieter Sollie (janpieter.sol...@dommel.be) --- Created attachment 286279 --> https://bugzilla.kernel.org/attachment.cgi?id=286279&action=edit lspci -v output -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 205853] New: amdgpu kernel bug: kernel null pointer dereference
https://bugzilla.kernel.org/show_bug.cgi?id=205853 Bug ID: 205853 Summary: amdgpu kernel bug: kernel null pointer dereference Product: Drivers Version: 2.5 Kernel Version: 5.4.2 Hardware: x86-64 OS: Linux Tree: Mainline Status: NEW Severity: normal Priority: P1 Component: Video(DRI - non Intel) Assignee: drivers_video-...@kernel-bugs.osdl.org Reporter: janpieter.sol...@dommel.be Regression: No Created attachment 286277 --> https://bugzilla.kernel.org/attachment.cgi?id=286277&action=edit dmesg of kernel 5.4.2 possible duplicate of #204181, but as they are talking about X software, and I don't even have an xorg setup (issue happens at boot, device is only present for opencl software), I decided to file a new one: AMDGPU kernel NULL pointer dereference, address: 0d71 using fiji device lspci, dmesg and .config attached. -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/panfrost: Prefix interrupt handlers' names
Currently, the interrupt lines requested by Panfrost use unmeaningful names, which adds some obscurity to interrupt introspection (i.e. any tool based on procfs' interrupts file). In order to improve this, prefix each requested interrupt with the module name: panfrost-{gpu,job,mmu}. Signed-off-by: Ezequiel Garcia --- v2: * Use consistent naming, as suggested by Alyssa, Neil and Robin. drivers/gpu/drm/panfrost/panfrost_gpu.c | 2 +- drivers/gpu/drm/panfrost/panfrost_job.c | 2 +- drivers/gpu/drm/panfrost/panfrost_mmu.c | 6 -- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index f67ed925c0ef..af2aa6b3bce3 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -348,7 +348,7 @@ int panfrost_gpu_init(struct panfrost_device *pfdev) return -ENODEV; err = devm_request_irq(pfdev->dev, irq, panfrost_gpu_irq_handler, - IRQF_SHARED, "gpu", pfdev); + IRQF_SHARED, KBUILD_MODNAME "-gpu", pfdev); if (err) { dev_err(pfdev->dev, "failed to request gpu irq"); return err; diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c index 05c85f45a0de..3bd79ebb6c40 100644 --- a/drivers/gpu/drm/panfrost/panfrost_job.c +++ b/drivers/gpu/drm/panfrost/panfrost_job.c @@ -480,7 +480,7 @@ int panfrost_job_init(struct panfrost_device *pfdev) return -ENODEV; ret = devm_request_irq(pfdev->dev, irq, panfrost_job_irq_handler, - IRQF_SHARED, "job", pfdev); + IRQF_SHARED, KBUILD_MODNAME "-job", pfdev); if (ret) { dev_err(pfdev->dev, "failed to request job irq"); return ret; diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index 842bdd7cf6be..806958434726 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -612,9 +612,11 @@ int panfrost_mmu_init(struct panfrost_device *pfdev) if (irq <= 0) return -ENODEV; - err = devm_request_threaded_irq(pfdev->dev, irq, panfrost_mmu_irq_handler, + err = devm_request_threaded_irq(pfdev->dev, irq, + panfrost_mmu_irq_handler, panfrost_mmu_irq_handler_thread, - IRQF_SHARED, "mmu", pfdev); + IRQF_SHARED, KBUILD_MODNAME "-mmu", + pfdev); if (err) { dev_err(pfdev->dev, "failed to request mmu irq"); -- 2.22.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v11 23/25] mm/gup: track FOLL_PIN pages
Add tracking of pages that were pinned via FOLL_PIN. As mentioned in the FOLL_PIN documentation, callers who effectively set FOLL_PIN are required to ultimately free such pages via unpin_user_page(). The effect is similar to FOLL_GET, and may be thought of as "FOLL_GET for DIO and/or RDMA use". Pages that have been pinned via FOLL_PIN are identifiable via a new function call: bool page_dma_pinned(struct page *page); What to do in response to encountering such a page, is left to later patchsets. There is discussion about this in [1], [2], and [3]. This also changes a BUG_ON(), to a WARN_ON(), in follow_page_mask(). [1] Some slow progress on get_user_pages() (Apr 2, 2019): https://lwn.net/Articles/784574/ [2] DMA and get_user_pages() (LPC: Dec 12, 2018): https://lwn.net/Articles/774411/ [3] The trouble with get_user_pages() (Apr 30, 2018): https://lwn.net/Articles/753027/ Suggested-by: Jan Kara Suggested-by: Jérôme Glisse Cc: Kirill A. Shutemov Signed-off-by: John Hubbard --- Hi Jan, This should address all of your comments for patch 23! thanks, John Hubbard NVIDIA Documentation/core-api/pin_user_pages.rst | 2 +- include/linux/mm.h| 83 - include/linux/mmzone.h| 2 + include/linux/page_ref.h | 10 + mm/gup.c | 409 +- mm/huge_memory.c | 28 +- mm/hugetlb.c | 38 +- mm/vmstat.c | 2 + 8 files changed, 438 insertions(+), 136 deletions(-) diff --git a/Documentation/core-api/pin_user_pages.rst b/Documentation/core-api/pin_user_pages.rst index 1d490155ecd7..2db14df1f2d7 100644 --- a/Documentation/core-api/pin_user_pages.rst +++ b/Documentation/core-api/pin_user_pages.rst @@ -53,7 +53,7 @@ Which flags are set by each wrapper For these pin_user_pages*() functions, FOLL_PIN is OR'd in with whatever gup flags the caller provides. The caller is required to pass in a non-null struct pages* array, and the function then pin pages by incrementing each by a special -value. For now, that value is +1, just like get_user_pages*().:: +value: GUP_PIN_COUNTING_BIAS.:: Function diff --git a/include/linux/mm.h b/include/linux/mm.h index 6a1a357e7d86..bb44c4d2ada7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1016,6 +1016,8 @@ static inline void get_page(struct page *page) page_ref_inc(page); } +bool __must_check try_grab_page(struct page *page, unsigned int flags); + static inline __must_check bool try_get_page(struct page *page) { page = compound_head(page); @@ -1044,29 +1046,80 @@ static inline void put_page(struct page *page) __put_page(page); } -/** - * unpin_user_page() - release a gup-pinned page - * @page:pointer to page to be released +/* + * GUP_PIN_COUNTING_BIAS, and the associated functions that use it, overload + * the page's refcount so that two separate items are tracked: the original page + * reference count, and also a new count of how many pin_user_pages() calls were + * made against the page. ("gup-pinned" is another term for the latter). + * + * With this scheme, pin_user_pages() becomes special: such pages are marked as + * distinct from normal pages. As such, the unpin_user_page() call (and its + * variants) must be used in order to release gup-pinned pages. + * + * Choice of value: + * + * By making GUP_PIN_COUNTING_BIAS a power of two, debugging of page reference + * counts with respect to pin_user_pages() and unpin_user_page() becomes + * simpler, due to the fact that adding an even power of two to the page + * refcount has the effect of using only the upper N bits, for the code that + * counts up using the bias value. This means that the lower bits are left for + * the exclusive use of the original code that increments and decrements by one + * (or at least, by much smaller values than the bias value). * - * Pages that were pinned via pin_user_pages*() must be released via either - * unpin_user_page(), or one of the unpin_user_pages*() routines. This is so - * that eventually such pages can be separately tracked and uniquely handled. In - * particular, interactions with RDMA and filesystems need special handling. + * Of course, once the lower bits overflow into the upper bits (and this is + * OK, because subtraction recovers the original values), then visual inspection + * no longer suffices to directly view the separate counts. However, for normal + * applications that don't have huge page reference counts, this won't be an + * issue. * - * unpin_user_page() and put_page() are not interchangeable, despite this early - * implementation that makes them look the same. unpin_user_page() calls must - * be perfectly matched up with pin*() calls. + * Locking: the lockless algorithm described in page_cache_get_speculative() + * and page_cache_gup_pin_speculative() provides safe op
Re: [PATCH 9/9] drm/bridge: ti-sn65dsi86: Skip non-standard DP rates
Hi, On Fri, Dec 13, 2019 at 4:07 PM Daniel Vetter wrote: > > On Fri, Dec 13, 2019 at 03:45:30PM -0800, Douglas Anderson wrote: > > The bridge chip supports these DP rates according to TI's spec: > > * 1.62 Gbps (RBR) > > * 2.16 Gbps > > * 2.43 Gbps > > * 2.7 Gbps (HBR) > > * 3.24 Gbps > > * 4.32 Gbps > > * 5.4 Gbps (HBR2) > > > > As far as I can tell, only RBR, HBR, and HBR2 are part of the DP spec. > > If other rates work then I believe it's because the sink has allowed > > bending the spec a little bit. > > I think you need to look at the eDP spec. And filter this stuff correctly > (there's more fields there for these somewhat irky edp timings). Simply > not using them works, but it's defeating the point of having these > intermediate clocks for edp panels. Ah, I see my problem. I had earlier only found the eDP 1.3 spec which doesn't mention these rates. The eDP 1.4 spec does, however. ...and the change log for 1.4 specifically mentions that it added 4 new link rates and also adds the "SUPPORTED_LINK_RATES" register. I can try to spin a v2 but for now I'll hold off for additional feedback. I'll also note that I'd be totally OK if just the first 8 patches in this series landed for now and someone could eventually figure out how to make this work. With just the first 8 patches I think we will still be in an improved state compared to where we were before (and it fixes the panel I care about) and someone could later write the code to skip unsupported rates... -Doug ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [RFC v2 02/12] drm/i915/svm: Runtime (RT) allocator support
On Fri, Dec 13, 2019 at 5:24 PM Niranjan Vishwanathapura < niranjana.vishwanathap...@intel.com> wrote: > On Fri, Dec 13, 2019 at 04:58:42PM -0600, Jason Ekstrand wrote: > > > > +/** > > + * struct drm_i915_gem_vm_bind > > + * > > + * Bind an object in a vm's page table. > > > > First off, this is something I've wanted for a while for Vulkan, it's > just > > never made its way high enough up the priority list. However, it's > going > > to have to come one way or another soon. I'm glad to see kernel API > for > > this being proposed. > > I do, however, have a few high-level comments/questions about the API: > >1. In order to be useful for sparse memory support, the API has to go > the > > other way around so that it binds a VA range to a range within the > BO. It > > also needs to be able to handle overlapping where two different VA > ranges > > may map to the same underlying bytes in the BO. This likely means that > > unbind needs to also take a VA range and only unbind that range. > >2. If this is going to be useful for managing GL's address space > where we > > have lots of BOs, we probably want it to take a list of ranges so we > > aren't making one ioctl for each thing we want to bind. > > Hi Jason, > > Yah, some of these requirements came up. > Yes, I have raised them every single time an API like this has come across my e-mail inbox for years and they continue to get ignored. Why are we landing an API that we know isn't the API we want especially when it's pretty obvious roughly what the API we want is? It may be less time in the short term, but long-term it means two ioctls and two implementations in i915, IGT tests for both code paths, and code in all UMDs to call one or the other depending on what kernel you're running on, and we have to maintain all that code going forward forever. Sure, that's a price we pay today for a variety of things but that's because they all seemed like the right thing at the time. Landing the wrong API when we know it's the wrong API seems foolish. They are not being done here due to time and effort involved in defining > those requirements, implementing and validating. > For #1, yes, it would require more effort but for #2, it really doesn't take any extra effort to make it take an array... > However, this ioctl can be extended in a backward compatible way to handle > those requirements if required. > > >3. Why are there no ways to synchronize this with anything? For > binding, > > this probably isn't really needed as long as the VA range you're > binding > > is empty. However, if you want to move bindings around or unbind > > something, the only option is to block in userspace and then call > > bind/unbind. This can be done but it means even more threads in the > UMD > > which is unpleasant. One could argue that that's more or less what the > > kernel is going to have to do so we may as well do it in userspace. > > However, I'm not 100% convinced that's true. > > --Jason > > > > Yah, that is the thought. > But as SVM feature evolves, I think we can consider handling some such > cases > if hadling those in driver does make whole lot sense. > Sparse binding exists as a feature. It's been in D3D for some time and it's in Vulkan. We pretty much know what the requirements are. If you go look at how it's supposed to work in Vulkan, you have a binding queue and it waits on semaphores before [un]binding and signals semaphores after [un]binding. The biggest problem from an API (as opposed to implementation) POV with doing that in i915 is that we have too many synchronization primitives to choose from. :-( --Jason > Thanks, > Niranjana > > > > > + */ > > +struct drm_i915_gem_vm_bind { > > + /** VA start to bind **/ > > + __u64 start; > > + > > + /** Type of memory to [un]bind **/ > > + __u32 type; > > +#define I915_GEM_VM_BIND_SVM_OBJ 0 > > + > > + /** Object handle to [un]bind for I915_GEM_VM_BIND_SVM_OBJ > type > > **/ > > + __u32 handle; > > + > > + /** vm to [un]bind **/ > > + __u32 vm_id; > > + > > + /** Flags **/ > > + __u32 flags; > > +#define I915_GEM_VM_BIND_UNBIND (1 << 0) > > +#define I915_GEM_VM_BIND_READONLY(1 << 1) > > +}; > > + > > #if defined(__cplusplus) > > } > > #endif > > -- > > 2.21.0.rc0.32.g243a4c7e27 > > > > ___ > > Intel-gfx mailing list > > intel-...@lists.freedesktop.org > > https://lists.freedesktop.org/mailman/listinfo/intel-gfx > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/4] drm/i915: Use dma_resv locking wrappers
On Mon, Nov 25, 2019 at 10:43:54AM +0100, Daniel Vetter wrote: > I'll add more fancy logic to them soon, so everyone really has to use > them. Plus they already provide some nice additional debug > infrastructure on top of direct ww_mutex usage for the fences tracked > by dma_resv. > > Aside: We might want to create wrappers for i915_vma locking of the > ->resv like we have for the i915_gem_bo itself already. > > Signed-off-by: Daniel Vetter > Cc: Chris Wilson > Cc: Tvrtko Ursulin > Cc: Matthew Auld > Cc: Joonas Lahtinen > Cc: Jani Nikula > --- Maarten/Chris, should I drop this one or keep? I guess this will all change anyway rsn ... -Daniel > drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > index 7a87e8270460..7b8f4ebd9986 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > @@ -1848,7 +1848,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) > for (i = 0; i < count; i++) { > struct i915_vma *vma = eb->vma[i]; > > - err = ww_mutex_lock_interruptible(&vma->resv->lock, &acquire); > + err = dma_resv_lock_interruptible(vma->resv, &acquire); > if (!err) > continue; > > @@ -1859,7 +1859,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) > do { > int j = i - 1; > > - ww_mutex_unlock(&eb->vma[j]->resv->lock); > + dma_resv_unlock(eb->vma[j]->resv); > > swap(eb->flags[i], eb->flags[j]); > swap(eb->vma[i], eb->vma[j]); > @@ -1868,7 +1868,7 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb) > GEM_BUG_ON(vma != eb->vma[0]); > vma->exec_flags = &eb->flags[0]; > > - err = ww_mutex_lock_slow_interruptible(&vma->resv->lock, > + err = dma_resv_lock_slow_interruptible(vma->resv, > &acquire); > } > if (err) > -- > 2.24.0 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/etnaviv: Use dma_resv locking wrappers
I'll add more fancy logic to them soon, so everyone really has to use them. Plus they already provide some nice additional debug infrastructure on top of direct ww_mutex usage for the fences tracked by dma_resv. v2: Fix the lost _interruptible (Michael) Signed-off-by: Daniel Vetter Cc: Lucas Stach Cc: Russell King Cc: Christian Gmeiner Cc: etna...@lists.freedesktop.org Cc: "Ruhl, Michael J" --- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 8 +++- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index aa3e4c3b063a..3b0afa156d92 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -113,7 +113,7 @@ static void submit_unlock_object(struct etnaviv_gem_submit *submit, int i) if (submit->bos[i].flags & BO_LOCKED) { struct drm_gem_object *obj = &submit->bos[i].obj->base; - ww_mutex_unlock(&obj->resv->lock); + dma_resv_unlock(obj->resv); submit->bos[i].flags &= ~BO_LOCKED; } } @@ -133,8 +133,7 @@ static int submit_lock_objects(struct etnaviv_gem_submit *submit, contended = i; if (!(submit->bos[i].flags & BO_LOCKED)) { - ret = ww_mutex_lock_interruptible(&obj->resv->lock, - ticket); + ret = dma_resv_lock_interruptible(obj->resv, ticket); if (ret == -EALREADY) DRM_ERROR("BO at index %u already on submit list\n", i); @@ -161,8 +160,7 @@ static int submit_lock_objects(struct etnaviv_gem_submit *submit, obj = &submit->bos[contended].obj->base; /* we lost out in a seqno race, lock and retry.. */ - ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock, - ticket); + ret = dma_resv_lock_slow_interruptible(obj->resv, ticket); if (!ret) { submit->bos[contended].flags |= BO_LOCKED; slow_locked = contended; -- 2.24.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 9/9] drm/bridge: ti-sn65dsi86: Skip non-standard DP rates
On Fri, Dec 13, 2019 at 03:45:30PM -0800, Douglas Anderson wrote: > The bridge chip supports these DP rates according to TI's spec: > * 1.62 Gbps (RBR) > * 2.16 Gbps > * 2.43 Gbps > * 2.7 Gbps (HBR) > * 3.24 Gbps > * 4.32 Gbps > * 5.4 Gbps (HBR2) > > As far as I can tell, only RBR, HBR, and HBR2 are part of the DP spec. > If other rates work then I believe it's because the sink has allowed > bending the spec a little bit. I think you need to look at the eDP spec. And filter this stuff correctly (there's more fields there for these somewhat irky edp timings). Simply not using them works, but it's defeating the point of having these intermediate clocks for edp panels. -Daniel > > I hoped that we could tell which rates would work and which rates > didn't work based on whether link training passed or not. > Unfortunately this wasn't so good on at least one panel hooked up to > the bridge (AUO B116XAK01). On that panel with 24 bpp configured: > * 1.62: too small for 69500 kHz at 24 bpp > * 2.16: link training failed > * 2.43: link training passed, but garbage on screen > * 2.7: joy and happiness > > Let's bypass all non-standard rates, which makes this panel happy > working. I'll still keep the code organized in such a way where it > _could_ try the other rates, though, on the assumption that eventually > someone will find a way to make use of them. > > Signed-off-by: Douglas Anderson > --- > > drivers/gpu/drm/bridge/ti-sn65dsi86.c | 21 + > 1 file changed, 21 insertions(+) > > diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > index cc8bef172f69..cb774ee536cd 100644 > --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > @@ -454,6 +454,15 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = { > 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 > }; > > +/** > + * A table indicating which of the rates in ti_sn_bridge_dp_rate_lut > + * is as per the DP spec (AKA a standard) as opposed to an intermediate > + * rate. > + */ > +static const bool ti_sn_bridge_dp_rate_standard[] = { > + false, true, false, false, true, false, false, true > +}; > + > static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn_bridge *pdata) > { > unsigned int bit_rate_khz, dp_rate_mhz; > @@ -660,6 +669,18 @@ static void ti_sn_bridge_enable(struct drm_bridge > *bridge) > for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata); >dp_rate_idx <= max_dp_rate_idx; >dp_rate_idx++) { > + /* > + * To be on the safe side, we'll skip all non-standard > + * rates and move up to the next standard one. This is > + * because some panels will pass link training with a non- > + * standard rate but just show garbage. If the non-standard > + * rates are useful we should figure out how to enable them > + * through querying the panel, having a per-panel whitelist, > + * or adding a DT property. > + */ > + if (!ti_sn_bridge_dp_rate_standard[dp_rate_idx]) > + continue; > + > ret = ti_sn_link_training(pdata, dp_rate_idx, &last_err_str); > if (!ret) > break; > -- > 2.24.1.735.g03f4e72817-goog > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[Bug 204987] fault in amdgpu_dm_atomic_commit_tail on Vega64 with compton and redshift
https://bugzilla.kernel.org/show_bug.cgi?id=204987 --- Comment #2 from Frank Steinborn (stei...@nognu.de) --- Still happens on 5.4.2. -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [RESEND PATCH v2] drm: Add getfb2 ioctl
On Fri, Dec 13, 2019 at 10:52:03PM +, Li, Juston wrote: > On Fri, 2019-12-13 at 23:36 +0200, Ville Syrjälä wrote: > > On Thu, Oct 03, 2019 at 11:31:25AM -0700, Juston Li wrote: > > > From: Daniel Stone > > > > > > getfb2 allows us to pass multiple planes and modifiers, just like > > > addfb2 > > > over addfb. > > > > > > Changes since v1: > > > - unused modifiers set to 0 instead of DRM_FORMAT_MOD_INVALID > > > - update ioctl number > > > > > > Signed-off-by: Daniel Stone > > > Signed-off-by: Juston Li > > > --- > > > drivers/gpu/drm/drm_crtc_internal.h | 2 + > > > drivers/gpu/drm/drm_framebuffer.c | 110 > > > > > > drivers/gpu/drm/drm_ioctl.c | 1 + > > > include/uapi/drm/drm.h | 2 + > > > 4 files changed, 115 insertions(+) > > > > > > diff --git a/drivers/gpu/drm/drm_crtc_internal.h > > > b/drivers/gpu/drm/drm_crtc_internal.h > > > index c7d5e4c21423..16f2413403aa 100644 > > > --- a/drivers/gpu/drm/drm_crtc_internal.h > > > +++ b/drivers/gpu/drm/drm_crtc_internal.h > > > @@ -216,6 +216,8 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev, > > > void *data, struct drm_file *file_priv); > > > int drm_mode_getfb(struct drm_device *dev, > > > void *data, struct drm_file *file_priv); > > > +int drm_mode_getfb2_ioctl(struct drm_device *dev, > > > + void *data, struct drm_file *file_priv); > > > int drm_mode_dirtyfb_ioctl(struct drm_device *dev, > > > void *data, struct drm_file *file_priv); > > > > > > diff --git a/drivers/gpu/drm/drm_framebuffer.c > > > b/drivers/gpu/drm/drm_framebuffer.c > > > index 57564318ceea..6db54f177443 100644 > > > --- a/drivers/gpu/drm/drm_framebuffer.c > > > +++ b/drivers/gpu/drm/drm_framebuffer.c > > > @@ -31,6 +31,7 @@ > > > #include > > > #include > > > #include > > > +#include > > > #include > > > #include > > > > > > @@ -548,7 +549,116 @@ int drm_mode_getfb(struct drm_device *dev, > > > > > > out: > > > drm_framebuffer_put(fb); > > > + return ret; > > > +} > > > + > > > +/** > > > + * drm_mode_getfb2 - get extended FB info > > > + * @dev: drm device for the ioctl > > > + * @data: data pointer for the ioctl > > > + * @file_priv: drm file for the ioctl call > > > + * > > > + * Lookup the FB given its ID and return info about it. > > > + * > > > + * Called by the user via ioctl. > > > + * > > > + * Returns: > > > + * Zero on success, negative errno on failure. > > > + */ > > > +int drm_mode_getfb2_ioctl(struct drm_device *dev, > > > + void *data, struct drm_file *file_priv) > > > +{ > > > + struct drm_mode_fb_cmd2 *r = data; > > > + struct drm_framebuffer *fb; > > > + unsigned int i; > > > + int ret; > > > + > > > + if (!drm_core_check_feature(dev, DRIVER_MODESET)) > > > + return -EINVAL; > > > + > > > + fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); > > > + if (!fb) > > > + return -ENOENT; > > > + > > > + /* For multi-plane framebuffers, we require the driver to place > > > the > > > + * GEM objects directly in the drm_framebuffer. For single- > > > plane > > > + * framebuffers, we can fall back to create_handle. > > > + */ > > > + if (!fb->obj[0] && > > > + (fb->format->num_planes > 1 || !fb->funcs->create_handle)) > > > { > > > + ret = -ENODEV; > > > + goto out; > > > + } > > > + > > > + r->height = fb->height; > > > + r->width = fb->width; > > > + r->pixel_format = fb->format->format; > > > + > > > + r->flags = 0; > > > + if (dev->mode_config.allow_fb_modifiers) > > > + r->flags |= DRM_MODE_FB_MODIFIERS; > > > + > > > + for (i = 0; i < ARRAY_SIZE(r->handles); i++) { > > > + r->handles[i] = 0; > > > + r->pitches[i] = 0; > > > + r->offsets[i] = 0; > > > + r->modifier[i] = 0; > > > + } > > > > > > + for (i = 0; i < fb->format->num_planes; i++) { > > > + int j; > > > + > > > + r->pitches[i] = fb->pitches[i]; > > > + r->offsets[i] = fb->offsets[i]; > > > + if (dev->mode_config.allow_fb_modifiers) > > > + r->modifier[i] = fb->modifier; > > > + > > > + /* If we reuse the same object for multiple planes, > > > also > > > + * return the same handle. > > > + */ > > > + for (j = 0; j < i; j++) { > > > + if (fb->obj[i] == fb->obj[j]) { > > > + r->handles[i] = r->handles[j]; > > > + break; > > > + } > > > + } > > > + > > > + if (r->handles[i]) > > > + continue; > > > + > > > + if (fb->obj[i]) { > > > + ret = drm_gem_handle_create(file_priv, fb- > > > >obj[i], > > > + &r->handles[i]); > > > + } else { > > > + WARN_ON(i > 0); > > > + ret = fb->funcs->create_handle(fb, file_priv, > > > +
[Bug 204987] fault in amdgpu_dm_atomic_commit_tail on Vega64 with compton and redshift
https://bugzilla.kernel.org/show_bug.cgi?id=204987 Frank Steinborn (stei...@nognu.de) changed: What|Removed |Added Summary|general protection fault in |fault in |amdgpu_dm_atomic_commit_tai |amdgpu_dm_atomic_commit_tai |l (Vega64) |l on Vega64 with compton ||and redshift -- You are receiving this mail because: You are watching the assignee of the bug. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 9/9] drm/bridge: ti-sn65dsi86: Skip non-standard DP rates
The bridge chip supports these DP rates according to TI's spec: * 1.62 Gbps (RBR) * 2.16 Gbps * 2.43 Gbps * 2.7 Gbps (HBR) * 3.24 Gbps * 4.32 Gbps * 5.4 Gbps (HBR2) As far as I can tell, only RBR, HBR, and HBR2 are part of the DP spec. If other rates work then I believe it's because the sink has allowed bending the spec a little bit. I hoped that we could tell which rates would work and which rates didn't work based on whether link training passed or not. Unfortunately this wasn't so good on at least one panel hooked up to the bridge (AUO B116XAK01). On that panel with 24 bpp configured: * 1.62: too small for 69500 kHz at 24 bpp * 2.16: link training failed * 2.43: link training passed, but garbage on screen * 2.7: joy and happiness Let's bypass all non-standard rates, which makes this panel happy working. I'll still keep the code organized in such a way where it _could_ try the other rates, though, on the assumption that eventually someone will find a way to make use of them. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 21 + 1 file changed, 21 insertions(+) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index cc8bef172f69..cb774ee536cd 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -454,6 +454,15 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = { 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 }; +/** + * A table indicating which of the rates in ti_sn_bridge_dp_rate_lut + * is as per the DP spec (AKA a standard) as opposed to an intermediate + * rate. + */ +static const bool ti_sn_bridge_dp_rate_standard[] = { + false, true, false, false, true, false, false, true +}; + static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn_bridge *pdata) { unsigned int bit_rate_khz, dp_rate_mhz; @@ -660,6 +669,18 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata); dp_rate_idx <= max_dp_rate_idx; dp_rate_idx++) { + /* +* To be on the safe side, we'll skip all non-standard +* rates and move up to the next standard one. This is +* because some panels will pass link training with a non- +* standard rate but just show garbage. If the non-standard +* rates are useful we should figure out how to enable them +* through querying the panel, having a per-panel whitelist, +* or adding a DT property. +*/ + if (!ti_sn_bridge_dp_rate_standard[dp_rate_idx]) + continue; + ret = ti_sn_link_training(pdata, dp_rate_idx, &last_err_str); if (!ret) break; -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 8/9] drm/bridge: ti-sn65dsi86: Train at faster rates if slower ones fail
If we fail training at a lower DP link rate let's now keep trying until we run out of rates to try. Basically the algorithm here is to start at the link rate that is the theoretical minimum and then slowly bump up until we run out of rates or hit the max rate of the sink. We query the sink using a DPCD read. This is, in fact, important in practice. Specifically at least one panel hooked up to the bridge (AUO B116XAK01) had a theoretical min rate more than 1.62 GHz (if run at 24 bpp) and fails to train at the next rate (2.16 GHz). It would train at 2.7 GHz, though. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 69 +++ 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 48fb4dc72e1c..cc8bef172f69 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -454,7 +454,7 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = { 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 }; -static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata) +static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn_bridge *pdata) { unsigned int bit_rate_khz, dp_rate_mhz; unsigned int i; @@ -472,8 +472,42 @@ static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata) if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz) break; - regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG, - DP_DATARATE_MASK, DP_DATARATE(i)); + return i; +} + +static int ti_sn_bridge_get_max_dp_rate_idx(struct ti_sn_bridge *pdata) +{ + u8 data; + int ret; + + ret = drm_dp_dpcd_readb(&pdata->aux, DP_MAX_LINK_RATE, &data); + if (ret != 1) { + DRM_DEV_ERROR(pdata->dev, + "Can't read max rate (%d); assuming 5.4 GHz\n", + ret); + return ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; + } + + /* +* Return an index into ti_sn_bridge_dp_rate_lut. Just hardcode +* these indicies since it's not like the register spec is ever going +* to change and a loop would just be more complicated. Apparently +* the DP sink can only return these few rates as supported even +* though the bridge allows some rates in between. +*/ + switch (data) { + case DP_LINK_BW_1_62: + return 1; + case DP_LINK_BW_2_7: + return 4; + case DP_LINK_BW_5_4: + return 7; + } + + DRM_DEV_ERROR(pdata->dev, + "Unexpected max data rate (%#x); assuming 5.4 GHz\n", + (int)data); + return ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; } static void ti_sn_bridge_set_video_timings(struct ti_sn_bridge *pdata) @@ -530,13 +564,15 @@ static unsigned int ti_sn_get_max_lanes(struct ti_sn_bridge *pdata) return data & DP_LANE_COUNT_MASK; } -static int ti_sn_link_training(struct ti_sn_bridge *pdata) +static int ti_sn_link_training(struct ti_sn_bridge *pdata, int dp_rate_idx, + const char **last_err_str) { unsigned int val; int ret; /* set dp clk frequency value */ - ti_sn_bridge_set_dp_rate(pdata); + regmap_update_bits(pdata->regmap, SN_DATARATE_CONFIG_REG, + DP_DATARATE_MASK, DP_DATARATE(dp_rate_idx)); /* enable DP PLL */ regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1); @@ -545,7 +581,7 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata) val & DPPLL_SRC_DP_PLL_LOCK, 1000, 50 * 1000); if (ret) { - DRM_ERROR("DP_PLL_LOCK polling failed (%d)\n", ret); + *last_err_str = "DP_PLL_LOCK polling failed"; goto exit; } @@ -556,9 +592,9 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata) val == ML_TX_NORMAL_MODE, 1000, 500 * 1000); if (ret) { - DRM_ERROR("Training complete polling failed (%d)\n", ret); + *last_err_str = "Training complete polling failed"; } else if (val == ML_TX_MAIN_LINK_OFF) { - DRM_ERROR("Link training failed, link is off\n"); + *last_err_str = "Link training failed, link is off"; ret = -EIO; } @@ -573,6 +609,9 @@ static int ti_sn_link_training(struct ti_sn_bridge *pdata) static void ti_sn_bridge_enable(struct drm_bridge *bridge) { struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); + const char *last_err_str; + int dp_rate_idx; + int max_dp_rate_idx; unsigned int val; int ret; @@ -616,9 +655,19 @@ static void ti_sn_
[PATCH 5/9] drm/bridge: ti-sn65dsi86: Read num lanes from the DP sink
At least one panel hooked up to the bridge (AUO B116XAK01) only supports 1 lane of DP. Let's read this information and stop hardcoding 4 DP lanes. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 32 +-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index d55d19759796..0fc9e97b2d98 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -313,8 +313,7 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge) goto err_dsi_host; } - /* TODO: setting to 4 lanes always for now */ - pdata->dp_lanes = 4; + /* TODO: setting to 4 MIPI lanes always for now */ dsi->lanes = 4; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO; @@ -511,12 +510,41 @@ static void ti_sn_bridge_set_video_timings(struct ti_sn_bridge *pdata) usleep_range(1, 10500); /* 10ms delay recommended by spec */ } +static unsigned int ti_sn_get_max_lanes(struct ti_sn_bridge *pdata) +{ + u8 data; + int ret; + + ret = drm_dp_dpcd_readb(&pdata->aux, DP_MAX_LANE_COUNT, &data); + if (ret != 1) { + DRM_DEV_ERROR(pdata->dev, + "Can't read lane count (%d); assuming 4\n", ret); + return 4; + } + + return data & DP_LANE_COUNT_MASK; +} + static void ti_sn_bridge_enable(struct drm_bridge *bridge) { struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); unsigned int val; int ret; + /* +* Run with the maximum number of lanes that the DP sink supports. +* +* Depending use cases, we might want to revisit this later because: +* - It's plausible that someone may have run fewer lines to the +* sink than the sink actually supports, assuming that the lines +* will just be driven at a higher rate. +* - The DP spec seems to indicate that it's more important to minimize +* the number of lanes than the link rate. +* +* If we do revisit, it would be important to measure the power impact. +*/ + pdata->dp_lanes = ti_sn_get_max_lanes(pdata); + /* DSI_A lane config */ val = CHA_DSI_LANES(4 - pdata->dsi->lanes); regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 4/9] drm/bridge: ti-sn65dsi86: Config number of DP lanes Mo' Betta
The driver used to say that the value to program into bridge register 0x93 was dp_lanes - 1. Looking at the datasheet for the bridge, this is wrong. The data sheet says: * 1 = 1 lane * 2 = 2 lanes * 3 = 4 lanes A more proper way to express this encoding is min(dp_lanes, 3). At the moment this change has zero effect because we've hardcoded the number of DP lanes to 4. ...and (4 - 1) == min(4, 3). How fortunate! ...but soon we'll stop hardcoding the number of lanes. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index ab644baaf90c..d55d19759796 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -523,7 +523,7 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) CHA_DSI_LANES_MASK, val); /* DP lane config */ - val = DP_NUM_LANES(pdata->dp_lanes - 1); + val = DP_NUM_LANES(min(pdata->dp_lanes, 3)); regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, val); -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 3/9] drm/bridge: ti-sn65dsi86: Don't use MIPI variables for DP link
The ti-sn65dsi86 is a bridge from MIPI to DP and thus has two links: the MIPI link and the DP link. The two links do not need to have the same format or number of lanes. Stop using MIPI variables when talking about the DP link. This has zero functional change because: * currently we are hardcoding the MIPI link as unpacked RGB888 which requires 24 bits and currently we are not changing the DP link rate from the bridge's default of 8 bits per pixel. * currently we are hardcoding both the MIPI and DP as being 4 lanes. This is all in prep for fixing some of the above. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 7b596af265e4..ab644baaf90c 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -100,6 +100,7 @@ struct ti_sn_bridge { struct drm_panel*panel; struct gpio_desc*enable_gpio; struct regulator_bulk_data supplies[SN_REGULATOR_SUPPLY_NUM]; + int dp_lanes; }; static const struct regmap_range ti_sn_bridge_volatile_ranges[] = { @@ -313,6 +314,7 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge) } /* TODO: setting to 4 lanes always for now */ + pdata->dp_lanes = 4; dsi->lanes = 4; dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO; @@ -451,13 +453,17 @@ static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata) struct drm_display_mode *mode = &pdata->bridge.encoder->crtc->state->adjusted_mode; - /* set DSIA clk frequency */ - bit_rate_mhz = (mode->clock / 1000) * - mipi_dsi_pixel_format_to_bpp(pdata->dsi->format); + /* +* Calculate minimum bit rate based on our pixel clock. At +* the moment this driver never sets the DP_18BPP_EN bit in +* register 0x5b so we hardcode 24bpp. +*/ + bit_rate_mhz = (mode->clock / 1000) * 24; - /* set DP data rate */ - dp_rate_mhz = ((bit_rate_mhz / pdata->dsi->lanes) * DP_CLK_FUDGE_NUM) / + /* Calculate minimum DP data rate, taking 80% as per DP spec */ + dp_rate_mhz = ((bit_rate_mhz / pdata->dp_lanes) * DP_CLK_FUDGE_NUM) / DP_CLK_FUDGE_DEN; + for (i = 1; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++) if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz) break; @@ -517,7 +523,7 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) CHA_DSI_LANES_MASK, val); /* DP lane config */ - val = DP_NUM_LANES(pdata->dsi->lanes - 1); + val = DP_NUM_LANES(pdata->dp_lanes - 1); regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, val); -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/9] drm/bridge: ti-sn65dsi86: zero is never greater than an unsigned int
When we iterate over ti_sn_bridge_dp_rate_lut, there's no reason to start at index 0 which always contains the value 0. 0 is not a valid link rate. This change should have no real effect but is a small cleanup. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 2fb9370a76e6..7b596af265e4 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -458,7 +458,7 @@ static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata) /* set DP data rate */ dp_rate_mhz = ((bit_rate_mhz / pdata->dsi->lanes) * DP_CLK_FUDGE_NUM) / DP_CLK_FUDGE_DEN; - for (i = 0; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++) + for (i = 1; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++) if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz) break; -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 0/9] drm/bridge: ti-sn65dsi86: Improve support for AUO B116XAK01 + other low res DP
This series contains a pile of patches that was created to support hooking up the AUO B116XAK01 panel to the eDP side of the bridge. In general it should be useful for hooking up a wider variety of DP panels to the bridge, especially those with lower resolution and lower bits per pixel. The overall result of this series: * Allows panels with fewer than 4 DP lanes hooked up to work. * Optimizes the link rate for panels with 6 bpp. * Supports trying more than one link rate when training if the main link rate didn't work. It's not expected that this series will break any existing users, but it is possible that the patch to skip non-standard DP rates could mean that a panel that used to use one of these non-standard link rates will now run at a higher rate than it used to. If this happens, the patch could be reverted or someone could figure out how to decide when it's OK to use the non-standard rates. To support the AUO B116XAK01, we could actually stop at the ("Use 18-bit DP if we can") patch since that causes the panel to run at a link rate of 1.62 which works. The patches to try more than one link rate were all developed prior to realizing that I could just use 18-bit mode and were validated with that patch reverted. The patch to try more than one rate was validated by forcing the code to try 2.16 GHz (but still skip 2.43 GHz, which trains but shows garbage on AUO B116XAK01) and seeing that we'd try 2.16 GHz (and fail) and then eventually pass at 2.7 GHz and show a pretty screen. These patches were tested on sdm845-cheza atop mainline as of 2019-12-13 and also on another board (the one with AUO B116XAK01) atop a downstream kernel tree. This patch series doesn't do anything to optimize the MIPI link and only focuses on the DP link. For instance, it's left as an exercise to the reader to see if we can use the 666-packed mode on the MIPI link and save some power (because we could lower the clock rate). I am nowhere near a display expert and my knowledge of DP and MIPI is pretty much zero. If something about this patch series smells wrong, it probably is. Please let know and I'll try to fix it. Douglas Anderson (9): drm/bridge: ti-sn65dsi86: Split the setting of the dp and dsi rates drm/bridge: ti-sn65dsi86: zero is never greater than an unsigned int drm/bridge: ti-sn65dsi86: Don't use MIPI variables for DP link drm/bridge: ti-sn65dsi86: Config number of DP lanes Mo' Betta drm/bridge: ti-sn65dsi86: Read num lanes from the DP sink drm/bridge: ti-sn65dsi86: Use 18-bit DP if we can drm/bridge: ti-sn65dsi86: Group DP link training bits in a function drm/bridge: ti-sn65dsi86: Train at faster rates if slower ones fail drm/bridge: ti-sn65dsi86: Skip non-standard DP rates drivers/gpu/drm/bridge/ti-sn65dsi86.c | 230 +- 1 file changed, 187 insertions(+), 43 deletions(-) -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 7/9] drm/bridge: ti-sn65dsi86: Group DP link training bits in a function
We'll re-organize the ti_sn_bridge_enable() function a bit to group together all the parts relating to link training and split them into a sub-function. This is not intended to have any functional change and is in preparation for trying link training several times at different rates. One small side effect here is that if link training fails we'll now leave the DP PLL disabled, but that seems like a sane thing to do. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 86 --- 1 file changed, 52 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index d5990a0947b9..48fb4dc72e1c 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -530,6 +530,46 @@ static unsigned int ti_sn_get_max_lanes(struct ti_sn_bridge *pdata) return data & DP_LANE_COUNT_MASK; } +static int ti_sn_link_training(struct ti_sn_bridge *pdata) +{ + unsigned int val; + int ret; + + /* set dp clk frequency value */ + ti_sn_bridge_set_dp_rate(pdata); + + /* enable DP PLL */ + regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1); + + ret = regmap_read_poll_timeout(pdata->regmap, SN_DPPLL_SRC_REG, val, + val & DPPLL_SRC_DP_PLL_LOCK, 1000, + 50 * 1000); + if (ret) { + DRM_ERROR("DP_PLL_LOCK polling failed (%d)\n", ret); + goto exit; + } + + /* Semi auto link training mode */ + regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A); + ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val, + val == ML_TX_MAIN_LINK_OFF || + val == ML_TX_NORMAL_MODE, 1000, + 500 * 1000); + if (ret) { + DRM_ERROR("Training complete polling failed (%d)\n", ret); + } else if (val == ML_TX_MAIN_LINK_OFF) { + DRM_ERROR("Link training failed, link is off\n"); + ret = -EIO; + } + +exit: + /* Disable the PLL if we failed */ + if (ret) + regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 0); + + return ret; +} + static void ti_sn_bridge_enable(struct drm_bridge *bridge) { struct ti_sn_bridge *pdata = bridge_to_ti_sn_bridge(bridge); @@ -555,29 +595,8 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, CHA_DSI_LANES_MASK, val); - /* Set the DP output format (18 bpp or 24 bpp) */ - val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0; - regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val); - - /* DP lane config */ - val = DP_NUM_LANES(min(pdata->dp_lanes, 3)); - regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, - val); - - /* set dsi/dp clk frequency value */ + /* set dsi clk frequency value */ ti_sn_bridge_set_dsi_rate(pdata); - ti_sn_bridge_set_dp_rate(pdata); - - /* enable DP PLL */ - regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1); - - ret = regmap_read_poll_timeout(pdata->regmap, SN_DPPLL_SRC_REG, val, - val & DPPLL_SRC_DP_PLL_LOCK, 1000, - 50 * 1000); - if (ret) { - DRM_ERROR("DP_PLL_LOCK polling failed (%d)\n", ret); - return; - } /** * The SN65DSI86 only supports ASSR Display Authentication method and @@ -588,19 +607,18 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET, DP_ALTERNATE_SCRAMBLER_RESET_ENABLE); - /* Semi auto link training mode */ - regmap_write(pdata->regmap, SN_ML_TX_MODE_REG, 0x0A); - ret = regmap_read_poll_timeout(pdata->regmap, SN_ML_TX_MODE_REG, val, - val == ML_TX_MAIN_LINK_OFF || - val == ML_TX_NORMAL_MODE, 1000, - 500 * 1000); - if (ret) { - DRM_ERROR("Training complete polling failed (%d)\n", ret); - return; - } else if (val == ML_TX_MAIN_LINK_OFF) { - DRM_ERROR("Link training failed, link is off\n"); + /* Set the DP output format (18 bpp or 24 bpp) */ + val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0; + regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val); + + /* DP lane config */ + val = DP_NUM_LANES(min(pdata->dp_lanes, 3)); + regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, + val); + + ret = ti_sn_link_t
[PATCH 6/9] drm/bridge: ti-sn65dsi86: Use 18-bit DP if we can
The current bridge driver always forced us to use 24 bits per pixel over the DP link. This is a waste if you are hooked up to a panel that only supports 6 bits per color or fewer, since in that case you ran run at 18 bits per pixel and thus end up at a lower DP clock rate. Let's support this. While at it, let's clean up the math in the function to avoid rounding errors (and round in the correct direction when we have to round). Numbers are sufficiently small (because mode->clock is in kHz) that we don't need to worry about integer overflow. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 27 ++- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 0fc9e97b2d98..d5990a0947b9 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -51,6 +51,7 @@ #define SN_ENH_FRAME_REG 0x5A #define VSTREAM_ENABLEBIT(3) #define SN_DATA_FORMAT_REG 0x5B +#define BPP_18_RGBBIT(0) #define SN_HPD_DISABLE_REG 0x5C #define HPD_DISABLE BIT(0) #define SN_AUX_WDATA_REG(x)(0x64 + (x)) @@ -436,6 +437,14 @@ static void ti_sn_bridge_set_dsi_rate(struct ti_sn_bridge *pdata) regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); } +static unsigned int ti_sn_bridge_get_bpp(struct ti_sn_bridge *pdata) +{ + if (pdata->connector.display_info.bpc <= 6) + return 18; + else + return 24; +} + /** * LUT index corresponds to register value and * LUT values corresponds to dp data rate supported @@ -447,21 +456,17 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = { static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata) { - unsigned int bit_rate_mhz, dp_rate_mhz; + unsigned int bit_rate_khz, dp_rate_mhz; unsigned int i; struct drm_display_mode *mode = &pdata->bridge.encoder->crtc->state->adjusted_mode; - /* -* Calculate minimum bit rate based on our pixel clock. At -* the moment this driver never sets the DP_18BPP_EN bit in -* register 0x5b so we hardcode 24bpp. -*/ - bit_rate_mhz = (mode->clock / 1000) * 24; + /* Calculate minimum bit rate based on our pixel clock. */ + bit_rate_khz = mode->clock * ti_sn_bridge_get_bpp(pdata); /* Calculate minimum DP data rate, taking 80% as per DP spec */ - dp_rate_mhz = ((bit_rate_mhz / pdata->dp_lanes) * DP_CLK_FUDGE_NUM) / - DP_CLK_FUDGE_DEN; + dp_rate_mhz = DIV_ROUND_UP(bit_rate_khz * DP_CLK_FUDGE_NUM, + 1000 * pdata->dp_lanes * DP_CLK_FUDGE_DEN); for (i = 1; i < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut) - 1; i++) if (ti_sn_bridge_dp_rate_lut[i] > dp_rate_mhz) @@ -550,6 +555,10 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, CHA_DSI_LANES_MASK, val); + /* Set the DP output format (18 bpp or 24 bpp) */ + val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0; + regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val); + /* DP lane config */ val = DP_NUM_LANES(min(pdata->dp_lanes, 3)); regmap_update_bits(pdata->regmap, SN_SSC_CONFIG_REG, DP_NUM_LANES_MASK, -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/9] drm/bridge: ti-sn65dsi86: Split the setting of the dp and dsi rates
These two things were in one function. Split into two. This looks like it's duplicating some code, but don't worry. This is is just in preparation for future changes. This is intended to have zero functional change and will just make future patches easier to understand. Signed-off-by: Douglas Anderson --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 33 +++ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 43abf01ebd4c..2fb9370a76e6 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -417,6 +417,24 @@ static void ti_sn_bridge_set_refclk_freq(struct ti_sn_bridge *pdata) REFCLK_FREQ(i)); } +static void ti_sn_bridge_set_dsi_rate(struct ti_sn_bridge *pdata) +{ + unsigned int bit_rate_mhz, clk_freq_mhz; + unsigned int val; + struct drm_display_mode *mode = + &pdata->bridge.encoder->crtc->state->adjusted_mode; + + /* set DSIA clk frequency */ + bit_rate_mhz = (mode->clock / 1000) * + mipi_dsi_pixel_format_to_bpp(pdata->dsi->format); + clk_freq_mhz = bit_rate_mhz / (pdata->dsi->lanes * 2); + + /* for each increment in val, frequency increases by 5MHz */ + val = (MIN_DSI_CLK_FREQ_MHZ / 5) + + (((clk_freq_mhz - MIN_DSI_CLK_FREQ_MHZ) / 5) & 0xFF); + regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); +} + /** * LUT index corresponds to register value and * LUT values corresponds to dp data rate supported @@ -426,22 +444,16 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = { 0, 1620, 2160, 2430, 2700, 3240, 4320, 5400 }; -static void ti_sn_bridge_set_dsi_dp_rate(struct ti_sn_bridge *pdata) +static void ti_sn_bridge_set_dp_rate(struct ti_sn_bridge *pdata) { - unsigned int bit_rate_mhz, clk_freq_mhz, dp_rate_mhz; - unsigned int val, i; + unsigned int bit_rate_mhz, dp_rate_mhz; + unsigned int i; struct drm_display_mode *mode = &pdata->bridge.encoder->crtc->state->adjusted_mode; /* set DSIA clk frequency */ bit_rate_mhz = (mode->clock / 1000) * mipi_dsi_pixel_format_to_bpp(pdata->dsi->format); - clk_freq_mhz = bit_rate_mhz / (pdata->dsi->lanes * 2); - - /* for each increment in val, frequency increases by 5MHz */ - val = (MIN_DSI_CLK_FREQ_MHZ / 5) + - (((clk_freq_mhz - MIN_DSI_CLK_FREQ_MHZ) / 5) & 0xFF); - regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); /* set DP data rate */ dp_rate_mhz = ((bit_rate_mhz / pdata->dsi->lanes) * DP_CLK_FUDGE_NUM) / @@ -510,7 +522,8 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) val); /* set dsi/dp clk frequency value */ - ti_sn_bridge_set_dsi_dp_rate(pdata); + ti_sn_bridge_set_dsi_rate(pdata); + ti_sn_bridge_set_dp_rate(pdata); /* enable DP PLL */ regmap_write(pdata->regmap, SN_PLL_ENABLE_REG, 1); -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 4/4] dt-bindings: display: add i.MX6 MIPI DSI host controller doc
On Mon, Dec 02, 2019 at 09:33:59PM +0200, Adrian Ratiu wrote: > This provides an example DT binding for the MIPI DSI host controller > present on the i.MX6 SoC based on Synopsis DesignWare v1.01 IP. > > Cc: Rob Herring > Cc: Neil Armstrong > Signed-off-by: Sjoerd Simons > Signed-off-by: Martyn Welch > Signed-off-by: Adrian Ratiu > --- > .../display/imx/fsl,mipi-dsi-imx6.yaml| 136 ++ > 1 file changed, 136 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/imx/fsl,mipi-dsi-imx6.yaml Run 'make dt_binding_check' and fix the errors. See Documentation/devicetree/writing-schema.rst. > > diff --git > a/Documentation/devicetree/bindings/display/imx/fsl,mipi-dsi-imx6.yaml > b/Documentation/devicetree/bindings/display/imx/fsl,mipi-dsi-imx6.yaml > new file mode 100644 > index ..8c9603c28240 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/imx/fsl,mipi-dsi-imx6.yaml > @@ -0,0 +1,136 @@ > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/fsl,mipi-dsi-imx6.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Freescale i.MX6 DW MIPI DSI Host Controller > + > +description: > + The DSI host controller is a Synopsys DesignWare MIPI DSI v1.01 IP with a > companion PHY IP. > + > + These DT bindings follow the Synopsys DW MIPI DSI bindings defined in > + Documentation/devicetree/bindings/display/bridge/dw_mipi_dsi.txt with > + the following device-specific properties. > + > +properties: > + compatible: > +const: [ "fsl,imx6q-mipi-dsi", "snps,dw-mipi-dsi" ] Not valid json-schema. You want 'items' with 2 'const' entries. > + > + reg: > +maxItems: 1 > + > + interrupts: > +maxItems: 1 > + > + clocks: > +items: > + - description: Module Clock > + - description: DSI bus clock > +minItems: 2 > +maxItems: 2 Don't need these. The min/max is implied by length of 'items'. > + > + clock-names: > +items: > + - const: pclk > + - const: ref > +minItems: 2 > +maxItems: 2 > + > + fsl,gpr: > +description: Phandle to the iomuxc-gpr region containing the multiplexer > control register. > +const: *gpr Not a const. Should be a phandle type. > + > + ports: > +type: object > +description: > + A node containing DSI input & output port nodes with endpoint > + definitions as documented in > + Documentation/devicetree/bindings/media/video-interfaces.txt > + Documentation/devicetree/bindings/graph.txt > +properties: > + port@0: > +type: object > +description: > + DSI input port node, connected to the ltdc rgb output port. > + > + port@1: > +type: object > +description: > + DSI output port node, connected to a panel or a bridge input port" > + > +patternProperties: > + "^(panel|panel-dsi)@[0-9]$": DSI virtual channels are 0-3 only. Do you really need both node names? > +type: object > +description: > + A node containing the panel or bridge description as documented in > + Documentation/devicetree/bindings/display/mipi-dsi-bus.txt > +properties: > + port: > +type: object > +description: > + Panel or bridge port node, connected to the DSI output port > (port@1) > + > + "#address-cells": > +const: 1 > + > + "#size-cells": > +const: 0 > + > +required: > + - "#address-cells" > + - "#size-cells" > + - compatible > + - reg > + - interrupts > + - clocks > + - clock-names > + - ports > + > +additionalProperties: false > + > +examples: > + - | > +dsi: dsi@21e { > +#address-cells = <1>; > +#size-cells = <0>; > +compatible = "fsl,imx6q-mipi-dsi", "snps,dw-mipi-dsi"; > +reg = <0x021e 0x4000>; > +interrupts = <0 102 IRQ_TYPE_LEVEL_HIGH>; > +fsl,gpr = <&gpr>; > +clocks = <&clks IMX6QDL_CLK_MIPI_CORE_CFG>, > + <&clks IMX6QDL_CLK_MIPI_IPG>; > +clock-names = "ref", "pclk"; > + > +ports { > +port@0 { > +reg = <0>; > +dsi_in: endpoint { > +remote-endpoint = <; > +}; > +}; > + > +port@1 { > +reg = <1>; > +dsi_out: endpoint { > +remote-endpoint = <&panel_in>; > +}; > +}; > +}; > + > +panel@0 { > +compatible = "sharp,ls032b3sx01"; > +reg = <0>; > +reset-gpios = <&gpio6 8 GPIO_ACTIVE_LOW>; > + > +ports { > +port@0 { > +panel_in: endpoint { > +remote-endpoint = <&dsi_out>; > +}; > +}; > +}; > +}; > +}; > + > +... > -- > 2.24.0 > __
Re: [Intel-gfx] [PATCH 1/5] drm: Add __drm_atomic_helper_crtc_state_reset() & co.
On Thu, Nov 07, 2019 at 04:24:13PM +0200, Ville Syrjälä wrote: From: Ville Syrjälä Annoyingly __drm_atomic_helper_crtc_reset() does two totally separate things: a) reset the state to defaults values b) assign the crtc->state pointer I just want a) without the b) so let's split out part a) into __drm_atomic_helper_crtc_state_reset(). And of course we'll do the same thing for planes and connectors. Signed-off-by: Ville Syrjälä --- drivers/gpu/drm/drm_atomic_state_helper.c | 70 --- include/drm/drm_atomic_state_helper.h | 6 ++ 2 files changed, 67 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index d0a937fb0c56..a972068d58cf 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -57,6 +57,22 @@ * for these functions. */ +/** + * __drm_atomic_helper_crtc_state_reset - reset the CRTC state + * @crtc_state: atomic CRTC state, must not be NULL + * @crtc: CRTC object, must not be NULL + * + * Initializes the newly allocated @crtc_state with default + * values. This is useful for drivers that subclass the CRTC state. + */ +void +__drm_atomic_helper_crtc_state_reset(struct drm_crtc_state *crtc_state, +struct drm_crtc *crtc) +{ + crtc_state->crtc = crtc; +} +EXPORT_SYMBOL(__drm_atomic_helper_crtc_state_reset); + /** * __drm_atomic_helper_crtc_reset - reset state on CRTC * @crtc: drm CRTC @@ -74,7 +90,7 @@ __drm_atomic_helper_crtc_reset(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state) { if (crtc_state) - crtc_state->crtc = crtc; + __drm_atomic_helper_crtc_state_reset(crtc_state, crtc); crtc->state = crtc_state; } @@ -212,23 +228,43 @@ void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); /** - * __drm_atomic_helper_plane_reset - resets planes state to default values + * __drm_atomic_helper_plane_state_reset - resets plane state to default values + * @plane_state: atomic plane state, must not be NULL * @plane: plane object, must not be NULL - * @state: atomic plane state, must not be NULL * - * Initializes plane state to default. This is useful for drivers that subclass - * the plane state. + * Initializes the newly allocated @plane_state with default + * values. This is useful for drivers that subclass the CRTC state. */ -void __drm_atomic_helper_plane_reset(struct drm_plane *plane, -struct drm_plane_state *state) +void __drm_atomic_helper_plane_state_reset(struct drm_plane_state *state, + struct drm_plane *plane) { state->plane = plane; state->rotation = DRM_MODE_ROTATE_0; state->alpha = DRM_BLEND_ALPHA_OPAQUE; state->pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; +} +EXPORT_SYMBOL(__drm_atomic_helper_plane_state_reset); - plane->state = state; +/** + * __drm_atomic_helper_plane_reset - reset state on plane + * @plane: drm plane + * @plane_state: plane state to assign + * + * Initializes the newly allocated @plane_state and assigns it to + * the &drm_crtc->state pointer of @plane, usually required when + * initializing the drivers or when called from the &drm_plane_funcs.reset + * hook. + * + * This is useful for drivers that subclass the plane state. + */ +void __drm_atomic_helper_plane_reset(struct drm_plane *plane, +struct drm_plane_state *plane_state) +{ + if (plane_state) + __drm_atomic_helper_plane_state_reset(plane_state, plane); + + plane->state = plane_state; } EXPORT_SYMBOL(__drm_atomic_helper_plane_reset); @@ -335,6 +371,22 @@ void drm_atomic_helper_plane_destroy_state(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); +/** + * __drm_atomic_helper_connector_state_reset - reset the connector state + * @conn__state: atomic connector state, must not be NULL typo here, otherwise Reviewed-by: Lucas De Marchi Lucas De Marchi + * @connector: connectotr object, must not be NULL + * + * Initializes the newly allocated @conn_state with default + * values. This is useful for drivers that subclass the connector state. + */ +void +__drm_atomic_helper_connector_state_reset(struct drm_connector_state *conn_state, + struct drm_connector *connector) +{ + conn_state->connector = connector; +} +EXPORT_SYMBOL(__drm_atomic_helper_connector_state_reset); + /** * __drm_atomic_helper_connector_reset - reset state on connector * @connector: drm connector @@ -352,7 +404,7 @@ __drm_atomic_helper_connector_reset(struct drm_connector *connector, struct drm_connector_state *conn_state) { if (conn_state) - conn_state->connector = connector; + _
Re: [PATCH] backlight: pwm_bl: Switch to full GPIO descriptor
On Fri, Dec 13, 2019 at 6:30 PM Robert Jarzmik wrote: > Daniel Thompson writes: > > > > ... I worry that palmtc.c is no longer compilable for some configs. > I you're right, there is a very simple way to test it : > make pxa_defconfig && make -j > > It should scream if the compilation is broken, and the kernel CI should > certainly protect us. I actually push my patches to the zeroday but it has reliability issues... Yours, Linus Walleij ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] backlight: corgi: Convert to use GPIO descriptors
On Fri, Dec 13, 2019 at 6:24 PM Robert Jarzmik wrote: > Linus Walleij writes: > > On Sun, Dec 8, 2019 at 9:06 PM Robert Jarzmik > > wrote: > >> Linus Walleij writes: > > So it will theoretically "spi0.1" > > > > Beware about bugs in the above interpreter because it is > > just my brain. > > Well, if nobody complains because of testing, why not, your explanation seems > as > good as it could be. :D > If you would be so kind as to carry these changes through your tree instead of > the PXA one, please have my : > Acked-by: Robert Jarzmik I was hoping the backlight people would pick it up to the backlight tree. Yours, Linus Walleij ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 2/3] dt-bindings: panel: Document Frida FRD350H54004 LCD panel
On Mon, Dec 02, 2019 at 04:41:22PM +0100, Paul Cercueil wrote: > Add bindings documentation for the Frida 3.5" (320x240 pixels) 24-bit > TFT LCD panel. > > v2: Switch documentation from plain text to YAML > > Signed-off-by: Paul Cercueil > --- > .../display/panel/frida,frd350h54004.yaml | 31 +++ > 1 file changed, 31 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/frida,frd350h54004.yaml > > diff --git > a/Documentation/devicetree/bindings/display/panel/frida,frd350h54004.yaml > b/Documentation/devicetree/bindings/display/panel/frida,frd350h54004.yaml > new file mode 100644 > index ..a29c3daf0c78 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/panel/frida,frd350h54004.yaml > @@ -0,0 +1,31 @@ > +# SPDX-License-Identifier: GPL-2.0 Dual license new bindings please: (GPL-2.0-only OR BSD-2-Clause) With that, Reviewed-by: Rob Herring > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/frida,frd350h54004.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Frida 3.5" (320x240 pixels) 24-bit TFT LCD panel > + > +maintainers: > + - Paul Cercueil > + - Thierry Reding > + > +allOf: > + - $ref: panel-common.yaml# > + > +properties: > + compatible: > +const: frida,frd350h54004 > + > + power-supply: true > + backlight: true > + enable-gpios: true > + port: true > + > +additionalProperties: false > + > +required: > + - compatible > + - power-supply > + > +... > -- > 2.24.0 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 1/3] dt-bindings: vendor-prefixes: Add Shenzhen Frida LCD Co., Ltd.
On Mon, 2 Dec 2019 16:41:21 +0100, Paul Cercueil wrote: > Add an entry for Shenzhen Frida LCD Co., Ltd. > > v2: No change > > Signed-off-by: Paul Cercueil > Acked-by: Sam Ravnborg > --- > Documentation/devicetree/bindings/vendor-prefixes.yaml | 2 ++ > 1 file changed, 2 insertions(+) > Acked-by: Rob Herring ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [RFC v2 02/12] drm/i915/svm: Runtime (RT) allocator support
On Fri, Dec 13, 2019 at 04:58:42PM -0600, Jason Ekstrand wrote: +/** + * struct drm_i915_gem_vm_bind + * + * Bind an object in a vm's page table. First off, this is something I've wanted for a while for Vulkan, it's just never made its way high enough up the priority list. However, it's going to have to come one way or another soon. I'm glad to see kernel API for this being proposed. I do, however, have a few high-level comments/questions about the API: 1. In order to be useful for sparse memory support, the API has to go the other way around so that it binds a VA range to a range within the BO. It also needs to be able to handle overlapping where two different VA ranges may map to the same underlying bytes in the BO. This likely means that unbind needs to also take a VA range and only unbind that range. 2. If this is going to be useful for managing GL's address space where we have lots of BOs, we probably want it to take a list of ranges so we aren't making one ioctl for each thing we want to bind. Hi Jason, Yah, some of these requirements came up. They are not being done here due to time and effort involved in defining those requirements, implementing and validating. However, this ioctl can be extended in a backward compatible way to handle those requirements if required. 3. Why are there no ways to synchronize this with anything? For binding, this probably isn't really needed as long as the VA range you're binding is empty. However, if you want to move bindings around or unbind something, the only option is to block in userspace and then call bind/unbind. This can be done but it means even more threads in the UMD which is unpleasant. One could argue that that's more or less what the kernel is going to have to do so we may as well do it in userspace. However, I'm not 100% convinced that's true. --Jason Yah, that is the thought. But as SVM feature evolves, I think we can consider handling some such cases if hadling those in driver does make whole lot sense. Thanks, Niranjana + */ +struct drm_i915_gem_vm_bind { + /** VA start to bind **/ + __u64 start; + + /** Type of memory to [un]bind **/ + __u32 type; +#define I915_GEM_VM_BIND_SVM_OBJ 0 + + /** Object handle to [un]bind for I915_GEM_VM_BIND_SVM_OBJ type **/ + __u32 handle; + + /** vm to [un]bind **/ + __u32 vm_id; + + /** Flags **/ + __u32 flags; +#define I915_GEM_VM_BIND_UNBIND (1 << 0) +#define I915_GEM_VM_BIND_READONLY(1 << 1) +}; + #if defined(__cplusplus) } #endif -- 2.21.0.rc0.32.g243a4c7e27 ___ Intel-gfx mailing list intel-...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/intel-gfx ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [git pull] drm fixes for 5.5-rc2
The pull request you sent on Fri, 13 Dec 2019 17:04:44 +1000: > git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2019-12-13 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/b2cb931d724b08def6e833541a37b08ebd59ab43 Thank you! -- Deet-doot-dot, I am a bot. https://korg.wiki.kernel.org/userdoc/prtracker ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [Intel-gfx] [RFC v2 02/12] drm/i915/svm: Runtime (RT) allocator support
On Fri, Dec 13, 2019 at 4:07 PM Niranjana Vishwanathapura < niranjana.vishwanathap...@intel.com> wrote: > Shared Virtual Memory (SVM) runtime allocator support allows > binding a shared virtual address to a buffer object (BO) in the > device page table through an ioctl call. > > Cc: Joonas Lahtinen > Cc: Jon Bloomfield > Cc: Daniel Vetter > Cc: Sudeep Dutt > Signed-off-by: Niranjana Vishwanathapura < > niranjana.vishwanathap...@intel.com> > --- > drivers/gpu/drm/i915/Kconfig | 11 > drivers/gpu/drm/i915/Makefile | 3 + > .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 58 ++ > drivers/gpu/drm/i915/gem/i915_gem_svm.c | 60 +++ > drivers/gpu/drm/i915/gem/i915_gem_svm.h | 22 +++ > drivers/gpu/drm/i915/i915_drv.c | 21 +++ > drivers/gpu/drm/i915/i915_drv.h | 22 +++ > drivers/gpu/drm/i915/i915_gem_gtt.c | 1 + > drivers/gpu/drm/i915/i915_gem_gtt.h | 13 > include/uapi/drm/i915_drm.h | 27 + > 10 files changed, 227 insertions(+), 11 deletions(-) > create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_svm.c > create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_svm.h > > diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig > index ba9595960bbe..c2e48710eec8 100644 > --- a/drivers/gpu/drm/i915/Kconfig > +++ b/drivers/gpu/drm/i915/Kconfig > @@ -137,6 +137,16 @@ config DRM_I915_GVT_KVMGT > Choose this option if you want to enable KVMGT support for > Intel GVT-g. > > +config DRM_I915_SVM > + bool "Enable Shared Virtual Memory support in i915" > + depends on STAGING > + depends on DRM_I915 > + default n > + help > + Choose this option if you want Shared Virtual Memory (SVM) > + support in i915. With SVM support, one can share the virtual > + address space between a process and the GPU. > + > menu "drm/i915 Debugging" > depends on DRM_I915 > depends on EXPERT > diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile > index e0fd10c0cfb8..75fe45633779 100644 > --- a/drivers/gpu/drm/i915/Makefile > +++ b/drivers/gpu/drm/i915/Makefile > @@ -153,6 +153,9 @@ i915-y += \ > intel_region_lmem.o \ > intel_wopcm.o > > +# SVM code > +i915-$(CONFIG_DRM_I915_SVM) += gem/i915_gem_svm.o > + > # general-purpose microcontroller (GuC) support > obj-y += gt/uc/ > i915-y += gt/uc/intel_uc.o \ > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > index 5003e616a1ad..af360238a392 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > @@ -2836,10 +2836,14 @@ int > i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, >struct drm_file *file) > { > + struct drm_i915_gem_exec_object2 *exec2_list, *exec2_list_user; > struct drm_i915_gem_execbuffer2 *args = data; > - struct drm_i915_gem_exec_object2 *exec2_list; > - struct drm_syncobj **fences = NULL; > const size_t count = args->buffer_count; > + struct drm_syncobj **fences = NULL; > + unsigned int i = 0, svm_count = 0; > + struct i915_address_space *vm; > + struct i915_gem_context *ctx; > + struct i915_svm_obj *svm_obj; > int err; > > if (!check_buffer_count(count)) { > @@ -2851,15 +2855,46 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, > void *data, > if (err) > return err; > > + ctx = i915_gem_context_lookup(file->driver_priv, args->rsvd1); > + if (!ctx || !rcu_access_pointer(ctx->vm)) > + return -ENOENT; > + > + rcu_read_lock(); > + vm = i915_vm_get(ctx->vm); > + rcu_read_unlock(); > + > +alloc_again: > + svm_count = vm->svm_count; > /* Allocate an extra slot for use by the command parser */ > - exec2_list = kvmalloc_array(count + 1, eb_element_size(), > + exec2_list = kvmalloc_array(count + svm_count + 1, > eb_element_size(), > __GFP_NOWARN | GFP_KERNEL); > if (exec2_list == NULL) { > DRM_DEBUG("Failed to allocate exec list for %zd buffers\n", > - count); > + count + svm_count); > return -ENOMEM; > } > - if (copy_from_user(exec2_list, > + mutex_lock(&vm->mutex); > + if (svm_count != vm->svm_count) { > + mutex_unlock(&vm->mutex); > + kvfree(exec2_list); > + goto alloc_again; > + } > + > + list_for_each_entry(svm_obj, &vm->svm_list, link) { > + memset(&exec2_list[i], 0, sizeof(*exec2_list)); > + exec2_list[i].handle = svm_obj->handle; > + exec2_list[i].offset = svm_obj->offset; > +
Re: [DPU PATCH v3 1/5] dt-bindings: msm/dp: add bindings of DP/DP-PLL driver for Snapdragon 845
On Mon, Dec 02, 2019 at 01:47:45PM +, Chandan Uddaraju wrote: > Add bindings for Snapdragon 845 DisplayPort and > display-port PLL driver. Is it just me, but I keep getting 2 copies of codeaurora emails? > > Changes in V2: > Provide details about sel-gpio This is V3, what changed in V3? > > Signed-off-by: Chandan Uddaraju > --- > .../devicetree/bindings/display/msm/dp.txt | 249 > + > .../devicetree/bindings/display/msm/dpu.txt| 16 +- > 2 files changed, 261 insertions(+), 4 deletions(-) > create mode 100644 Documentation/devicetree/bindings/display/msm/dp.txt New bindings should be in DT schema format. > diff --git a/Documentation/devicetree/bindings/display/msm/dp.txt > b/Documentation/devicetree/bindings/display/msm/dp.txt > new file mode 100644 > index 000..38be36d > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/msm/dp.txt > @@ -0,0 +1,249 @@ > +Qualcomm Technologies, Inc. > +DP is the master Display Port device which supports DP host controllers that > are compatible with VESA Display Port interface specification. > +DP Controller: Required properties: > +- compatible: Should be "qcom,dp-display". Needs to be more specific like including the SoC name. > +- reg: Base address and length of DP hardware's memory > mapped regions. > +- cell-index: Specifies the controller instance. FDT doesn't use cell-index. > +- reg-names:A list of strings that name the list of regs. > + "dp_ahb" - DP controller memory region. > + "dp_aux" - DP AUX memory region. > + "dp_link" - DP link layer memory region. > + "dp_p0" - DP pixel clock domain memory region. > + "dp_phy" - DP PHY memory region. > + "dp_ln_tx0" - USB3 DP PHY combo TX-0 lane memory region. > + "dp_ln_tx1" - USB3 DP PHY combo TX-1 lane memory region. > + "dp_mmss_cc" - Display Clock Control memory region. Sounds like a separate clock controller node... > + "qfprom_physical" - QFPROM Phys memory region. > + "dp_pll" - USB3 DP combo PLL memory region. > + "usb3_dp_com" - USB3 DP PHY combo memory region. Should be a separate phy node? > + "hdcp_physical" - DP HDCP memory region. The 'dp_' part is redundant. What does 'physical' mean? Addresses in DT are always physical. > +- interrupt-parent phandle to the interrupt parent device node. Don't document interrupt-parent. It's not required either because it could be in a parent node. > +- interrupts:The interrupt signal from the DP block. > +- clocks: Clocks required for Display Port operation. See [1] > for details on clock bindings. > +- clock-names: Names of the clocks corresponding to handles. > Following clocks are required: > + "core_aux_clk", > "core_usb_ref_clk_src","core_usb_ref_clk", "core_usb_cfg_ahb_clk", > + "core_usb_pipe_clk", "ctrl_link_clk", > "ctrl_link_iface_clk", "ctrl_crypto_clk", > + "ctrl_pixel_clk", "pixel_clk_rcg", "pixel_parent". Clocks should be actual clock inputs to the module. If 'pixel_parent' is just some parent clock you want to assign, then use assigned-clocks. > +- pll-node: phandle to DP PLL node. But you have a DP PLL reg region defined. Is this something else? Needs a 'qcom' prefix if it stays. > +- vdda-1p2-supply: phandle to vdda 1.2V regulator node. > +- vdda-0p9-supply: phandle to vdda 0.9V regulator node. > +- qcom,aux-cfg0-settings:Specifies the DP AUX configuration 0 > settings. The first > + entry in this array corresponds to the > register offset > + within DP AUX, while the remaining > entries indicate the > + programmable values. Needs more details on what these are and why they must be in DT. We generally don't just stuff DT with raw values to initial registers with. Line lengths should be <80 char. > +- qcom,aux-cfg1-settings:Specifies the DP AUX configuration 1 > settings. The first > + entry in this array corresponds to the > register offset > + within DP AUX, while the remaining > entries indicate the > + programmable values. > +- qcom,aux-cfg2-settings:Specifies the DP AUX configuration 2 > settings. The first > + entry in this array corresponds to the > register offset > + within DP AUX, while the remaining > entries indicate the > + programmable values. > +- qcom,aux-cfg3-settings:
Re: [RESEND PATCH v2] drm: Add getfb2 ioctl
On Fri, 2019-12-13 at 23:36 +0200, Ville Syrjälä wrote: > On Thu, Oct 03, 2019 at 11:31:25AM -0700, Juston Li wrote: > > From: Daniel Stone > > > > getfb2 allows us to pass multiple planes and modifiers, just like > > addfb2 > > over addfb. > > > > Changes since v1: > > - unused modifiers set to 0 instead of DRM_FORMAT_MOD_INVALID > > - update ioctl number > > > > Signed-off-by: Daniel Stone > > Signed-off-by: Juston Li > > --- > > drivers/gpu/drm/drm_crtc_internal.h | 2 + > > drivers/gpu/drm/drm_framebuffer.c | 110 > > > > drivers/gpu/drm/drm_ioctl.c | 1 + > > include/uapi/drm/drm.h | 2 + > > 4 files changed, 115 insertions(+) > > > > diff --git a/drivers/gpu/drm/drm_crtc_internal.h > > b/drivers/gpu/drm/drm_crtc_internal.h > > index c7d5e4c21423..16f2413403aa 100644 > > --- a/drivers/gpu/drm/drm_crtc_internal.h > > +++ b/drivers/gpu/drm/drm_crtc_internal.h > > @@ -216,6 +216,8 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev, > > void *data, struct drm_file *file_priv); > > int drm_mode_getfb(struct drm_device *dev, > >void *data, struct drm_file *file_priv); > > +int drm_mode_getfb2_ioctl(struct drm_device *dev, > > + void *data, struct drm_file *file_priv); > > int drm_mode_dirtyfb_ioctl(struct drm_device *dev, > >void *data, struct drm_file *file_priv); > > > > diff --git a/drivers/gpu/drm/drm_framebuffer.c > > b/drivers/gpu/drm/drm_framebuffer.c > > index 57564318ceea..6db54f177443 100644 > > --- a/drivers/gpu/drm/drm_framebuffer.c > > +++ b/drivers/gpu/drm/drm_framebuffer.c > > @@ -31,6 +31,7 @@ > > #include > > #include > > #include > > +#include > > #include > > #include > > > > @@ -548,7 +549,116 @@ int drm_mode_getfb(struct drm_device *dev, > > > > out: > > drm_framebuffer_put(fb); > > + return ret; > > +} > > + > > +/** > > + * drm_mode_getfb2 - get extended FB info > > + * @dev: drm device for the ioctl > > + * @data: data pointer for the ioctl > > + * @file_priv: drm file for the ioctl call > > + * > > + * Lookup the FB given its ID and return info about it. > > + * > > + * Called by the user via ioctl. > > + * > > + * Returns: > > + * Zero on success, negative errno on failure. > > + */ > > +int drm_mode_getfb2_ioctl(struct drm_device *dev, > > + void *data, struct drm_file *file_priv) > > +{ > > + struct drm_mode_fb_cmd2 *r = data; > > + struct drm_framebuffer *fb; > > + unsigned int i; > > + int ret; > > + > > + if (!drm_core_check_feature(dev, DRIVER_MODESET)) > > + return -EINVAL; > > + > > + fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); > > + if (!fb) > > + return -ENOENT; > > + > > + /* For multi-plane framebuffers, we require the driver to place > > the > > +* GEM objects directly in the drm_framebuffer. For single- > > plane > > +* framebuffers, we can fall back to create_handle. > > +*/ > > + if (!fb->obj[0] && > > + (fb->format->num_planes > 1 || !fb->funcs->create_handle)) > > { > > + ret = -ENODEV; > > + goto out; > > + } > > + > > + r->height = fb->height; > > + r->width = fb->width; > > + r->pixel_format = fb->format->format; > > + > > + r->flags = 0; > > + if (dev->mode_config.allow_fb_modifiers) > > + r->flags |= DRM_MODE_FB_MODIFIERS; > > + > > + for (i = 0; i < ARRAY_SIZE(r->handles); i++) { > > + r->handles[i] = 0; > > + r->pitches[i] = 0; > > + r->offsets[i] = 0; > > + r->modifier[i] = 0; > > + } > > > > + for (i = 0; i < fb->format->num_planes; i++) { > > + int j; > > + > > + r->pitches[i] = fb->pitches[i]; > > + r->offsets[i] = fb->offsets[i]; > > + if (dev->mode_config.allow_fb_modifiers) > > + r->modifier[i] = fb->modifier; > > + > > + /* If we reuse the same object for multiple planes, > > also > > +* return the same handle. > > +*/ > > + for (j = 0; j < i; j++) { > > + if (fb->obj[i] == fb->obj[j]) { > > + r->handles[i] = r->handles[j]; > > + break; > > + } > > + } > > + > > + if (r->handles[i]) > > + continue; > > + > > + if (fb->obj[i]) { > > + ret = drm_gem_handle_create(file_priv, fb- > > >obj[i], > > + &r->handles[i]); > > + } else { > > + WARN_ON(i > 0); > > + ret = fb->funcs->create_handle(fb, file_priv, > > + &r->handles[i]); > > + } > > getfb1 doesn't allow non-master/root to see the handles. Here we > don't > seem to have that same protection? Hmm yeah sorry I missed the protections handling. I think we can
Re: [PATCH RESEND 2/4] drm: bridge: anx7688: Add anx7688 bridge driver support.
Hi Hsin-Yi and Nicolas, Thank you for the patch. On Wed, Dec 11, 2019 at 02:19:09PM +0800, Hsin-Yi Wang wrote: > From: Nicolas Boichat > > ANX7688 is a HDMI to DP converter (as well as USB-C port controller), > that has an internal microcontroller. > > The only reason a Linux kernel driver is necessary is to reject > resolutions that require more bandwidth than what is available on > the DP side. DP bandwidth and lane count are reported by the bridge > via 2 registers on I2C. How about power, doesn't this chip have power supplies that potentially need to be controlled ? > Signed-off-by: Nicolas Boichat > Signed-off-by: Hsin-Yi Wang > --- > drivers/gpu/drm/bridge/Kconfig| 9 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/analogix-anx7688.c | 202 ++ > 3 files changed, 212 insertions(+) > create mode 100644 drivers/gpu/drm/bridge/analogix-anx7688.c > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index 34362976cd6f..1f3fc6bec842 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -16,6 +16,15 @@ config DRM_PANEL_BRIDGE > menu "Display Interface Bridges" > depends on DRM && DRM_BRIDGE > > +config DRM_ANALOGIX_ANX7688 > + tristate "Analogix ANX7688 bridge" > + select DRM_KMS_HELPER > + select REGMAP_I2C > + ---help--- > + ANX7688 is a transmitter to support DisplayPort over USB-C for > + smartphone and tablets. > + This driver only supports the HDMI to DP component of the chip. > + > config DRM_ANALOGIX_ANX78XX > tristate "Analogix ANX78XX bridge" > select DRM_KMS_HELPER > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile > index 4934fcf5a6f8..7a1e0ec032e6 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -1,4 +1,5 @@ > # SPDX-License-Identifier: GPL-2.0 > +obj-$(CONFIG_DRM_ANALOGIX_ANX7688) += analogix-anx7688.o > obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o > obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o > obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o > diff --git a/drivers/gpu/drm/bridge/analogix-anx7688.c > b/drivers/gpu/drm/bridge/analogix-anx7688.c > new file mode 100644 > index ..baaed48d6201 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/analogix-anx7688.c > @@ -0,0 +1,202 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * ANX7688 HDMI->DP bridge driver > + * > + * Copyright 2016 Google LLC > + */ > + > +#include > +#include > +#include > +#include > + > +/* Register addresses */ > +#define VENDOR_ID_REG 0x00 > +#define DEVICE_ID_REG 0x02 > + > +#define FW_VERSION_REG 0x80 > + > +#define DP_BANDWIDTH_REG 0x85 > +#define DP_LANE_COUNT_REG 0x86 Are these registers defined by the ANX7688 hardware, or by the firmware running on the chip (and, I assume, developed by Google) ? > + > +#define VENDOR_ID 0x1f29 > +#define DEVICE_ID 0x7688 > + > +/* First supported firmware version (0.85) */ > +#define MINIMUM_FW_VERSION 0x0085 > + > +struct anx7688 { > + struct drm_bridge bridge; > + struct i2c_client *client; > + struct regmap *regmap; > + > + bool filter; > +}; > + > +static inline struct anx7688 *bridge_to_anx7688(struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct anx7688, bridge); > +} > + > +static bool anx7688_bridge_mode_fixup(struct drm_bridge *bridge, > + const struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode) > +{ > + struct anx7688 *anx7688 = bridge_to_anx7688(bridge); > + u8 regs[2]; > + u8 dpbw, lanecount; > + int totalbw, requiredbw; > + int ret; > + > + if (!anx7688->filter) > + return true; > + > + /* Read both regs 0x85 (bandwidth) and 0x86 (lane count). */ > + ret = regmap_bulk_read(anx7688->regmap, DP_BANDWIDTH_REG, regs, 2); > + if (ret < 0) { > + dev_err(&anx7688->client->dev, > + "Failed to read bandwidth/lane count\n"); > + return false; > + } > + dpbw = regs[0]; > + lanecount = regs[1]; > + > + /* Maximum 0x19 bandwidth (6.75 Gbps Turbo mode), 2 lanes */ > + if (dpbw > 0x19 || lanecount > 2) { > + dev_err(&anx7688->client->dev, > + "Invalid bandwidth/lane count (%02x/%d)\n", > + dpbw, lanecount); > + return false; > + } > + > + /* Compute available bandwidth (kHz) */ > + totalbw = dpbw * lanecount * 27 * 8 / 10; > + > + /* Required bandwidth (8 bpc, kHz) */ > + requiredbw = mode->clock * 8 * 3; > + > + dev_dbg(&anx7688->client->dev, > + "DP bandwidth: %d kHz (%02x/%d); mode requires %d Khz\n", > + totalbw, dpbw, lanecount, requiredbw); > + > + if (totalbw == 0) { > + dev_warn(&anx7688->client->dev, > +
Re: [PATCH RESEND 4/4] drm: bridge: Generic GPIO mux driver
Hi Hsin-Yi and Nicolas, Thank you for the patch. On Wed, Dec 11, 2019 at 02:19:11PM +0800, Hsin-Yi Wang wrote: > From: Nicolas Boichat > > This driver supports single input, 2 output display mux (e.g. > HDMI mux), that provide its status via a GPIO. > > Signed-off-by: Nicolas Boichat > Signed-off-by: Hsin-Yi Wang > --- > drivers/gpu/drm/bridge/Kconfig| 10 + > drivers/gpu/drm/bridge/Makefile | 1 + > drivers/gpu/drm/bridge/generic-gpio-mux.c | 306 ++ > 3 files changed, 317 insertions(+) > create mode 100644 drivers/gpu/drm/bridge/generic-gpio-mux.c > > diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig > index 1f3fc6bec842..4734f6993858 100644 > --- a/drivers/gpu/drm/bridge/Kconfig > +++ b/drivers/gpu/drm/bridge/Kconfig > @@ -54,6 +54,16 @@ config DRM_DUMB_VGA_DAC > Support for non-programmable RGB to VGA DAC bridges, such as ADI > ADV7123, TI THS8134 and THS8135 or passive resistor ladder DACs. > > +config DRM_GENERIC_GPIO_MUX > + tristate "Generic GPIO-controlled mux" > + depends on OF > + select DRM_KMS_HELPER > + ---help--- > + This bridge driver models a GPIO-controlled display mux with one > + input, 2 outputs (e.g. an HDMI mux). The hardware decides which output > + is active, reports it as a GPIO, and the driver redirects calls to the > + appropriate downstream bridge (if any). My understanding of the issue was that the mux was controllable by a GPIO, not that the GPIO would report its status. This changes a few things. How is the mux controlled then ? > config DRM_LVDS_ENCODER > tristate "Transparent parallel to LVDS encoder support" > depends on OF > diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile > index 7a1e0ec032e6..1c0c92667ac4 100644 > --- a/drivers/gpu/drm/bridge/Makefile > +++ b/drivers/gpu/drm/bridge/Makefile > @@ -3,6 +3,7 @@ obj-$(CONFIG_DRM_ANALOGIX_ANX7688) += analogix-anx7688.o > obj-$(CONFIG_DRM_ANALOGIX_ANX78XX) += analogix-anx78xx.o > obj-$(CONFIG_DRM_CDNS_DSI) += cdns-dsi.o > obj-$(CONFIG_DRM_DUMB_VGA_DAC) += dumb-vga-dac.o > +obj-$(CONFIG_DRM_GENERIC_GPIO_MUX) += generic-gpio-mux.o > obj-$(CONFIG_DRM_LVDS_ENCODER) += lvds-encoder.o > obj-$(CONFIG_DRM_MEGACHIPS_STDP_GE_B850V3_FW) += > megachips-stdp-ge-b850v3-fw.o > obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o > diff --git a/drivers/gpu/drm/bridge/generic-gpio-mux.c > b/drivers/gpu/drm/bridge/generic-gpio-mux.c > new file mode 100644 > index ..ba08321dcc17 > --- /dev/null > +++ b/drivers/gpu/drm/bridge/generic-gpio-mux.c > @@ -0,0 +1,306 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Generic gpio mux bridge driver > + * > + * Copyright 2016 Google LLC > + */ > + > + One blank line is enough. > +#include > +#include > +#include > +#include > +#include > +#include > +#include Could you please sort these headers alphabetically ? > +#include > +#include > +#include > + > +struct gpio_display_mux { > + struct device *dev; > + > + struct gpio_desc *gpiod_detect; > + int detect_irq; > + > + struct drm_bridge bridge; > + > + struct drm_bridge *next[2]; > +}; > + > +static inline struct gpio_display_mux *bridge_to_gpio_display_mux( > + struct drm_bridge *bridge) > +{ > + return container_of(bridge, struct gpio_display_mux, bridge); > +} > + > +static irqreturn_t gpio_display_mux_det_threaded_handler(int unused, void > *data) > +{ > + struct gpio_display_mux *gpio_display_mux = data; gpio_display_mux is a long variable name. You can shorten it to mux here and below. > + int active = gpiod_get_value(gpio_display_mux->gpiod_detect); > + > + dev_dbg(gpio_display_mux->dev, "Interrupt %d!\n", active); > + > + if (gpio_display_mux->bridge.dev) > + drm_kms_helper_hotplug_event(gpio_display_mux->bridge.dev); > + > + return IRQ_HANDLED; > +} > + > +static int gpio_display_mux_attach(struct drm_bridge *bridge) > +{ > + struct gpio_display_mux *gpio_display_mux = > + bridge_to_gpio_display_mux(bridge); > + struct drm_bridge *next; > + int i; i never takes negative values, you can make it an unsigned int. > + > + for (i = 0; i < ARRAY_SIZE(gpio_display_mux->next); i++) { > + next = gpio_display_mux->next[i]; > + if (next) > + next->encoder = bridge->encoder; > + } > + > + return 0; > +} > + > +static bool gpio_display_mux_mode_fixup(struct drm_bridge *bridge, > + const struct drm_display_mode *mode, > + struct drm_display_mode *adjusted_mode) > +{ > + struct gpio_display_mux *gpio_display_mux = > + bridge_to_gpio_display_mux(bridge); > + int active; > + struct drm_bridge *next; > + > + active = gpiod_get_value(gpio_display_mux->gpiod_detect); What if the value of the GPIO
Re: [PATCH v4 6/7] dt-bindings: display: Add idk-2121wr binding
Hi Fabrizio, Thank you for the patch. On Fri, Dec 06, 2019 at 04:32:53PM +, Fabrizio Castro wrote: > Add binding for the idk-2121wr LVDS panel from Advantech. > > Some panel-specific documentation can be found here: > https://buy.advantech.eu/Displays/Embedded-LCD-Kits-High-Brightness/model-IDK-2121WR-K2FHA2E.htm > > Signed-off-by: Fabrizio Castro Reviewed-by: Laurent Pinchart > --- > v3->v4: > * Absorbed patch "dt-bindings: display: Add bindings for LVDS > bus-timings" > * Big restructuring after Rob's and Laurent's comments > > v2->v3: > * new patch > --- > .../display/panel/advantech,idk-2121wr.yaml| 128 > + > 1 file changed, 128 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml > > diff --git > a/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml > b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml > new file mode 100644 > index 000..24cd38b > --- /dev/null > +++ > b/Documentation/devicetree/bindings/display/panel/advantech,idk-2121wr.yaml > @@ -0,0 +1,128 @@ > +# SPDX-License-Identifier: GPL-2.0 > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/panel/advantech,idk-2121wr.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Advantech IDK-2121WR 21.5" Full-HD dual-LVDS panel > + > +maintainers: > + - Fabrizio Castro > + - Thierry Reding > + > +description: | > + The IDK-2121WR from Advantech is a Full-HD dual-LVDS panel. > + A dual-LVDS interface is a dual-link connection with even pixels traveling > + on one link, and with odd pixels traveling on the other link. > + > + The panel expects odd pixels on the first port, and even pixels on the > + second port, therefore the ports must be marked accordingly (with either > + dual-lvds-odd-pixels or dual-lvds-even-pixels). > + > +properties: > + compatible: > +items: > + - const: advantech,idk-2121wr > + - {} # panel-lvds, but not listed here to avoid false select > + > + width-mm: > +const: 476 > + > + height-mm: > +const: 268 > + > + data-mapping: > +const: vesa-24 > + > + ports: > +type: object > +properties: > + "#address-cells": > +const: 1 > + > + "#size-cells": > +const: 0 > + > + port@0: > +type: object > +description: The sink for odd pixels. > +properties: > + reg: > +const: 0 > + > + dual-lvds-odd-pixels: true > + > +required: > + - reg > + - dual-lvds-odd-pixels > + > + port@1: > +type: object > +description: The sink for even pixels. > +properties: > + reg: > +const: 1 > + > + dual-lvds-even-pixels: true > + > +required: > + - reg > + - dual-lvds-even-pixels > + > + panel-timing: true > + > +additionalProperties: false > + > +required: > + - compatible > + - width-mm > + - height-mm > + - data-mapping > + - panel-timing > + - ports > + > +examples: > + - |+ > +panel-lvds { > + compatible = "advantech,idk-2121wr", "panel-lvds"; > + > + width-mm = <476>; > + height-mm = <268>; > + > + data-mapping = "vesa-24"; > + > + panel-timing { > +clock-frequency = <14850>; > +hactive = <1920>; > +vactive = <1080>; > +hsync-len = <44>; > +hfront-porch = <88>; > +hback-porch = <148>; > +vfront-porch = <4>; > +vback-porch = <36>; > +vsync-len = <5>; > + }; > + > + ports { > +#address-cells = <1>; > +#size-cells = <0>; > + > +port@0 { > + reg = <0>; > + dual-lvds-odd-pixels; > + panel_in0: endpoint { > +remote-endpoint = <&lvds0_out>; > + }; > +}; > + > +port@1 { > + reg = <1>; > + dual-lvds-even-pixels; > + panel_in1: endpoint { > +remote-endpoint = <&lvds1_out>; > + }; > +}; > + }; > +}; > + > +... -- Regards, Laurent Pinchart ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC v2 04/12] drm/i915/svm: Page table update support for SVM
For Shared Virtual Memory (SVM) system (SYS) allocator, there is no backing buffer object (BO). Add support to bind a VA to PA mapping in the device page table. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/i915_gem_gtt.c | 60 - drivers/gpu/drm/i915/i915_gem_gtt.h | 10 + 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 7d4f5fa84b02..6657ff41dc3f 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -195,6 +195,50 @@ static void ppgtt_unbind_vma(struct i915_vma *vma) vma->vm->clear_range(vma->vm, vma->node.start, vma->size); } +int svm_bind_addr_prepare(struct i915_address_space *vm, u64 start, u64 size) +{ + return vm->allocate_va_range(vm, start, size); +} + +int svm_bind_addr_commit(struct i915_address_space *vm, u64 start, u64 size, +u64 flags, struct sg_table *st, u32 sg_page_sizes) +{ + struct i915_vma vma = {0}; + u32 pte_flags = 0; + + /* use a vma wrapper */ + vma.page_sizes.sg = sg_page_sizes; + vma.node.start = start; + vma.node.size = size; + vma.pages = st; + vma.vm = vm; + + /* Applicable to VLV, and gen8+ */ + if (flags & I915_GTT_SVM_READONLY) + pte_flags |= PTE_READ_ONLY; + + vm->insert_entries(vm, &vma, 0, pte_flags); + return 0; +} + +int svm_bind_addr(struct i915_address_space *vm, u64 start, u64 size, + u64 flags, struct sg_table *st, u32 sg_page_sizes) +{ + int ret; + + ret = svm_bind_addr_prepare(vm, start, size); + if (ret) + return ret; + + return svm_bind_addr_commit(vm, start, size, flags, st, sg_page_sizes); +} + +void svm_unbind_addr(struct i915_address_space *vm, +u64 start, u64 size) +{ + vm->clear_range(vm, start, size); +} + static int ppgtt_set_pages(struct i915_vma *vma) { GEM_BUG_ON(vma->pages); @@ -985,11 +1029,21 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, DBG("%s(%p):{ lvl:%d, start:%llx, end:%llx, idx:%d, len:%d, used:%d }\n", __func__, vm, lvl + 1, start, end, idx, len, atomic_read(px_used(pd))); - GEM_BUG_ON(!len || len >= atomic_read(px_used(pd))); + /* +* FIXME: In SVM case, during mmu invalidation, we need to clear ppgtt, +* but we don't know if the entry exist or not. So, we can't assume +* that it is called only when the entry exist. revisit. +* Also need to add the ebility to properly handle partial invalidations +* by downgrading the large mappings. +*/ + GEM_BUG_ON(!len); do { struct i915_page_table *pt = pd->entry[idx]; + if (!pt) + continue; + if (atomic_fetch_inc(&pt->used) >> gen8_pd_shift(1) && gen8_pd_contains(start, end, lvl)) { DBG("%s(%p):{ lvl:%d, idx:%d, start:%llx, end:%llx } removing pd\n", @@ -1012,7 +1066,9 @@ static u64 __gen8_ppgtt_clear(struct i915_address_space * const vm, __func__, vm, lvl, start, end, gen8_pd_index(start, 0), count, atomic_read(&pt->used)); - GEM_BUG_ON(!count || count >= atomic_read(&pt->used)); + GEM_BUG_ON(!count); + if (count > atomic_read(&pt->used)) + count = atomic_read(&pt->used); vaddr = kmap_atomic_px(pt); memset64(vaddr + gen8_pd_index(start, 0), diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 7c1b54c9677d..8a8a314e1295 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -679,4 +680,13 @@ int i915_gem_gtt_insert(struct i915_address_space *vm, #define PIN_OFFSET_MASK(-I915_GTT_PAGE_SIZE) +/* SVM UAPI */ +#define I915_GTT_SVM_READONLY BIT(0) + +int svm_bind_addr_prepare(struct i915_address_space *vm, u64 start, u64 size); +int svm_bind_addr_commit(struct i915_address_space *vm, u64 start, u64 size, +u64 flags, struct sg_table *st, u32 sg_page_sizes); +int svm_bind_addr(struct i915_address_space *vm, u64 start, u64 size, + u64 flags, struct sg_table *st, u32 sg_page_sizes); +void svm_unbind_addr(struct i915_address_space *vm, u64 start, u64 size); #endif -- 2.21.0.rc0.32.g243a4c7e27 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinf
[RFC v2 10/12] drm/i915/svm: Use blitter copy for migration
Use blitter engine to copy pages during migration. As blitter context virtual address space is shared with other flows, ensure virtual address are allocated properly from that address space. Also ensure completion of blitter copy by waiting on the fence of the issued request. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/i915_svm_devmem.c | 249 - 1 file changed, 245 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_svm_devmem.c b/drivers/gpu/drm/i915/i915_svm_devmem.c index 2b0c7f4c51b8..589cf42bc2da 100644 --- a/drivers/gpu/drm/i915/i915_svm_devmem.c +++ b/drivers/gpu/drm/i915/i915_svm_devmem.c @@ -15,7 +15,15 @@ struct i915_devmem_migrate { enum intel_region_id src_id; enum intel_region_id dst_id; + dma_addr_t *host_dma; + bool blitter_copy; u64 npages; + + /* required for blitter copy */ + struct drm_mm_node src_node; + struct drm_mm_node dst_node; + struct intel_context *ce; + struct dma_fence *fence; }; struct i915_devmem { @@ -148,6 +156,139 @@ i915_devmem_page_free_locked(struct drm_i915_private *dev_priv, put_page(page); } +static int i915_devmem_bind_addr(struct i915_devmem_migrate *migrate, +bool is_src) +{ + struct i915_gem_context *ctx = migrate->ce->gem_context; + struct drm_i915_private *i915 = migrate->i915; + struct i915_address_space *vm = ctx->vm; + struct intel_memory_region *mem; + u64 npages = migrate->npages; + enum intel_region_id mem_id; + struct drm_mm_node *node; + struct scatterlist *sg; + u32 sg_page_sizes = 0; + struct sg_table st; + u64 flags = 0; + int i, ret; + + if (unlikely(sg_alloc_table(&st, npages, GFP_KERNEL))) + return -ENOMEM; + + if (is_src) { + node = &migrate->src_node; + mem_id = migrate->src_id; + flags |= I915_GTT_SVM_READONLY; + } else { + node = &migrate->dst_node; + mem_id = migrate->dst_id; + } + + mutex_lock(&vm->mutex); + ret = i915_gem_gtt_insert(vm, node, npages * PAGE_SIZE, + I915_GTT_PAGE_SIZE_2M, 0, + 0, vm->total, PIN_USER); + mutex_unlock(&vm->mutex); + if (unlikely(ret)) + return ret; + + sg = NULL; + st.nents = 0; + + /* +* XXX: If the source page is missing, source it from a temporary +* zero filled page. If needed, destination page missing scenarios +* can be similarly handled by draining data into a temporary page. +*/ + for (i = 0; i < npages; i++) { + u64 addr; + + if (mem_id == INTEL_REGION_SMEM) { + addr = migrate->host_dma[i]; + } else { + struct page *page; + unsigned long mpfn; + + mpfn = is_src ? migrate->args->src[i] : + migrate->args->dst[i]; + page = migrate_pfn_to_page(mpfn); + mem = i915->mm.regions[mem_id]; + addr = page_to_pfn(page) - mem->devmem->pfn_first; + addr <<= PAGE_SHIFT; + addr += mem->region.start; + } + + if (sg && (addr == (sg_dma_address(sg) + sg->length))) { + sg->length += PAGE_SIZE; + sg_dma_len(sg) += PAGE_SIZE; + continue; + } + + if (sg) + sg_page_sizes |= sg->length; + + sg = sg ? __sg_next(sg) : st.sgl; + sg_dma_address(sg) = addr; + sg_dma_len(sg) = PAGE_SIZE; + sg->length = PAGE_SIZE; + st.nents++; + } + + sg_page_sizes |= sg->length; + sg_mark_end(sg); + i915_sg_trim(&st); + + ret = svm_bind_addr(vm, node->start, npages * PAGE_SIZE, + flags, &st, sg_page_sizes); + sg_free_table(&st); + + return ret; +} + +static void i915_devmem_unbind_addr(struct i915_devmem_migrate *migrate, + bool is_src) +{ + struct i915_gem_context *ctx = migrate->ce->gem_context; + struct i915_address_space *vm = ctx->vm; + struct drm_mm_node *node; + + node = is_src ? &migrate->src_node : &migrate->dst_node; + svm_unbind_addr(vm, node->start, migrate->npages * PAGE_SIZE); + mutex_lock(&vm->mutex); + drm_mm_remove_node(node); + mutex_unlock(&vm->mutex); +} + +static int i915_migrate_blitter_copy(struct i915_devmem_migrate *migrate) +{ + struct drm_i915_private *i915 = migrate->i915; + int ret; + +
[RFC v2 12/12] drm/i915/svm: Add page table dump support
Add support to dump page table for debug purpose. Here is an example dump. Format is, [] : Page Table dump start 0x0 len 0x [0x0fe] 0x7f000: 0x6b0003 [0x1e6] 0x7f798: 0x6c0003 [0x16d] 0x7f79ada00: 0x5f0003 [0x000] 0x7f79ada00: 0x610803 [0x16e] 0x7f79adc00: 0x6d0003 [0x000] 0x7f79adc00: 0x630803 [0x100] 0x8: 0x6f0003 [0x000] 0x8: 0x73 [0x000] 0x8: 0x710003 [0x000] 0x8: 0x5d0803 Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/Kconfig.debug| 14 +++ .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 1 + drivers/gpu/drm/i915/i915_gem_gtt.c | 92 +++ drivers/gpu/drm/i915/i915_gem_gtt.h | 14 +++ 4 files changed, 121 insertions(+) diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug index 206882e154bc..257510a38b15 100644 --- a/drivers/gpu/drm/i915/Kconfig.debug +++ b/drivers/gpu/drm/i915/Kconfig.debug @@ -221,3 +221,17 @@ config DRM_I915_DEBUG_RUNTIME_PM driver loading, suspend and resume operations. If in doubt, say "N" + +config DRM_I915_DUMP_PPGTT +bool "Enable PPGTT Page Table dump support" +depends on DRM_I915 +default n +help + Choose this option to enable PPGTT page table dump support. + The page table snapshot helps developers to debug page table + related issues. This will affect performance and dumps a lot of + information, so only recommended for developer debug. + + Recommended for driver developers only. + + If in doubt, say "N". diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index a7ac24de2017..2c09d4bdee6f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2678,6 +2678,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, intel_engine_pool_mark_active(eb.batch->private, eb.request); trace_i915_request_queue(eb.request, eb.batch_flags); + ppgtt_dump(eb.context->vm, 0, eb.context->vm->total); err = eb_submit(&eb); err_request: add_to_client(eb.request, file); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 192674f03e4e..a473f43c5320 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1227,6 +1227,97 @@ static int gen8_ppgtt_alloc(struct i915_address_space *vm, return err; } +#ifdef CONFIG_DRM_I915_DUMP_PPGTT +static void __gen8_ppgtt_dump(struct i915_address_space * const vm, + struct i915_page_directory * const pd, + u64 start, u64 end, int lvl) +{ + char *prefix[4] = { "\t\t\t\t", "\t\t\t", "\t\t", "\t"}; + char *format = "%s [0x%03x] 0x%llx: 0x%llx\n"; + unsigned int idx, len; + gen8_pte_t *vaddr; + unsigned int pdpe; + bool is_large; + + GEM_BUG_ON(end > vm->total >> GEN8_PTE_SHIFT); + + len = gen8_pd_range(start, end, lvl--, &idx); + GEM_BUG_ON(!len || (idx + len - 1) >> gen8_pd_shift(1)); + + spin_lock(&pd->lock); + GEM_BUG_ON(!atomic_read(px_used(pd))); /* Must be pinned! */ + do { + struct i915_page_table *pt = pd->entry[idx]; + + if (!pt) { + start += (1 << gen8_pd_shift(lvl + 1)); + continue; + } + + vaddr = kmap_atomic_px(&pd->pt); + pdpe = gen8_pd_index(start, lvl + 1); + DRM_DEBUG_DRIVER(format, prefix[lvl + 1], pdpe, +start, vaddr[pdpe]); + is_large = (vaddr[pdpe] & GEN8_PDE_PS_2M); + kunmap_atomic(vaddr); + if (is_large) { + start += (1 << gen8_pd_shift(lvl + 1)); + continue; + } + + if (lvl) { + atomic_inc(&pt->used); + spin_unlock(&pd->lock); + + __gen8_ppgtt_dump(vm, as_pd(pt), + start, end, lvl); + + start += (1 << gen8_pd_shift(lvl + 1)); + spin_lock(&pd->lock); + atomic_dec(&pt->used); + GEM_BUG_ON(!atomic_read(&pt->used)); + } else { + unsigned int count = gen8_pt_count(start, end); + + pdpe = gen8_pd_index(start, lvl); + vaddr = kmap_atomic_px(pt); + while (count) { +
[RFC v2 09/12] drm/i915/svm: Add functions to blitter copy SVM buffers
Add support function to blitter copy SVM VAs without requiring any gem objects. Also add function to wait for completion of the copy. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/gem/i915_gem_object.h | 3 + drivers/gpu/drm/i915/gem/i915_gem_wait.c | 2 +- drivers/gpu/drm/i915/i915_svm.h| 6 + drivers/gpu/drm/i915/i915_svm_copy.c | 172 + 5 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_svm_copy.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index b574ec31ea2e..97d40172bf27 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -156,7 +156,8 @@ i915-y += \ # SVM code i915-$(CONFIG_DRM_I915_SVM) += gem/i915_gem_svm.o \ i915_svm.o \ - i915_svm_devmem.o + i915_svm_devmem.o \ + i915_svm_copy.o # general-purpose microcontroller (GuC) support obj-y += gt/uc/ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 6d8ca3f0ccf7..1defc227c729 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -478,6 +478,9 @@ static inline void __start_cpu_write(struct drm_i915_gem_object *obj) int i915_gem_object_wait(struct drm_i915_gem_object *obj, unsigned int flags, long timeout); +long i915_gem_object_wait_fence(struct dma_fence *fence, + unsigned int flags, + long timeout); int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj, unsigned int flags, const struct i915_sched_attr *attr); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index 8af55cd3e690..b7905aa8f821 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -12,7 +12,7 @@ #include "i915_gem_ioctls.h" #include "i915_gem_object.h" -static long +long i915_gem_object_wait_fence(struct dma_fence *fence, unsigned int flags, long timeout) diff --git a/drivers/gpu/drm/i915/i915_svm.h b/drivers/gpu/drm/i915/i915_svm.h index ae39c2ef2f18..f8bedb4569b5 100644 --- a/drivers/gpu/drm/i915/i915_svm.h +++ b/drivers/gpu/drm/i915/i915_svm.h @@ -33,6 +33,12 @@ static inline bool i915_vm_is_svm_enabled(struct i915_address_space *vm) return vm->svm; } +int i915_svm_copy_blt(struct intel_context *ce, + u64 src_start, u64 dst_start, u64 size, + struct dma_fence **fence); +int i915_svm_copy_blt_wait(struct drm_i915_private *i915, + struct dma_fence *fence); + int i915_dmem_convert_pfn(struct drm_i915_private *dev_priv, struct hmm_range *range); int i915_gem_vm_prefetch_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/i915/i915_svm_copy.c b/drivers/gpu/drm/i915/i915_svm_copy.c new file mode 100644 index ..42f7d563f6b4 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_svm_copy.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2019 Intel Corporation + */ + +#include "i915_drv.h" +#include "gem/i915_gem_object_blt.h" +#include "gt/intel_engine_pm.h" +#include "gt/intel_engine_pool.h" +#include "gt/intel_gpu_commands.h" +#include "gt/intel_gt.h" + +static struct i915_vma * +intel_emit_svm_copy_blt(struct intel_context *ce, + u64 src_start, u64 dst_start, u64 buff_size) +{ + struct drm_i915_private *i915 = ce->vm->i915; + const u32 block_size = SZ_8M; /* ~1ms at 8GiB/s preemption delay */ + struct intel_engine_pool_node *pool; + struct i915_vma *batch; + u64 count, rem; + u32 size, *cmd; + int err; + + GEM_BUG_ON(intel_engine_is_virtual(ce->engine)); + intel_engine_pm_get(ce->engine); + + if (INTEL_GEN(i915) < 8) + return ERR_PTR(-ENOTSUPP); + + count = div_u64(round_up(buff_size, block_size), block_size); + size = (1 + 11 * count) * sizeof(u32); + size = round_up(size, PAGE_SIZE); + pool = intel_engine_get_pool(ce->engine, size); + if (IS_ERR(pool)) { + err = PTR_ERR(pool); + goto out_pm; + } + + cmd = i915_gem_object_pin_map(pool->obj, I915_MAP_FORCE_WC); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto out_put; + } + + rem = buff_size; + do { + size = min_t(u64, rem, block_size); + GEM_BUG_ON(size >> PAGE_SHIFT > S16_MAX
[RFC v2 06/12] drm/i915/svm: Device memory support
Plugin device memory through HMM as DEVICE_PRIVATE. Add support functions to allocate pages and free pages from device memory. Implement ioctl to prefetch pages from host to device memory. For now, only support migrating pages from host memory to device memory. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/Kconfig | 9 + drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/gem/i915_gem_object.c | 13 - drivers/gpu/drm/i915/i915_buddy.h | 12 + drivers/gpu/drm/i915/i915_drv.c| 1 + drivers/gpu/drm/i915/i915_svm.c| 6 + drivers/gpu/drm/i915/i915_svm.h| 15 + drivers/gpu/drm/i915/i915_svm_devmem.c | 400 + drivers/gpu/drm/i915/intel_memory_region.h | 14 + drivers/gpu/drm/i915/intel_region_lmem.c | 10 + include/uapi/drm/i915_drm.h| 22 ++ 11 files changed, 491 insertions(+), 14 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_svm_devmem.c diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 689e57fe3973..66337f2ca2bf 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -141,9 +141,18 @@ config DRM_I915_SVM bool "Enable Shared Virtual Memory support in i915" depends on STAGING depends on DRM_I915 + depends on ARCH_ENABLE_MEMORY_HOTPLUG + depends on ARCH_ENABLE_MEMORY_HOTREMOVE + depends on MEMORY_HOTPLUG + depends on MEMORY_HOTREMOVE + depends on ARCH_HAS_PTE_DEVMAP + depends on SPARSEMEM_VMEMMAP + depends on ZONE_DEVICE + depends on DEVICE_PRIVATE depends on MMU select HMM_MIRROR select MMU_NOTIFIER + select MIGRATE_VMA_HELPER default n help Choose this option if you want Shared Virtual Memory (SVM) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 7d4cd9eefd12..b574ec31ea2e 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -155,7 +155,8 @@ i915-y += \ # SVM code i915-$(CONFIG_DRM_I915_SVM) += gem/i915_gem_svm.o \ - i915_svm.o + i915_svm.o \ + i915_svm_devmem.o # general-purpose microcontroller (GuC) support obj-y += gt/uc/ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 003d81c171d2..f868a301fc04 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -504,19 +504,6 @@ int __init i915_global_objects_init(void) return 0; } -static enum intel_region_id -__region_id(u32 region) -{ - enum intel_region_id id; - - for (id = 0; id < INTEL_REGION_UNKNOWN; ++id) { - if (intel_region_map[id] == region) - return id; - } - - return INTEL_REGION_UNKNOWN; -} - bool i915_gem_object_svm_mapped(struct drm_i915_gem_object *obj) { diff --git a/drivers/gpu/drm/i915/i915_buddy.h b/drivers/gpu/drm/i915/i915_buddy.h index ed41f3507cdc..afc493e6c130 100644 --- a/drivers/gpu/drm/i915/i915_buddy.h +++ b/drivers/gpu/drm/i915/i915_buddy.h @@ -9,6 +9,9 @@ #include #include +/* 512 bits (one per pages) supports 2MB blocks */ +#define I915_BUDDY_MAX_PAGES 512 + struct i915_buddy_block { #define I915_BUDDY_HEADER_OFFSET GENMASK_ULL(63, 12) #define I915_BUDDY_HEADER_STATE GENMASK_ULL(11, 10) @@ -32,6 +35,15 @@ struct i915_buddy_block { */ struct list_head link; struct list_head tmp_link; + + unsigned long pfn_first; + /* +* FIXME: There are other alternatives to bitmap. Like splitting the +* block into contiguous 4K sized blocks. But it is part of bigger +* issues involving partially invalidating large mapping, freeing the +* blocks etc., revisit. +*/ + unsigned long bitmap[BITS_TO_LONGS(I915_BUDDY_MAX_PAGES)]; }; #define I915_BUDDY_MAX_ORDER I915_BUDDY_HEADER_ORDER diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 866d3cbb1edf..f1b92fd3d234 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -2765,6 +2765,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_VM_CREATE, i915_gem_vm_create_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_VM_BIND, i915_gem_vm_bind_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_GEM_VM_PREFETCH, i915_gem_vm_prefetch_ioctl, DRM_RENDER_ALLOW) }; static struct drm_driver driver = { diff --git a/drivers/gpu/drm/i915/i915_svm.c b/drivers/gpu/drm/i915/i915_svm.c index 5941be5b5803..31a80ae0dd45 100644 --- a/drivers/gpu/drm/i915/i915_sv
[RFC v2 08/12] drm/i915/svm: Page copy support during migration
Copy the pages duing SVM migration using memcpy(). Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/i915_svm_devmem.c | 72 ++ 1 file changed, 72 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_svm_devmem.c b/drivers/gpu/drm/i915/i915_svm_devmem.c index 98ab27879041..2b0c7f4c51b8 100644 --- a/drivers/gpu/drm/i915/i915_svm_devmem.c +++ b/drivers/gpu/drm/i915/i915_svm_devmem.c @@ -148,6 +148,69 @@ i915_devmem_page_free_locked(struct drm_i915_private *dev_priv, put_page(page); } +static int i915_migrate_cpu_copy(struct i915_devmem_migrate *migrate) +{ + const unsigned long *src = migrate->args->src; + unsigned long *dst = migrate->args->dst; + struct drm_i915_private *i915 = migrate->i915; + struct intel_memory_region *mem; + void *src_vaddr, *dst_vaddr; + u64 src_addr, dst_addr; + struct page *page; + int i, ret = 0; + + /* XXX: Copy multiple pages at a time */ + for (i = 0; !ret && i < migrate->npages; i++) { + if (!dst[i]) + continue; + + page = migrate_pfn_to_page(dst[i]); + mem = i915->mm.regions[migrate->dst_id]; + dst_addr = page_to_pfn(page); + if (migrate->dst_id != INTEL_REGION_SMEM) + dst_addr -= mem->devmem->pfn_first; + dst_addr <<= PAGE_SHIFT; + + if (migrate->dst_id == INTEL_REGION_SMEM) + dst_vaddr = phys_to_virt(dst_addr); + else + dst_vaddr = io_mapping_map_atomic_wc(&mem->iomap, +dst_addr); + if (unlikely(!dst_vaddr)) + return -ENOMEM; + + page = migrate_pfn_to_page(src[i]); + mem = i915->mm.regions[migrate->src_id]; + src_addr = page_to_pfn(page); + if (migrate->src_id != INTEL_REGION_SMEM) + src_addr -= mem->devmem->pfn_first; + src_addr <<= PAGE_SHIFT; + + if (migrate->src_id == INTEL_REGION_SMEM) + src_vaddr = phys_to_virt(src_addr); + else + src_vaddr = io_mapping_map_atomic_wc(&mem->iomap, +src_addr); + + if (likely(src_vaddr)) + memcpy(dst_vaddr, src_vaddr, PAGE_SIZE); + else + ret = -ENOMEM; + + if (migrate->dst_id != INTEL_REGION_SMEM) + io_mapping_unmap_atomic(dst_vaddr); + + if (migrate->src_id != INTEL_REGION_SMEM && src_vaddr) + io_mapping_unmap_atomic(src_vaddr); + + DRM_DEBUG_DRIVER("src [%d] 0x%llx, dst [%d] 0x%llx\n", +migrate->src_id, src_addr, +migrate->dst_id, dst_addr); + } + + return ret; +} + static int i915_devmem_migrate_alloc_and_copy(struct i915_devmem_migrate *migrate) { @@ -207,6 +270,8 @@ i915_devmem_migrate_alloc_and_copy(struct i915_devmem_migrate *migrate) /* Copy the pages */ migrate->npages = npages; + /* XXX: Flush the caches? */ + ret = i915_migrate_cpu_copy(migrate); migrate_out: if (unlikely(ret)) { for (i = 0; i < npages; i++) { @@ -292,6 +357,7 @@ i915_devmem_fault_alloc_and_copy(struct i915_devmem_migrate *migrate) struct device *dev = migrate->i915->drm.dev; struct migrate_vma *args = migrate->args; struct page *dpage, *spage; + int err; DRM_DEBUG_DRIVER("start 0x%lx\n", args->start); /* Allocate host page */ @@ -308,6 +374,12 @@ i915_devmem_fault_alloc_and_copy(struct i915_devmem_migrate *migrate) /* Copy the pages */ migrate->npages = 1; + err = i915_migrate_cpu_copy(migrate); + if (unlikely(err)) { + __free_page(dpage); + args->dst[0] = 0; + return VM_FAULT_SIGBUS; + } return 0; } -- 2.21.0.rc0.32.g243a4c7e27 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC v2 03/12] drm/i915/svm: Implicitly migrate BOs upon CPU access
From: Venkata Sandeep Dhanalakota As PCIe is non-coherent link, do not allow direct access to buffer objects across the PCIe link for SVM case. Upon CPU accesses (mmap, pread), migrate buffer object to host memory. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Cc: Niranjana Vishwanathapura Signed-off-by: Venkata Sandeep Dhanalakota --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 10 drivers/gpu/drm/i915/gem/i915_gem_object.c | 29 +- drivers/gpu/drm/i915/gem/i915_gem_object.h | 3 +++ drivers/gpu/drm/i915/intel_memory_region.c | 4 --- drivers/gpu/drm/i915/intel_memory_region.h | 4 +++ 5 files changed, 40 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index 879fff8adc48..fc1a11f0bec9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -14,6 +14,7 @@ #include "i915_drv.h" #include "i915_gem_gtt.h" #include "i915_gem_ioctls.h" +#include "i915_gem_lmem.h" #include "i915_gem_object.h" #include "i915_gem_mman.h" #include "i915_trace.h" @@ -295,6 +296,15 @@ static vm_fault_t vm_fault_gtt(struct vm_fault *vmf) if (i915_gem_object_is_readonly(obj) && write) return VM_FAULT_SIGBUS; + /* Implicitly migrate BO to SMEM if it is SVM mapped */ + if (i915_gem_object_svm_mapped(obj) && i915_gem_object_is_lmem(obj)) { + u32 regions[] = { REGION_MAP(INTEL_MEMORY_SYSTEM, 0) }; + + ret = i915_gem_object_migrate_region(obj, regions, 1); + if (ret) + goto err; + } + /* We don't use vmf->pgoff since that has the fake offset */ page_offset = (vmf->address - area->vm_start) >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 025c26266801..003d81c171d2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -517,12 +517,17 @@ __region_id(u32 region) return INTEL_REGION_UNKNOWN; } +bool +i915_gem_object_svm_mapped(struct drm_i915_gem_object *obj) +{ + return false; +} + static int i915_gem_object_region_select(struct drm_i915_private *dev_priv, struct drm_i915_gem_object_param *args, struct drm_file *file, struct drm_i915_gem_object *obj) { - struct intel_context *ce = dev_priv->engine[BCS0]->kernel_context; u32 __user *uregions = u64_to_user_ptr(args->data); u32 uregions_copy[INTEL_REGION_UNKNOWN]; int i, ret; @@ -542,16 +547,28 @@ static int i915_gem_object_region_select(struct drm_i915_private *dev_priv, ++uregions; } + ret = i915_gem_object_migrate_region(obj, uregions_copy, +args->size); + + return ret; +} + +int i915_gem_object_migrate_region(struct drm_i915_gem_object *obj, + u32 *regions, int size) +{ + struct drm_i915_private *dev_priv = to_i915(obj->base.dev); + struct intel_context *ce = dev_priv->engine[BCS0]->kernel_context; + int i, ret; + mutex_lock(&dev_priv->drm.struct_mutex); ret = i915_gem_object_prepare_move(obj); if (ret) { DRM_ERROR("Cannot set memory region, object in use\n"); - goto err; + goto err; } - for (i = 0; i < args->size; i++) { - u32 region = uregions_copy[i]; - enum intel_region_id id = __region_id(region); + for (i = 0; i < size; i++) { + enum intel_region_id id = __region_id(regions[i]); if (id == INTEL_REGION_UNKNOWN) { ret = -EINVAL; @@ -561,7 +578,7 @@ static int i915_gem_object_region_select(struct drm_i915_private *dev_priv, ret = i915_gem_object_migrate(obj, ce, id); if (!ret) { if (!i915_gem_object_has_pages(obj) && - MEMORY_TYPE_FROM_REGION(region) == + MEMORY_TYPE_FROM_REGION(regions[i]) == INTEL_MEMORY_LOCAL) { /* * TODO: this should be part of get_pages(), diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index 87e6b6f18d91..6d8ca3f0ccf7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -47,6 +47,9 @@ int i915_gem_object_prepare_move(struct drm_i915_gem_object *obj); int i915_gem_object_migrate(struct drm_i915_gem_object *obj, struct intel_context *ce, enum intel_region_id id); +bool i915_gem_object_
[RFC v2 11/12] drm/i915/svm: Add support to en/disable SVM
Add SVM as a capability and allow user to enable/disable SVM functionality on a per context basis. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura Signed-off-by: Venkata Sandeep Dhanalakota --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 95 ++- drivers/gpu/drm/i915/gem/i915_gem_context.h | 2 + .../gpu/drm/i915/gem/i915_gem_context_types.h | 1 + .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 6 ++ drivers/gpu/drm/i915/gem/i915_gem_object.c| 11 +++ drivers/gpu/drm/i915/i915_drv.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 10 ++ drivers/gpu/drm/i915/i915_getparam.c | 3 + include/uapi/drm/i915_drm.h | 17 9 files changed, 145 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index d91975efc940..7db09c8bacb5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -77,6 +77,7 @@ #include "i915_gem_context.h" #include "i915_globals.h" +#include "i915_svm.h" #include "i915_trace.h" #include "i915_user_extensions.h" #include "i915_gem_ioctls.h" @@ -961,6 +962,78 @@ int i915_gem_vm_destroy_ioctl(struct drm_device *dev, void *data, return 0; } +static int i915_gem_vm_setparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_file_private *file_priv = file->driver_priv; + struct drm_i915_gem_vm_param *args = data; + struct i915_address_space *vm; + int err = 0; + u32 id; + + id = args->vm_id; + if (!id) + return -ENOENT; + + err = mutex_lock_interruptible(&file_priv->vm_idr_lock); + if (err) + return err; + + vm = idr_find(&file_priv->vm_idr, id); + + mutex_unlock(&file_priv->vm_idr_lock); + if (!vm) + return -ENOENT; + + switch (lower_32_bits(args->param)) { + case I915_GEM_VM_PARAM_SVM: + /* FIXME: Ensure ppgtt is empty before switching */ + if (!i915_has_svm(file_priv->dev_priv)) + err = -ENOTSUPP; + else if (args->value) + err = i915_svm_bind_mm(vm); + else + i915_svm_unbind_mm(vm); + break; + default: + err = -EINVAL; + } + return err; +} + +static int i915_gem_vm_getparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_file_private *file_priv = file->driver_priv; + struct drm_i915_gem_vm_param *args = data; + struct i915_address_space *vm; + int err = 0; + u32 id; + + id = args->vm_id; + if (!id) + return -ENOENT; + + err = mutex_lock_interruptible(&file_priv->vm_idr_lock); + if (err) + return err; + + vm = idr_find(&file_priv->vm_idr, id); + + mutex_unlock(&file_priv->vm_idr_lock); + if (!vm) + return -ENOENT; + + switch (lower_32_bits(args->param)) { + case I915_GEM_VM_PARAM_SVM: + args->value = i915_vm_is_svm_enabled(vm); + break; + default: + err = -EINVAL; + } + return err; +} + struct context_barrier_task { struct i915_active base; void (*task)(void *data); @@ -2382,6 +2455,21 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, return ret; } +int i915_gem_getparam_ioctl(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_i915_gem_context_param *args = data; + u32 class = upper_32_bits(args->param); + + switch (class) { + case 0: + return i915_gem_context_getparam_ioctl(dev, data, file); + case 2: + return i915_gem_vm_getparam_ioctl(dev, data, file); + } + return -EINVAL; +} + int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { @@ -2404,14 +2492,15 @@ int i915_gem_setparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_gem_context_param *args = data; - u32 object_class = upper_32_bits(args->param); + u32 class = upper_32_bits(args->param); - switch (object_class) { + switch (class) { case 0: return i915_gem_context_setparam_ioctl(dev, data, file); case 1: return i915_gem_object_setparam_ioctl(dev, data, file); - + case 2: + return i915_gem_vm_setparam_ioctl(dev, data, file); } return -EINVAL; } diff --git a/drivers/gpu/drm/i915/gem/i9
[RFC v2 01/12] drm/i915/svm: Add SVM documentation
Add Shared Virtual Memory (SVM) support information. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- Documentation/gpu/i915.rst | 29 + 1 file changed, 29 insertions(+) diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index e539c42a3e78..0bc63489 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -415,6 +415,35 @@ Object Tiling IOCTLs .. kernel-doc:: drivers/gpu/drm/i915/gem/i915_gem_tiling.c :doc: buffer object tiling +Shared Virtual Memory (SVM) +--- + +Shared Virtual Memory (SVM) allows the programmer to use a single virtual +address space which will be shared between threads executing on CPUs and GPUs. +It abstracts away from the user the location of the backing memory, and hence +simplifies the user programming model. +SVM supports two types of virtual memory allocation methods. +Runtime allocator requires the driver to provide memory allocation and +management interface, like buffer object (BO) interface. +Whereas system allocator makes use of default OS memory allocation and +management support like malloc(). + +Linux kernel has a Heterogeneous Memory Management (HMM) framework to +Support SVM system allocator. HMM’s address space mirroring support allows +sharing of the address space by duplicating sections of CPU page tables in the +device page tables. This enables both CPU and GPU access a physical memory +location using the same virtual address. Linux kernel also provides the ability +to plugin device memory with the system (as a special ZONE_DEVICE type) and +allocates struct page for each device memory page. It also provides a mechanism +to migrate pages from host to device memory and vice versa. +More information on HMM can be found here. +https://www.kernel.org/doc/Documentation/vm/hmm.rst + +i915 supports both SVM system and runtime allocator. As PCIe is a non-coherent +bus, it plugs in device memory as DEVICE_PRIVATE and no memory access across +PCIe link is allowed. Any such access will trigger migration of the page/s +or BOs before the memory is accessed. + Microcontrollers -- 2.21.0.rc0.32.g243a4c7e27 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC v2 02/12] drm/i915/svm: Runtime (RT) allocator support
Shared Virtual Memory (SVM) runtime allocator support allows binding a shared virtual address to a buffer object (BO) in the device page table through an ioctl call. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/Kconfig | 11 drivers/gpu/drm/i915/Makefile | 3 + .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 58 ++ drivers/gpu/drm/i915/gem/i915_gem_svm.c | 60 +++ drivers/gpu/drm/i915/gem/i915_gem_svm.h | 22 +++ drivers/gpu/drm/i915/i915_drv.c | 21 +++ drivers/gpu/drm/i915/i915_drv.h | 22 +++ drivers/gpu/drm/i915/i915_gem_gtt.c | 1 + drivers/gpu/drm/i915/i915_gem_gtt.h | 13 include/uapi/drm/i915_drm.h | 27 + 10 files changed, 227 insertions(+), 11 deletions(-) create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_svm.c create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_svm.h diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index ba9595960bbe..c2e48710eec8 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -137,6 +137,16 @@ config DRM_I915_GVT_KVMGT Choose this option if you want to enable KVMGT support for Intel GVT-g. +config DRM_I915_SVM + bool "Enable Shared Virtual Memory support in i915" + depends on STAGING + depends on DRM_I915 + default n + help + Choose this option if you want Shared Virtual Memory (SVM) + support in i915. With SVM support, one can share the virtual + address space between a process and the GPU. + menu "drm/i915 Debugging" depends on DRM_I915 depends on EXPERT diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index e0fd10c0cfb8..75fe45633779 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -153,6 +153,9 @@ i915-y += \ intel_region_lmem.o \ intel_wopcm.o +# SVM code +i915-$(CONFIG_DRM_I915_SVM) += gem/i915_gem_svm.o + # general-purpose microcontroller (GuC) support obj-y += gt/uc/ i915-y += gt/uc/intel_uc.o \ diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 5003e616a1ad..af360238a392 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2836,10 +2836,14 @@ int i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { + struct drm_i915_gem_exec_object2 *exec2_list, *exec2_list_user; struct drm_i915_gem_execbuffer2 *args = data; - struct drm_i915_gem_exec_object2 *exec2_list; - struct drm_syncobj **fences = NULL; const size_t count = args->buffer_count; + struct drm_syncobj **fences = NULL; + unsigned int i = 0, svm_count = 0; + struct i915_address_space *vm; + struct i915_gem_context *ctx; + struct i915_svm_obj *svm_obj; int err; if (!check_buffer_count(count)) { @@ -2851,15 +2855,46 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data, if (err) return err; + ctx = i915_gem_context_lookup(file->driver_priv, args->rsvd1); + if (!ctx || !rcu_access_pointer(ctx->vm)) + return -ENOENT; + + rcu_read_lock(); + vm = i915_vm_get(ctx->vm); + rcu_read_unlock(); + +alloc_again: + svm_count = vm->svm_count; /* Allocate an extra slot for use by the command parser */ - exec2_list = kvmalloc_array(count + 1, eb_element_size(), + exec2_list = kvmalloc_array(count + svm_count + 1, eb_element_size(), __GFP_NOWARN | GFP_KERNEL); if (exec2_list == NULL) { DRM_DEBUG("Failed to allocate exec list for %zd buffers\n", - count); + count + svm_count); return -ENOMEM; } - if (copy_from_user(exec2_list, + mutex_lock(&vm->mutex); + if (svm_count != vm->svm_count) { + mutex_unlock(&vm->mutex); + kvfree(exec2_list); + goto alloc_again; + } + + list_for_each_entry(svm_obj, &vm->svm_list, link) { + memset(&exec2_list[i], 0, sizeof(*exec2_list)); + exec2_list[i].handle = svm_obj->handle; + exec2_list[i].offset = svm_obj->offset; + exec2_list[i].flags = EXEC_OBJECT_PINNED | + EXEC_OBJECT_SUPPORTS_48B_ADDRESS; + i++; + } + exec2_list_user = &exec2_list[i]; + args->buffer_count += svm_count; + mutex_unlock(&vm->mutex); + i915_vm_put(vm); + i915_gem_context_put(ctx); + + if (copy_from_user(exec2_list_user,
[RFC v2 05/12] drm/i915/svm: Page table mirroring support
Use HMM page table mirroring support to build device page table. Implement the bind ioctl and bind the process address range in the specified context's ppgtt. Handle invalidation notifications by unbinding the address range. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/Kconfig| 3 + drivers/gpu/drm/i915/Makefile | 3 +- drivers/gpu/drm/i915/i915_drv.c | 5 + drivers/gpu/drm/i915/i915_gem_gtt.c | 5 + drivers/gpu/drm/i915/i915_gem_gtt.h | 4 + drivers/gpu/drm/i915/i915_svm.c | 324 drivers/gpu/drm/i915/i915_svm.h | 50 + include/uapi/drm/i915_drm.h | 9 +- 8 files changed, 401 insertions(+), 2 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_svm.c create mode 100644 drivers/gpu/drm/i915/i915_svm.h diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index c2e48710eec8..689e57fe3973 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -141,6 +141,9 @@ config DRM_I915_SVM bool "Enable Shared Virtual Memory support in i915" depends on STAGING depends on DRM_I915 + depends on MMU + select HMM_MIRROR + select MMU_NOTIFIER default n help Choose this option if you want Shared Virtual Memory (SVM) diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 75fe45633779..7d4cd9eefd12 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -154,7 +154,8 @@ i915-y += \ intel_wopcm.o # SVM code -i915-$(CONFIG_DRM_I915_SVM) += gem/i915_gem_svm.o +i915-$(CONFIG_DRM_I915_SVM) += gem/i915_gem_svm.o \ + i915_svm.o # general-purpose microcontroller (GuC) support obj-y += gt/uc/ diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index d452ea8e40b3..866d3cbb1edf 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -62,6 +62,7 @@ #include "gem/i915_gem_context.h" #include "gem/i915_gem_ioctls.h" #include "gem/i915_gem_mman.h" +#include "gem/i915_gem_svm.h" #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" #include "gt/intel_rc6.h" @@ -73,6 +74,7 @@ #include "i915_perf.h" #include "i915_query.h" #include "i915_suspend.h" +#include "i915_svm.h" #include "i915_switcheroo.h" #include "i915_sysfs.h" #include "i915_trace.h" @@ -2694,6 +2696,9 @@ static int i915_gem_vm_bind_ioctl(struct drm_device *dev, void *data, switch (args->type) { case I915_GEM_VM_BIND_SVM_OBJ: ret = i915_gem_vm_bind_svm_obj(vm, args, file); + break; + case I915_GEM_VM_BIND_SVM_BUFFER: + ret = i915_gem_vm_bind_svm_buffer(vm, args); } i915_vm_put(vm); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 6657ff41dc3f..192674f03e4e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -42,6 +42,7 @@ #include "i915_drv.h" #include "i915_scatterlist.h" +#include "i915_svm.h" #include "i915_trace.h" #include "i915_vgpu.h" @@ -562,6 +563,7 @@ static void i915_address_space_fini(struct i915_address_space *vm) drm_mm_takedown(&vm->mm); mutex_destroy(&vm->mutex); + mutex_destroy(&vm->svm_mutex); } void __i915_vm_close(struct i915_address_space *vm) @@ -591,6 +593,7 @@ static void __i915_vm_release(struct work_struct *work) struct i915_address_space *vm = container_of(work, struct i915_address_space, rcu.work); + i915_svm_unbind_mm(vm); vm->cleanup(vm); i915_address_space_fini(vm); @@ -620,6 +623,7 @@ static void i915_address_space_init(struct i915_address_space *vm, int subclass) * attempt holding the lock is immediately reported by lockdep. */ mutex_init(&vm->mutex); + mutex_init(&vm->svm_mutex); lockdep_set_subclass(&vm->mutex, subclass); i915_gem_shrinker_taints_mutex(vm->i915, &vm->mutex); @@ -631,6 +635,7 @@ static void i915_address_space_init(struct i915_address_space *vm, int subclass) INIT_LIST_HEAD(&vm->bound_list); INIT_LIST_HEAD(&vm->svm_list); + RCU_INIT_POINTER(vm->svm, NULL); } static int __setup_page_dma(struct i915_address_space *vm, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 8a8a314e1295..e06e6447e0d7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -293,6 +293,8 @@ struct i915_svm_obj { u64 offset; }; +struct i915_svm; + struct i915_address_space { struct kref ref; struct rcu_work rcu; @@ -342,6 +344,8 @@ struct i915_address_space { */ struct list_head svm_list; unsigned int svm_count; + struct i915_svm *svm
[RFC v2 00/12] drm/i915/svm: Add SVM support
Shared Virtual Memory (SVM) allows the programmer to use a single virtual address space which will be shared between threads executing on CPUs and GPUs. It abstracts away from the user the location of the backing memory, and hence simplifies the user programming model. SVM supports two types of virtual memory allocation methods. Runtime allocator requires the driver to provide memory allocation and management interface, like buffer object (BO) interface. Whereas system allocator makes use of default OS memory allocation and management support like malloc(). This patch series adds both SVM system and runtime allocator support to i915 driver. The patch series includes - SVM support for both system and runtime allocation. - Plugin in device memory with the Linux kernel. - User API advertising SVM capability and configuration by user on per vm basis. - User API to bind an address range or a BO with a device page table. - User API to prefetch an address range to device memory. - Implicit migration by moving pages or BOs back from device to host memory upon CPU access. - CPU copy and blitter copy support for migrating the pages/BOs. - Large page mapping support - Page table dump support. References: https://www.kernel.org/doc/Documentation/vm/hmm.rst The HMM use cases in the Linux kernel. Test RFC series "[RFC i-g-t 0/7] tests/i915/svm: Shared Virtual Memory (SVM) test" v2: - Use updated HMM API - HMM usage changes as per review feedback - UAPI name change as per review feedback - Reformat RFC series - Some minor fixes Niranjana Vishwanathapura (11): drm/i915/svm: Add SVM documentation drm/i915/svm: Runtime (RT) allocator support drm/i915/svm: Page table update support for SVM drm/i915/svm: Page table mirroring support drm/i915/svm: Device memory support drm/i915/svm: Implicitly migrate pages upon CPU fault drm/i915/svm: Page copy support during migration drm/i915/svm: Add functions to blitter copy SVM buffers drm/i915/svm: Use blitter copy for migration drm/i915/svm: Add support to en/disable SVM drm/i915/svm: Add page table dump support Venkata Sandeep Dhanalakota (1): drm/i915/svm: Implicitly migrate BOs upon CPU access Documentation/gpu/i915.rst| 29 + drivers/gpu/drm/i915/Kconfig | 23 + drivers/gpu/drm/i915/Kconfig.debug| 14 + drivers/gpu/drm/i915/Makefile | 6 + drivers/gpu/drm/i915/gem/i915_gem_context.c | 95 ++- drivers/gpu/drm/i915/gem/i915_gem_context.h | 2 + .../gpu/drm/i915/gem/i915_gem_context_types.h | 1 + .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 65 +- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 10 + drivers/gpu/drm/i915/gem/i915_gem_object.c| 43 +- drivers/gpu/drm/i915/gem/i915_gem_object.h| 6 + drivers/gpu/drm/i915/gem/i915_gem_svm.c | 60 ++ drivers/gpu/drm/i915/gem/i915_gem_svm.h | 22 + drivers/gpu/drm/i915/gem/i915_gem_wait.c | 2 +- drivers/gpu/drm/i915/i915_buddy.h | 12 + drivers/gpu/drm/i915/i915_drv.c | 31 +- drivers/gpu/drm/i915/i915_drv.h | 32 + drivers/gpu/drm/i915/i915_gem_gtt.c | 158 +++- drivers/gpu/drm/i915/i915_gem_gtt.h | 41 + drivers/gpu/drm/i915/i915_getparam.c | 3 + drivers/gpu/drm/i915/i915_svm.c | 330 drivers/gpu/drm/i915/i915_svm.h | 71 ++ drivers/gpu/drm/i915/i915_svm_copy.c | 172 drivers/gpu/drm/i915/i915_svm_devmem.c| 781 ++ drivers/gpu/drm/i915/intel_memory_region.c| 4 - drivers/gpu/drm/i915/intel_memory_region.h| 18 + drivers/gpu/drm/i915/intel_region_lmem.c | 10 + include/uapi/drm/i915_drm.h | 73 ++ 28 files changed, 2078 insertions(+), 36 deletions(-) create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_svm.c create mode 100644 drivers/gpu/drm/i915/gem/i915_gem_svm.h create mode 100644 drivers/gpu/drm/i915/i915_svm.c create mode 100644 drivers/gpu/drm/i915/i915_svm.h create mode 100644 drivers/gpu/drm/i915/i915_svm_copy.c create mode 100644 drivers/gpu/drm/i915/i915_svm_devmem.c -- 2.21.0.rc0.32.g243a4c7e27 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC v2 07/12] drm/i915/svm: Implicitly migrate pages upon CPU fault
As PCIe is non-coherent link, do not allow direct memory access across PCIe link. Handle CPU fault by migrating pages back to host memory. Cc: Joonas Lahtinen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: Sudeep Dutt Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/i915_svm_devmem.c | 70 +- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_svm_devmem.c b/drivers/gpu/drm/i915/i915_svm_devmem.c index 0a1f1394f196..98ab27879041 100644 --- a/drivers/gpu/drm/i915/i915_svm_devmem.c +++ b/drivers/gpu/drm/i915/i915_svm_devmem.c @@ -286,9 +286,77 @@ int i915_devmem_migrate_vma(struct intel_memory_region *mem, return ret; } +static vm_fault_t +i915_devmem_fault_alloc_and_copy(struct i915_devmem_migrate *migrate) +{ + struct device *dev = migrate->i915->drm.dev; + struct migrate_vma *args = migrate->args; + struct page *dpage, *spage; + + DRM_DEBUG_DRIVER("start 0x%lx\n", args->start); + /* Allocate host page */ + spage = migrate_pfn_to_page(args->src[0]); + if (unlikely(!spage || !(args->src[0] & MIGRATE_PFN_MIGRATE))) + return 0; + + dpage = alloc_page_vma(GFP_HIGHUSER, args->vma, args->start); + if (unlikely(!dpage)) + return VM_FAULT_SIGBUS; + lock_page(dpage); + + args->dst[0] = migrate_pfn(page_to_pfn(dpage)) | MIGRATE_PFN_LOCKED; + + /* Copy the pages */ + migrate->npages = 1; + + return 0; +} + +void i915_devmem_fault_finalize_and_map(struct i915_devmem_migrate *migrate) +{ + DRM_DEBUG_DRIVER("\n"); +} + +static inline struct i915_devmem *page_to_devmem(struct page *page) +{ + return container_of(page->pgmap, struct i915_devmem, pagemap); +} + static vm_fault_t i915_devmem_migrate_to_ram(struct vm_fault *vmf) { - return VM_FAULT_SIGBUS; + struct i915_devmem *devmem = page_to_devmem(vmf->page); + struct drm_i915_private *i915 = devmem->i915; + struct i915_devmem_migrate migrate = {0}; + unsigned long src = 0, dst = 0; + vm_fault_t ret; + struct migrate_vma args = { + .vma= vmf->vma, + .start = vmf->address, + .end= vmf->address + PAGE_SIZE, + .src= &src, + .dst= &dst, + }; + + /* XXX: Opportunistically migrate more pages? */ + DRM_DEBUG_DRIVER("addr 0x%lx\n", args.start); + migrate.i915 = i915; + migrate.args = &args; + migrate.src_id = INTEL_REGION_LMEM; + migrate.dst_id = INTEL_REGION_SMEM; + if (migrate_vma_setup(&args) < 0) + return VM_FAULT_SIGBUS; + if (!args.cpages) + return 0; + + ret = i915_devmem_fault_alloc_and_copy(&migrate); + if (ret || dst == 0) + goto done; + + migrate_vma_pages(&args); + i915_devmem_fault_finalize_and_map(&migrate); +done: + migrate_vma_finalize(&args); + return ret; } static void i915_devmem_page_free(struct page *page) -- 2.21.0.rc0.32.g243a4c7e27 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH RESEND 3/4] dt-bindings: drm/bridge: Add GPIO display mux binding
On Wed, Dec 11, 2019 at 12:19 AM Hsin-Yi Wang wrote: > > From: Nicolas Boichat > > Add bindings for Generic GPIO mux driver. > > Signed-off-by: Nicolas Boichat > Signed-off-by: Hsin-Yi Wang > --- > Change from RFC to v1: > - txt to yaml > --- > .../bindings/display/bridge/gpio-mux.yaml | 89 +++ > 1 file changed, 89 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/display/bridge/gpio-mux.yaml > > diff --git a/Documentation/devicetree/bindings/display/bridge/gpio-mux.yaml > b/Documentation/devicetree/bindings/display/bridge/gpio-mux.yaml > new file mode 100644 > index ..cef098749066 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/bridge/gpio-mux.yaml > @@ -0,0 +1,89 @@ > +# SPDX-License-Identifier: GPL-2.0 > +%YAML 1.2 > +--- > +$id: http://devicetree.org/schemas/display/bridge/gpio-mux.yaml# > +$schema: http://devicetree.org/meta-schemas/core.yaml# > + > +title: Generic display mux (1 input, 2 outputs) What makes it generic? Doesn't the mux chip have power supply, possibly a reset line or not, etc.? What about a mux where the GPIO controls the mux? Generally, we avoid 'generic' bindings because h/w is rarely generic. You can have a generic driver which works on multiple devices. > + > +maintainers: > + - Nicolas Boichat > + > +description: | > + This bindings describes a simple display (e.g. HDMI) mux, that has 1 > + input, and 2 outputs. The mux status is controlled by hardware, and > + its status is read back using a GPIO. > + > +properties: > + compatible: > +const: gpio-display-mux > + > + detect-gpios: > +maxItems: 1 > +description: GPIO that indicates the active output > + > + ports: > +type: object > + > +properties: > + port@0: > +type: object > +description: | > + Video port for input. > + > + port@1: > +type: object > +description: | > + 2 video ports for output. > + The reg value in the endpoints matches the GPIO status: when > + GPIO is asserted, endpoint with reg value <1> is selected. You should describe 'endpoint@0' and 'endpoint@1' here too. > + > +required: > + - port@0 > + - port@1 > + > +required: > + - compatible > + - detect-gpios > + - ports > + > +examples: > + - | > +hdmi_mux: hdmi_mux { > + compatible = "gpio-display-mux"; > + status = "okay"; Don't show status in examples. > + detect-gpios = <&pio 36 GPIO_ACTIVE_HIGH>; > + pinctrl-names = "default"; > + pinctrl-0 = <&hdmi_mux_pins>; > + ddc-i2c-bus = <&hdmiddc0>; Not documented. Is the i2c bus muxed too? If not, then this is in the wrong place. > + > + ports { > +#address-cells = <1>; > +#size-cells = <0>; > + > +port@0 { /* input */ > + reg = <0>; > + > + hdmi_mux_in: endpoint { > +remote-endpoint = <&hdmi0_out>; > + }; > +}; > + > +port@1 { /* output */ > + reg = <1>; > + > + #address-cells = <1>; > + #size-cells = <0>; > + > + hdmi_mux_out_anx: endpoint@0 { > +reg = <0>; > +remote-endpoint = <&anx7688_in>; > + }; > + > + hdmi_mux_out_hdmi: endpoint@1 { > +reg = <1>; > +remote-endpoint = <&hdmi_connector_in>; > + }; > +}; > + }; > +}; > -- > 2.24.0.525.g8f36a354ae-goog > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v1 1/2] dt-bindings: display: add sc7180 panel variant
On Fri, Nov 29, 2019 at 12:25:44PM +0530, Harigovindan P wrote: > Add a compatible string to support sc7180 panel version. > > Signed-off-by: Harigovindan P > --- > .../bindings/display/visionox,rm69299.txt | 68 > ++ > 1 file changed, 68 insertions(+) > create mode 100755 > Documentation/devicetree/bindings/display/visionox,rm69299.txt Source files should not have execute permission. New bindings should be in DT schema format. checkpatch.pl will tell you both of these things. > > diff --git a/Documentation/devicetree/bindings/display/visionox,rm69299.txt > b/Documentation/devicetree/bindings/display/visionox,rm69299.txt > new file mode 100755 > index 000..4622191 > --- /dev/null > +++ b/Documentation/devicetree/bindings/display/visionox,rm69299.txt > @@ -0,0 +1,68 @@ > +Visionox model RM69299 DSI display driver > + > +The Visionox RM69299 is a generic display driver, currently only configured > +for use in the 1080p display on the Qualcomm SC7180 MTP board. > + > +Required properties: > +- compatible: should be "visionox,rm69299-1080p-display" RM69299 may be generic, but 1080p sounds like a specific panel. Is there anything besides a 'display'? If not, '-display' is redundant. > +- vdda-supply: phandle of the regulator that provides the supply voltage > + Power IC supply > +- vdd3p3-supply: phandle of the regulator that provides the supply voltage > + Power IC supply > +- reset-gpios: phandle of gpio for reset line > + This should be 8mA, gpio can be configured using mux, pinctrl, > pinctrl-names > + (active low) > +- mode-gpios: phandle of the gpio for choosing the mode of the display > + for single DSI The modes are what? > +- ports: This device has one video port driven by one DSI. Their connections > + are modeled using the OF graph bindings specified in > + Documentation/devicetree/bindings/graph.txt. > + - port@0: DSI input port driven by master DSI > + > +Example: > + > + dsi@ae94000 { > + panel@0 { > + compatible = "visionox,rm69299-1080p-display"; > + reg = <0>; > + > + vdda-supply = <&src_pp1800_l8c>; > + vdd3p3-supply = <&src_pp2800_l18a>; > + > + pinctrl-names = "default", "suspend"; > + pinctrl-0 = <&disp_pins_default>; > + pinctrl-1 = <&disp_pins_default>; > + > + reset-gpios = <&pm6150l_gpios 3 0>; > + > + display-timings { > + timing0: timing-0 { > + /* originally > + * 268316160 Mhz, > + * but value below fits > + * better w/ downstream > + */ > + clock-frequency = <158695680>; > + hactive = <1080>; > + vactive = <2248>; > + hfront-porch = <26>; > + hback-porch = <36>; > + hsync-len = <2>; > + vfront-porch = <56>; > + vback-porch = <4>; > + vsync-len = <4>; > + }; > + }; > + > + ports { > + #address-cells = <1>; > + #size-cells = <0>; > + port@0 { > + reg = <0>; > + panel0_in: endpoint { > + remote-endpoint = <&dsi0_out>; > + }; > + }; > + }; > + }; > + }; > -- > 2.7.4 > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/4] drm/msm: Use dma_resv locking wrappers
On Fri, Dec 13, 2019 at 12:08 PM Daniel Vetter wrote: > > On Mon, Nov 25, 2019 at 10:43:55AM +0100, Daniel Vetter wrote: > > I'll add more fancy logic to them soon, so everyone really has to use > > them. Plus they already provide some nice additional debug > > infrastructure on top of direct ww_mutex usage for the fences tracked > > by dma_resv. > > > > Signed-off-by: Daniel Vetter > > Cc: Rob Clark > > Cc: Sean Paul > > Cc: linux-arm-...@vger.kernel.org > > Cc: freedr...@lists.freedesktop.org > > Ping for some review/acks. > > Thanks, Daniel > > > --- > > drivers/gpu/drm/msm/msm_gem_submit.c | 10 +- > > 1 file changed, 5 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c > > b/drivers/gpu/drm/msm/msm_gem_submit.c > > index 7d04c47d0023..385d4965a8d0 100644 > > --- a/drivers/gpu/drm/msm/msm_gem_submit.c > > +++ b/drivers/gpu/drm/msm/msm_gem_submit.c > > @@ -157,7 +157,7 @@ static void submit_unlock_unpin_bo(struct > > msm_gem_submit *submit, > > msm_gem_unpin_iova(&msm_obj->base, submit->aspace); > > > > if (submit->bos[i].flags & BO_LOCKED) > > - ww_mutex_unlock(&msm_obj->base.resv->lock); > > + dma_resv_unlock(msm_obj->base.resv); > > > > if (backoff && !(submit->bos[i].flags & BO_VALID)) > > submit->bos[i].iova = 0; > > @@ -180,8 +180,8 @@ static int submit_lock_objects(struct msm_gem_submit > > *submit) > > contended = i; > > > > if (!(submit->bos[i].flags & BO_LOCKED)) { > > - ret = > > ww_mutex_lock_interruptible(&msm_obj->base.resv->lock, > > - &submit->ticket); > > + ret = dma_resv_lock_interruptible(msm_obj->base.resv, > > + &submit->ticket); > > if (ret) > > goto fail; > > submit->bos[i].flags |= BO_LOCKED; > > @@ -202,8 +202,8 @@ static int submit_lock_objects(struct msm_gem_submit > > *submit) > > if (ret == -EDEADLK) { > > struct msm_gem_object *msm_obj = submit->bos[contended].obj; > > /* we lost out in a seqno race, lock and retry.. */ > > - ret = > > ww_mutex_lock_slow_interruptible(&msm_obj->base.resv->lock, > > - &submit->ticket); > > + ret = dma_resv_lock_slow_interruptible(msm_obj->base.resv, > > +&submit->ticket); > > if (!ret) { > > submit->bos[contended].flags |= BO_LOCKED; > > slow_locked = contended; > > -- > > 2.24.0 > > Reviewed-by: Eric Anholt ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 5/7] drm: rcar-du: lvds: Fix mode for companion encoder
Hi Fabrizio, Thank you for the patch. On Fri, Dec 06, 2019 at 04:32:52PM +, Fabrizio Castro wrote: > Primary and companion encoders need to set the same mode for > things to work properly. > > rcar_lvds_mode_set gets called into for the primary encoder only, > therefore initialize the companion encoder mode while sorting > the primary encoder mode out. > > Fixes: fa440d870358 ("drm: rcar-du: lvds: Add support for dual-link mode") > Signed-off-by: Fabrizio Castro Would you mind rebasing this on top of "drm: rcar-du: lvds: Get mode from state" ? > --- > v3->v4: > * New patch extracted from patch: > "drm: rcar-du: lvds: Add dual-LVDS panels support" > --- > drivers/gpu/drm/rcar-du/rcar_lvds.c | 12 > 1 file changed, 12 insertions(+) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c > b/drivers/gpu/drm/rcar-du/rcar_lvds.c > index cb2147c..eed5611 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > @@ -614,6 +614,18 @@ static void rcar_lvds_mode_set(struct drm_bridge *bridge, > lvds->display_mode = *adjusted_mode; > > rcar_lvds_get_lvds_mode(lvds); > + if (lvds->companion) { > + struct rcar_lvds *companion_lvds = bridge_to_rcar_lvds( > + lvds->companion); > + > + /* > + * FIXME: We should not be messing with the companion encoder > + * private data from the primary encoder, but since > + * rcar_lvds_mode_set gets called into for the primary encoder > + * only, we don't have much of a choice for now. > + */ > + companion_lvds->mode = lvds->mode; > + } > } > > static int rcar_lvds_attach(struct drm_bridge *bridge) -- Regards, Laurent Pinchart ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 4/7] drm: rcar-du: lvds: Allow for even and odd pixels swap
Hi Fabrizio, Thank you for the patch. On Fri, Dec 06, 2019 at 04:32:51PM +, Fabrizio Castro wrote: > DT properties dual-lvds-even-pixels and dual-lvds-odd-pixels > can be used to work out if the driver needs to swap even > and odd pixels around. > > This patch makes use of the return value from function > drm_of_lvds_get_dual_link_pixel_order to determine if we > need to swap odd and even pixels around for things to work > properly. > > Signed-off-by: Fabrizio Castro > > --- > v3->v4: > * New patch extracted from patch: > "drm: rcar-du: lvds: Add dual-LVDS panels support" > --- > drivers/gpu/drm/rcar-du/rcar_lvds.c | 46 > + > 1 file changed, 37 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c > b/drivers/gpu/drm/rcar-du/rcar_lvds.c > index 6c1f171..cb2147c 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > @@ -71,6 +71,7 @@ struct rcar_lvds { > > struct drm_bridge *companion; > bool dual_link; > + bool stripe_swap_data; Should we merge those two fields in an int dual_link that would be set to DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS, DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS or a negative value (or maybe we the value of enum drm_lvds_dual_link_pixels could be modified so that 0 could mean single link) ? > }; > > #define bridge_to_rcar_lvds(b) \ > @@ -441,12 +442,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge) > rcar_lvds_write(lvds, LVDCHCR, lvdhcr); > > if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) { > - /* > - * Configure vertical stripe based on the mode of operation of > - * the connected device. > - */ > - rcar_lvds_write(lvds, LVDSTRIPE, > - lvds->dual_link ? LVDSTRIPE_ST_ON : 0); > + u32 lvdstripe = 0; > + > + if (lvds->dual_link) > + /* > + * Configure vertical stripe based on the mode of > + * operation of the connected device. > + * > + * ST_SWAP from LVD1STRIPE is reserved, do not set > + * in the companion LVDS Maybe "ST_SWAP is reserved for the companion encoder, only set it in the primary encoder." ? > + */ > + lvdstripe = LVDSTRIPE_ST_ON | > + (lvds->companion && lvds->stripe_swap_data ? > + LVDSTRIPE_ST_SWAP : 0); To match the coding style of the rest of the driver, lvdstripe = LVDSTRIPE_ST_ON | (lvds->companion && lvds->stripe_swap_data ? LVDSTRIPE_ST_SWAP : 0); Even though not strictly required, could you surround this statement with { } as it spans quite a few lines with the comment ? > + rcar_lvds_write(lvds, LVDSTRIPE, lvdstripe); > } > > /* > @@ -702,17 +711,33 @@ static int rcar_lvds_parse_dt_companion(struct > rcar_lvds *lvds) > dual_link = drm_of_lvds_get_dual_link_pixel_order(p0, p1); > of_node_put(p0); > of_node_put(p1); > - if (dual_link >= DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) { > + > + switch (dual_link) { > + case DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS: > + /* > + * By default we generate even pixels from this encoder and odd > + * pixels from the companion encoder, but since p0 is connected > + * to the port expecting ood pixels, and p1 is connected to the > + * port expecting even pixels, we need to swap even and odd > + * pixels around. > + */ > + lvds->stripe_swap_data = true; > + lvds->dual_link = true; > + break; > + case DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS: > lvds->dual_link = true; > - } else if (lvds->next_bridge && lvds->next_bridge->timings) { > + break; > + default: > /* >* Early dual-link bridge specific implementations populate the >* timings field of drm_bridge, read the dual_link flag off the >* bridge directly for backward compatibility. >*/ > - lvds->dual_link = lvds->next_bridge->timings->dual_link; > + if (lvds->next_bridge && lvds->next_bridge->timings) > + lvds->dual_link = lvds->next_bridge->timings->dual_link; > } > > + A single blank line is enough. > if (!lvds->dual_link) { > dev_dbg(dev, "Single-link configuration detected\n"); > goto done; > @@ -728,6 +753,9 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds > *lvds) > "Dual-link configuration detected (companion encoder %pOF)\n", > companion); > > + if (lvds->stripe_swap_data)
Re: [PATCH 4/4] drm/vc4: Use dma_resv locking wrappers
On Fri, Dec 13, 2019 at 12:10 PM Daniel Vetter wrote: > > On Mon, Nov 25, 2019 at 10:43:56AM +0100, Daniel Vetter wrote: > > I'll add more fancy logic to them soon, so everyone really has to use > > them. Plus they already provide some nice additional debug > > infrastructure on top of direct ww_mutex usage for the fences tracked > > by dma_resv. > > > > Signed-off-by: Daniel Vetter > > Ping for some review/acks. > > Thanks, Daniel > > > --- > > drivers/gpu/drm/vc4/vc4_gem.c | 11 +-- > > 1 file changed, 5 insertions(+), 6 deletions(-) > > > > diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c > > index 7a06cb6e31c5..e1cfc3ccd05a 100644 > > --- a/drivers/gpu/drm/vc4/vc4_gem.c > > +++ b/drivers/gpu/drm/vc4/vc4_gem.c > > @@ -568,7 +568,7 @@ vc4_unlock_bo_reservations(struct drm_device *dev, > > for (i = 0; i < exec->bo_count; i++) { > > struct drm_gem_object *bo = &exec->bo[i]->base; > > > > - ww_mutex_unlock(&bo->resv->lock); > > + dma_resv_unlock(bo->resv); > > } > > > > ww_acquire_fini(acquire_ctx); > > @@ -595,8 +595,7 @@ vc4_lock_bo_reservations(struct drm_device *dev, > > retry: > > if (contended_lock != -1) { > > bo = &exec->bo[contended_lock]->base; > > - ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, > > -acquire_ctx); > > + ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); > > if (ret) { > > ww_acquire_done(acquire_ctx); > > return ret; > > @@ -609,19 +608,19 @@ vc4_lock_bo_reservations(struct drm_device *dev, > > > > bo = &exec->bo[i]->base; > > > > - ret = ww_mutex_lock_interruptible(&bo->resv->lock, > > acquire_ctx); > > + ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); > > if (ret) { > > int j; > > > > for (j = 0; j < i; j++) { > > bo = &exec->bo[j]->base; > > - ww_mutex_unlock(&bo->resv->lock); > > + dma_resv_unlock(bo->resv); > > } > > > > if (contended_lock != -1 && contended_lock >= i) { > > bo = &exec->bo[contended_lock]->base; > > > > - ww_mutex_unlock(&bo->resv->lock); > > + dma_resv_unlock(bo->resv); > > } > > > > if (ret == -EDEADLK) { > > -- > > 2.24.0 > > Assuming they're supposed to be exactly equivalent currently, Acked-by: Eric Anholt but we should really just be using drm_gem_lock_reservations() ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RESEND PATCH v2] drm: Add getfb2 ioctl
On Thu, Oct 03, 2019 at 11:31:25AM -0700, Juston Li wrote: > From: Daniel Stone > > getfb2 allows us to pass multiple planes and modifiers, just like addfb2 > over addfb. > > Changes since v1: > - unused modifiers set to 0 instead of DRM_FORMAT_MOD_INVALID > - update ioctl number > > Signed-off-by: Daniel Stone > Signed-off-by: Juston Li > --- > drivers/gpu/drm/drm_crtc_internal.h | 2 + > drivers/gpu/drm/drm_framebuffer.c | 110 > drivers/gpu/drm/drm_ioctl.c | 1 + > include/uapi/drm/drm.h | 2 + > 4 files changed, 115 insertions(+) > > diff --git a/drivers/gpu/drm/drm_crtc_internal.h > b/drivers/gpu/drm/drm_crtc_internal.h > index c7d5e4c21423..16f2413403aa 100644 > --- a/drivers/gpu/drm/drm_crtc_internal.h > +++ b/drivers/gpu/drm/drm_crtc_internal.h > @@ -216,6 +216,8 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev, > void *data, struct drm_file *file_priv); > int drm_mode_getfb(struct drm_device *dev, > void *data, struct drm_file *file_priv); > +int drm_mode_getfb2_ioctl(struct drm_device *dev, > + void *data, struct drm_file *file_priv); > int drm_mode_dirtyfb_ioctl(struct drm_device *dev, > void *data, struct drm_file *file_priv); > > diff --git a/drivers/gpu/drm/drm_framebuffer.c > b/drivers/gpu/drm/drm_framebuffer.c > index 57564318ceea..6db54f177443 100644 > --- a/drivers/gpu/drm/drm_framebuffer.c > +++ b/drivers/gpu/drm/drm_framebuffer.c > @@ -31,6 +31,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -548,7 +549,116 @@ int drm_mode_getfb(struct drm_device *dev, > > out: > drm_framebuffer_put(fb); > + return ret; > +} > + > +/** > + * drm_mode_getfb2 - get extended FB info > + * @dev: drm device for the ioctl > + * @data: data pointer for the ioctl > + * @file_priv: drm file for the ioctl call > + * > + * Lookup the FB given its ID and return info about it. > + * > + * Called by the user via ioctl. > + * > + * Returns: > + * Zero on success, negative errno on failure. > + */ > +int drm_mode_getfb2_ioctl(struct drm_device *dev, > + void *data, struct drm_file *file_priv) > +{ > + struct drm_mode_fb_cmd2 *r = data; > + struct drm_framebuffer *fb; > + unsigned int i; > + int ret; > + > + if (!drm_core_check_feature(dev, DRIVER_MODESET)) > + return -EINVAL; > + > + fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); > + if (!fb) > + return -ENOENT; > + > + /* For multi-plane framebuffers, we require the driver to place the > + * GEM objects directly in the drm_framebuffer. For single-plane > + * framebuffers, we can fall back to create_handle. > + */ > + if (!fb->obj[0] && > + (fb->format->num_planes > 1 || !fb->funcs->create_handle)) { > + ret = -ENODEV; > + goto out; > + } > + > + r->height = fb->height; > + r->width = fb->width; > + r->pixel_format = fb->format->format; > + > + r->flags = 0; > + if (dev->mode_config.allow_fb_modifiers) > + r->flags |= DRM_MODE_FB_MODIFIERS; > + > + for (i = 0; i < ARRAY_SIZE(r->handles); i++) { > + r->handles[i] = 0; > + r->pitches[i] = 0; > + r->offsets[i] = 0; > + r->modifier[i] = 0; > + } > > + for (i = 0; i < fb->format->num_planes; i++) { > + int j; > + > + r->pitches[i] = fb->pitches[i]; > + r->offsets[i] = fb->offsets[i]; > + if (dev->mode_config.allow_fb_modifiers) > + r->modifier[i] = fb->modifier; > + > + /* If we reuse the same object for multiple planes, also > + * return the same handle. > + */ > + for (j = 0; j < i; j++) { > + if (fb->obj[i] == fb->obj[j]) { > + r->handles[i] = r->handles[j]; > + break; > + } > + } > + > + if (r->handles[i]) > + continue; > + > + if (fb->obj[i]) { > + ret = drm_gem_handle_create(file_priv, fb->obj[i], > + &r->handles[i]); > + } else { > + WARN_ON(i > 0); > + ret = fb->funcs->create_handle(fb, file_priv, > +&r->handles[i]); > + } getfb1 doesn't allow non-master/root to see the handles. Here we don't seem to have that same protection? > + > + if (ret != 0) > + goto out; Could be just 'break;' and then we wouldn't even need the label. Rest lgtm. > + } > + > +out: > + if (ret != 0) { > + /* Delete any previously-created handles on failure. */ > + for (i = 0; i < ARRAY_
Re: [PATCH v4 3/7] drm: rcar-du: lvds: Get dual link configuration from DT
Hi Fabrizio, Thank you for the patch. On Fri, Dec 06, 2019 at 04:32:50PM +, Fabrizio Castro wrote: > For dual-LVDS configurations, it is now possible to mark the > DT port nodes for the sink with boolean properties (like > dual-lvds-even-pixels and dual-lvds-odd-pixels) to let drivers > know the encoders need to be configured in dual-LVDS mode. > > Rework the implementation of rcar_lvds_parse_dt_companion > to make use of the DT markers while keeping backward > compatibility. > > Signed-off-by: Fabrizio Castro > > --- > v3->v4: > * New patch extracted from patch: > "drm: rcar-du: lvds: Add dual-LVDS panels support" > --- > drivers/gpu/drm/rcar-du/rcar_lvds.c | 56 > +++-- > 1 file changed, 47 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c > b/drivers/gpu/drm/rcar-du/rcar_lvds.c > index 3cb0a83..6c1f171 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > @@ -669,8 +669,10 @@ EXPORT_SYMBOL_GPL(rcar_lvds_dual_link); > static int rcar_lvds_parse_dt_companion(struct rcar_lvds *lvds) > { > const struct of_device_id *match; > - struct device_node *companion; > + struct device_node *companion, *p0, *p1; Could you rename p0 and p1 to port0 and port1, and spit them to a separate line of variable declaration ? > + struct rcar_lvds *companion_lvds; > struct device *dev = lvds->dev; > + int dual_link; > int ret = 0; > > /* Locate the companion LVDS encoder for dual-link operation, if any. */ > @@ -689,13 +691,55 @@ static int rcar_lvds_parse_dt_companion(struct > rcar_lvds *lvds) > goto done; > } > > + /* > + * We need to work out if the sink is expecting us to function in > + * dual-link mode. We do this by looking at the DT port nodes we are > + * connected to, if they are marked as expecting even pixels and > + * odd pixels than we need to enable vertical stripe output. > + */ > + p0 = of_graph_get_port_by_id(dev->of_node, 1); > + p1 = of_graph_get_port_by_id(companion, 1); > + dual_link = drm_of_lvds_get_dual_link_pixel_order(p0, p1); > + of_node_put(p0); > + of_node_put(p1); > + if (dual_link >= DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS) { > + lvds->dual_link = true; > + } else if (lvds->next_bridge && lvds->next_bridge->timings) { > + /* > + * Early dual-link bridge specific implementations populate the > + * timings field of drm_bridge, read the dual_link flag off the > + * bridge directly for backward compatibility. > + */ > + lvds->dual_link = lvds->next_bridge->timings->dual_link; > + } > + > + if (!lvds->dual_link) { > + dev_dbg(dev, "Single-link configuration detected\n"); > + goto done; > + } > + > lvds->companion = of_drm_find_bridge(companion); > if (!lvds->companion) { > ret = -EPROBE_DEFER; > goto done; > } > > - dev_dbg(dev, "Found companion encoder %pOF\n", companion); > + dev_dbg(dev, > + "Dual-link configuration detected (companion encoder %pOF)\n", > + companion); > + > + companion_lvds = bridge_to_rcar_lvds(lvds->companion); Could you move this line after the FIXME comment ? With these small issues fixed, Reviewed-by: Laurent Pinchart > + > + /* > + * FIXME: We should not be messing with the companion encoder private > + * data from the primary encoder, we should rather let the companion > + * encoder work things out on its own. However, the companion encoder > + * doesn't hold a reference to the primary encoder, and > + * drm_of_lvds_get_dual_link_pixel_order needs to be given references > + * to the output ports of both encoders, therefore leave it like this > + * for the time being. > + */ > + companion_lvds->dual_link = true; > > done: > of_node_put(companion); > @@ -739,13 +783,7 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) > if (ret) > goto done; > > - if ((lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) && > - lvds->next_bridge) > - lvds->dual_link = lvds->next_bridge->timings > - ? lvds->next_bridge->timings->dual_link > - : false; > - > - if (lvds->dual_link) > + if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) > ret = rcar_lvds_parse_dt_companion(lvds); > > done: -- Regards, Laurent Pinchart ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 2/7] drm: rcar-du: lvds: Improve identification of panels
Hi Fabrizio, Thank you for the patch. On Fri, Dec 06, 2019 at 04:32:49PM +, Fabrizio Castro wrote: > Dual-LVDS panels are mistakenly identified as bridges, this > commit replaces the current logic with a call to > drm_of_find_panel_or_bridge to sort that out. > > Signed-off-by: Fabrizio Castro > > --- > v3->v4: > * New patch extracted from patch: > "drm: rcar-du: lvds: Add dual-LVDS panels support" > --- > drivers/gpu/drm/rcar-du/rcar_lvds.c | 45 > + > 1 file changed, 10 insertions(+), 35 deletions(-) > > diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c > b/drivers/gpu/drm/rcar-du/rcar_lvds.c > index 8c6c172..3cb0a83 100644 > --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c > +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c > @@ -21,6 +21,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -705,10 +706,7 @@ static int rcar_lvds_parse_dt_companion(struct rcar_lvds > *lvds) > static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) > { > struct device_node *local_output = NULL; > - struct device_node *remote_input = NULL; > struct device_node *remote = NULL; > - struct device_node *node; > - bool is_bridge = false; > int ret = 0; > > local_output = of_graph_get_endpoint_by_regs(lvds->dev->of_node, 1, 0); > @@ -736,45 +734,22 @@ static int rcar_lvds_parse_dt(struct rcar_lvds *lvds) > goto done; > } I think you can remove the calls above this too. drm_of_find_panel_or_bridge() calls of_graph_get_remote_node(), which in turn calls of_graph_get_endpoint_by_regs(), of_graph_get_remote_port_parent() and checks the status of the remote with of_device_is_available(). > > - remote_input = of_graph_get_remote_endpoint(local_output); > - > - for_each_endpoint_of_node(remote, node) { > - if (node != remote_input) { > - /* > - * We've found one endpoint other than the input, this > - * must be a bridge. > - */ > - is_bridge = true; > - of_node_put(node); > - break; > - } > - } > - > - if (is_bridge) { > - lvds->next_bridge = of_drm_find_bridge(remote); > - if (!lvds->next_bridge) { > - ret = -EPROBE_DEFER; > - goto done; > - } > + ret = drm_of_find_panel_or_bridge(lvds->dev->of_node, 1, 0, > + &lvds->panel, &lvds->next_bridge); > + if (ret) > + goto done; > > - if (lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) > - lvds->dual_link = lvds->next_bridge->timings > - ? lvds->next_bridge->timings->dual_link > - : false; > - } else { > - lvds->panel = of_drm_find_panel(remote); > - if (IS_ERR(lvds->panel)) { > - ret = PTR_ERR(lvds->panel); > - goto done; > - } > - } > + if ((lvds->info->quirks & RCAR_LVDS_QUIRK_DUAL_LINK) && > + lvds->next_bridge) > + lvds->dual_link = lvds->next_bridge->timings > + ? lvds->next_bridge->timings->dual_link > + : false; > > if (lvds->dual_link) > ret = rcar_lvds_parse_dt_companion(lvds); > > done: > of_node_put(local_output); > - of_node_put(remote_input); > of_node_put(remote); > > /* -- Regards, Laurent Pinchart ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v4 1/7] drm: of: Add drm_of_lvds_get_dual_link_pixel_order
Hi Fabrizio, Thank you for the patch. On Fri, Dec 06, 2019 at 04:32:48PM +, Fabrizio Castro wrote: > An LVDS dual-link connection is made of two links, with even > pixels transitting on one link, and odd pixels on the other > link. The device tree can be used to fully describe dual-link > LVDS connections between encoders and bridges/panels. > The sink of an LVDS dual-link connection is made of two ports, > the corresponding OF graph port nodes can be marked > with either dual-lvds-even-pixels or dual-lvds-odd-pixels, > and that fully describes an LVDS dual-link connection, > including pixel order. > > drm_of_lvds_get_dual_link_pixel_order is a new helper > added by this patch, given the source port nodes it > returns DRM_LVDS_DUAL_LINK_EVEN_ODD_PIXELS if the source > port nodes belong to an LVDS dual-link connection, with even > pixels expected to be generated from the first port, and odd > pixels expected to be generated from the second port. > If the new helper returns DRM_LVDS_DUAL_LINK_ODD_EVEN_PIXELS, > odd pixels are expected to be generated from the first port, > and even pixels from the other port. > > Signed-off-by: Fabrizio Castro > > --- > v3->v4: > * The patch had title "drm: Add bus timings helper" in v3 > * The code has now been moved to drm_of, and has been fully > restructured, thanks to Laurent and Daniel for the comments > > v2->v3: > * new patch > --- > drivers/gpu/drm/drm_of.c | 104 > +++ > include/drm/drm_of.h | 20 + > 2 files changed, 124 insertions(+) > > diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c > index 0ca5880..c2e9ab7 100644 > --- a/drivers/gpu/drm/drm_of.c > +++ b/drivers/gpu/drm/drm_of.c > @@ -274,3 +274,107 @@ int drm_of_find_panel_or_bridge(const struct > device_node *np, > return ret; > } > EXPORT_SYMBOL_GPL(drm_of_find_panel_or_bridge); > + > +enum drm_of_lvds_pixels { > + DRM_OF_LVDS_EVEN = BIT(0), > + DRM_OF_LVDS_ODD = BIT(1), > +}; > + > +static int drm_of_lvds_get_port_pixels_type(struct device_node *port_node) > +{ > + bool even_pixels = > + of_property_read_bool(port_node, "dual-lvds-even-pixels"); > + bool odd_pixels = > + of_property_read_bool(port_node, "dual-lvds-odd-pixels"); > + > + return (even_pixels ? DRM_OF_LVDS_EVEN : 0) | > +(odd_pixels ? DRM_OF_LVDS_ODD : 0); > +} > + > +static int drm_of_lvds_get_remote_pixels_type( > + const struct device_node *port_node) > +{ > + struct device_node *endpoint = NULL; > + int pixels_type = -EPIPE; > + > + for_each_child_of_node(port_node, endpoint) { > + struct device_node *remote_port; > + int current_pt; > + > + if (!of_node_name_eq(endpoint, "endpoint")) > + continue; > + > + remote_port = of_graph_get_remote_port(endpoint); > + if (!remote_port) You need an of_node_put(endpoint) in the code paths that exit from the loop. > + return -EPIPE; > + > + current_pt = drm_of_lvds_get_port_pixels_type(remote_port); > + of_node_put(remote_port); > + if (!pixels_type) > + pixels_type = current_pt; This will never happen as pixels_type is initialized to -EPIPE. Replacing the condition with if (pixels_type < 0) should fix it. > + if (!current_pt || pixels_type != current_pt) > + return -EINVAL; I would add a comment to explain this. If I understand the code correcty, something along the lines of /* * Sanity check, ensure that all remote endpoints have the same * pixel type. We may lift this restriction later if we need to * support multiple sinks with different dual-link * configurations by passing the endpoints explicitly to * drm_of_lvds_get_dual_link_pixel_order(). / > + } > + > + return pixels_type; > +} > + > +/** > + * drm_of_lvds_get_dual_link_pixel_order - Get LVDS dual-link pixel order > + * @port1: First DT port node of the Dual-link LVDS source > + * @port2: Second DT port node of the Dual-link LVDS source > + * > + * An LVDS dual-link connection is made of two links, with even pixels > + * transitting on one link, and odd pixels on the other link. This function > + * returns, for two ports of an LVDS dual-link source, which port shall > transmit > + * the even and odd pixels, based on the requirements of the connected sink. > + * > + * The pixel order is determined from the dual-lvds-even-pixels and > + * dual-lvds-odd-pixels properties in the sink's DT port nodes. If those > + * properties are not present, or if their usage is not valid, this function > + * returns -EINVAL. > + * > + * If either port is not connected, this function returns -EPIPE. > + * > + * @port1 and @port2 are typically DT sibling nodes, b
[PATCH v2 00/24] drivers, fs: y2038 updates
These are updates to devidce drivers and file systems that for some reason or another were not included in the kernel in the previous y2038 series. I've gone through all users of time_t again to make sure the kernel is in a long-term maintainable state. Posting these as a series for better organization, but each change here is applicable standalone. Please merge, review, ack/nack etc as you see fit. I will add these to my y2038 branch [1] for linux-next, but can keep rebasing for feedback and to remove any patches that get picked up by a maintainer. Changes since v1 [2]: - Add Acks I received - Rebase to v5.5-rc1, droping patches that got merged already - Add NFS, XFS and the final three patches from another series - Rewrite etnaviv patches Arnd [1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/log/?h=y2038 [2] https://lore.kernel.org/lkml/20191108213257.3097633-1-a...@arndb.de/ Arnd Bergmann (24): Input: input_event: fix struct padding on sparc64 fat: use prandom_u32() for i_generation dlm: use SO_SNDTIMEO_NEW instead of SO_SNDTIMEO_OLD xtensa: ISS: avoid struct timeval um: ubd: use 64-bit time_t where possible acct: stop using get_seconds() tsacct: add 64-bit btime field packet: clarify timestamp overflow quota: avoid time_t in v1_disk_dqblk definition hostfs: pass 64-bit timestamps to/from user space hfs/hfsplus: use 64-bit inode timestamps drm/msm: avoid using 'timespec' drm/etnaviv: reject timeouts with tv_nsec >= NSEC_PER_SEC drm/etnaviv: avoid deprecated timespec sunrpc: convert to time64_t for expiry nfs: use time64_t internally nfs: fix timstamp debug prints nfs: fscache: use timespec64 in inode auxdata xfs: rename compat_time_t to old_time32_t xfs: disallow broken ioctls without compat-32-bit-time xfs: quota: move to time64_t interfaces y2038: remove obsolete jiffies conversion functions y2038: rename itimerval to __kernel_old_itimerval y2038: sparc: remove use of struct timex arch/sparc/kernel/sys_sparc_64.c | 29 +- arch/um/drivers/cow.h | 2 +- arch/um/drivers/cow_user.c| 7 ++- arch/um/drivers/ubd_kern.c| 10 ++-- arch/um/include/shared/os.h | 2 +- arch/um/os-Linux/file.c | 2 +- .../platforms/iss/include/platform/simcall.h | 4 +- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 --- drivers/gpu/drm/etnaviv/etnaviv_drv.h | 11 ++-- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 4 +- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 5 +- drivers/gpu/drm/msm/msm_drv.h | 3 +- drivers/input/evdev.c | 14 ++--- drivers/input/misc/uinput.c | 14 +++-- fs/dlm/lowcomms.c | 6 +- fs/fat/inode.c| 3 +- fs/hfs/hfs_fs.h | 28 +++-- fs/hfs/inode.c| 4 +- fs/hfsplus/hfsplus_fs.h | 28 +++-- fs/hfsplus/inode.c| 12 ++-- fs/hostfs/hostfs.h| 22 --- fs/hostfs/hostfs_kern.c | 15 +++-- fs/nfs/fscache-index.c| 6 +- fs/nfs/fscache.c | 18 -- fs/nfs/fscache.h | 8 ++- fs/nfs/nfs4xdr.c | 10 ++-- fs/quota/quotaio_v1.h | 6 +- fs/xfs/xfs_dquot.c| 6 +- fs/xfs/xfs_ioctl.c| 26 + fs/xfs/xfs_ioctl32.c | 2 +- fs/xfs/xfs_ioctl32.h | 2 +- fs/xfs/xfs_qm.h | 6 +- fs/xfs/xfs_quotaops.c | 6 +- fs/xfs/xfs_trans_dquot.c | 8 ++- include/linux/jiffies.h | 20 --- include/linux/sunrpc/cache.h | 42 -- include/linux/sunrpc/gss_api.h| 4 +- include/linux/sunrpc/gss_krb5.h | 2 +- include/linux/syscalls.h | 9 ++- include/uapi/linux/acct.h | 2 + include/uapi/linux/input.h| 1 + include/uapi/linux/taskstats.h| 6 +- include/uapi/linux/time_types.h | 5 ++ include/uapi/linux/timex.h| 2 + kernel/acct.c | 4 +- kernel/time/itimer.c | 18 +++--- kernel/time/time.c| 58 ++- kernel/tsacct.c | 9 ++- net/packet/af_packet.c| 27 + net/sunrpc/auth_gss/gss_krb5_mech.c | 12 +++- net/sunrpc/auth_gss/gss
[PATCH v2 12/24] drm/msm: avoid using 'timespec'
The timespec structure and associated interfaces are deprecated and will be removed in the future because of the y2038 overflow. The use of ktime_to_timespec() in timeout_to_jiffies() does not suffer from that overflow, but is easy to avoid by just converting the ktime_t into jiffies directly. Reviewed-by: Jordan Crouse Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/msm/msm_drv.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 71547e756e29..740bf7c70d8f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -454,8 +454,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) remaining_jiffies = 0; } else { ktime_t rem = ktime_sub(*timeout, now); - struct timespec ts = ktime_to_timespec(rem); - remaining_jiffies = timespec_to_jiffies(&ts); + remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); } return remaining_jiffies; -- 2.20.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 13/24] drm/etnaviv: reject timeouts with tv_nsec >= NSEC_PER_SEC
Most kernel interfaces that take a timespec require normalized representation with tv_nsec between 0 and NSEC_PER_SEC. Passing values larger than 0x1ull further behaves differently on 32-bit and 64-bit kernels, and can cause the latter to spend a long time counting seconds in timespec64_sub()/set_normalized_timespec64(). Reject those large values at the user interface to enforce sane and portable behavior. Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 1f9c01be40d7..95d72dc00280 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -297,6 +297,9 @@ static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC)) return -EINVAL; + if (args->timeout.tv_nsec > NSEC_PER_SEC) + return -EINVAL; + obj = drm_gem_object_lookup(file, args->handle); if (!obj) return -ENOENT; @@ -360,6 +363,9 @@ static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, if (args->flags & ~(ETNA_WAIT_NONBLOCK)) return -EINVAL; + if (args->timeout.tv_nsec > NSEC_PER_SEC) + return -EINVAL; + if (args->pipe >= ETNA_MAX_PIPES) return -EINVAL; @@ -411,6 +417,9 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, if (args->flags & ~(ETNA_WAIT_NONBLOCK)) return -EINVAL; + if (args->timeout.tv_nsec > NSEC_PER_SEC) + return -EINVAL; + if (args->pipe >= ETNA_MAX_PIPES) return -EINVAL; -- 2.20.0 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 14/24] drm/etnaviv: avoid deprecated timespec
struct timespec is being removed from the kernel because it often leads to code that is not y2038-safe. In the etnaviv driver, monotonic timestamps are used, which do not suffer from overflow, but the usage of timespec here gets in the way of removing the interface completely. Pass down the user-supplied 64-bit value here rather than converting it to an intermediate timespec to avoid the conversion. The conversion is transparent for all regular CLOCK_MONOTONIC values, but is a small change in behavior for excessively large values: the existing code would treat e.g. tv_sec=0x1 the same as tv_sec=0 and not block, while the new code it would block for up to 2^31 seconds. The new behavior is more logical here, but if it causes problems, the truncation can be put back. Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 11 +++ drivers/gpu/drm/etnaviv/etnaviv_drv.h | 11 ++- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 4 ++-- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 +++-- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 5 +++-- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 95d72dc00280..3eb0f9223bea 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -282,11 +282,6 @@ static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data, args->flags, &args->handle); } -#define TS(t) ((struct timespec){ \ - .tv_sec = (t).tv_sec, \ - .tv_nsec = (t).tv_nsec \ -}) - static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, struct drm_file *file) { @@ -304,7 +299,7 @@ static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, if (!obj) return -ENOENT; - ret = etnaviv_gem_cpu_prep(obj, args->op, &TS(args->timeout)); + ret = etnaviv_gem_cpu_prep(obj, args->op, &args->timeout); drm_gem_object_put_unlocked(obj); @@ -357,7 +352,7 @@ static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, { struct drm_etnaviv_wait_fence *args = data; struct etnaviv_drm_private *priv = dev->dev_private; - struct timespec *timeout = &TS(args->timeout); + struct drm_etnaviv_timespec *timeout = &args->timeout; struct etnaviv_gpu *gpu; if (args->flags & ~(ETNA_WAIT_NONBLOCK)) @@ -409,7 +404,7 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, { struct etnaviv_drm_private *priv = dev->dev_private; struct drm_etnaviv_gem_wait *args = data; - struct timespec *timeout = &TS(args->timeout); + struct drm_etnaviv_timespec *timeout = &args->timeout; struct drm_gem_object *obj; struct etnaviv_gpu *gpu; int ret; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index 32cfa5a48d42..efc656efeb0f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -61,7 +61,7 @@ int etnaviv_gem_prime_pin(struct drm_gem_object *obj); void etnaviv_gem_prime_unpin(struct drm_gem_object *obj); void *etnaviv_gem_vmap(struct drm_gem_object *obj); int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, - struct timespec *timeout); + struct drm_etnaviv_timespec *timeout); int etnaviv_gem_cpu_fini(struct drm_gem_object *obj); void etnaviv_gem_free_object(struct drm_gem_object *obj); int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, @@ -107,11 +107,12 @@ static inline size_t size_vstruct(size_t nelem, size_t elem_size, size_t base) * between the specified timeout and the current CLOCK_MONOTONIC time. */ static inline unsigned long etnaviv_timeout_to_jiffies( - const struct timespec *timeout) + const struct drm_etnaviv_timespec *timeout) { - struct timespec64 ts, to; - - to = timespec_to_timespec64(*timeout); + struct timespec64 ts, to = { + .tv_sec = timeout->tv_sec, + .tv_nsec = timeout->tv_nsec, + }; ktime_get_ts64(&ts); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index cb1faaac380a..6adea180d629 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -373,7 +373,7 @@ static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op) } int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, - struct timespec *timeout) + struct drm_etnaviv_timespec *timeout) { struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); struct drm_device *dev = obj->dev; @@ -431,7 +431,7 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj) } int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_objec
RE: [PATCH 1/4] drm/etnaviv: Use dma_resv locking wrappers
>-Original Message- >From: dri-devel On Behalf Of >Daniel Vetter >Sent: Friday, December 13, 2019 3:08 PM >To: DRI Development >Cc: Daniel Vetter ; Intel Graphics Development >; etna...@lists.freedesktop.org; Russell >King ; Vetter, Daniel > >Subject: Re: [PATCH 1/4] drm/etnaviv: Use dma_resv locking wrappers > >On Mon, Nov 25, 2019 at 10:43:53AM +0100, Daniel Vetter wrote: >> I'll add more fancy logic to them soon, so everyone really has to use >> them. Plus they already provide some nice additional debug >> infrastructure on top of direct ww_mutex usage for the fences tracked >> by dma_resv. >> >> Signed-off-by: Daniel Vetter >> Cc: Lucas Stach >> Cc: Russell King >> Cc: Christian Gmeiner >> Cc: etna...@lists.freedesktop.org > >Ping for some review/acks. > >Thanks, Daniel > >> --- >> drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 8 +++- >> 1 file changed, 3 insertions(+), 5 deletions(-) >> >> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c >b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c >> index aa3e4c3b063a..947b21868e72 100644 >> --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c >> +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c >> @@ -113,7 +113,7 @@ static void submit_unlock_object(struct >etnaviv_gem_submit *submit, int i) >> if (submit->bos[i].flags & BO_LOCKED) { >> struct drm_gem_object *obj = &submit->bos[i].obj->base; >> >> -ww_mutex_unlock(&obj->resv->lock); >> +dma_resv_unlock(obj->resv); >> submit->bos[i].flags &= ~BO_LOCKED; >> } >> } >> @@ -133,8 +133,7 @@ static int submit_lock_objects(struct >etnaviv_gem_submit *submit, >> contended = i; >> >> if (!(submit->bos[i].flags & BO_LOCKED)) { >> -ret = ww_mutex_lock_interruptible(&obj->resv- >>lock, >> - ticket); >> +ret = dma_resv_lock(obj->resv, ticket); Should this be dma_resv_lock_interruptible()? Mike >> if (ret == -EALREADY) >> DRM_ERROR("BO at index %u already on >submit list\n", >>i); >> @@ -161,8 +160,7 @@ static int submit_lock_objects(struct >etnaviv_gem_submit *submit, >> obj = &submit->bos[contended].obj->base; >> >> /* we lost out in a seqno race, lock and retry.. */ >> -ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock, >> - ticket); >> +ret = dma_resv_lock_slow_interruptible(obj->resv, ticket); >> if (!ret) { >> submit->bos[contended].flags |= BO_LOCKED; >> slow_locked = contended; >> -- >> 2.24.0 >> > >-- >Daniel Vetter >Software Engineer, Intel Corporation >http://blog.ffwll.ch >___ >dri-devel mailing list >dri-devel@lists.freedesktop.org >https://lists.freedesktop.org/mailman/listinfo/dri-devel ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 16/18] drm/amd/display: Recalculate VCPI slots for new DSC connectors
From: Mikita Lipski [why] Since for DSC MST connector's PBN is claculated differently due to compression, we have to recalculate both PBN and VCPI slots for that connector. [how] The function iterates through all the active streams to find, which have DSC enabled, then recalculates PBN for it and calls drm_dp_helper_update_vcpi_slots_for_dsc to update connector's VCPI slots. v2: - use drm_dp_mst_atomic_enable_dsc per port to enable/disable DSC v3: - Iterate through connector states from the state passed - On each connector state get stream from dc_state, instead CRTC state Reviewed-by: Lyude Paul Signed-off-by: Mikita Lipski --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 76 +-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 93a230d956ee..2ac3a2f0b452 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4986,6 +4986,69 @@ const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs = { .atomic_check = dm_encoder_helper_atomic_check }; +static int dm_update_mst_vcpi_slots_for_dsc(struct drm_atomic_state *state, + struct dc_state *dc_state) +{ + struct dc_stream_state *stream = NULL; + struct drm_connector *connector; + struct drm_connector_state *new_con_state, *old_con_state; + struct amdgpu_dm_connector *aconnector; + struct dm_connector_state *dm_conn_state; + int i, j, clock, bpp; + int vcpi, pbn_div, pbn = 0; + + for_each_oldnew_connector_in_state(state, connector, old_con_state, new_con_state, i) { + + aconnector = to_amdgpu_dm_connector(connector); + + if (!aconnector->port) + continue; + + if (!new_con_state || !new_con_state->crtc) + continue; + + dm_conn_state = to_dm_connector_state(new_con_state); + + for (j = 0; j < dc_state->stream_count; j++) { + stream = dc_state->streams[j]; + if (!stream) + continue; + + if ((struct amdgpu_dm_connector*)stream->dm_stream_context == aconnector) + break; + + stream = NULL; + } + + if (!stream) + continue; + + if (stream->timing.flags.DSC != 1) { + drm_dp_mst_atomic_enable_dsc(state, +aconnector->port, +dm_conn_state->pbn, +0, +false); + continue; + } + + pbn_div = dm_mst_get_pbn_divider(stream->link); + bpp = stream->timing.dsc_cfg.bits_per_pixel; + clock = stream->timing.pix_clk_100hz / 10; + pbn = drm_dp_calc_pbn_mode(clock, bpp, true); + vcpi = drm_dp_mst_atomic_enable_dsc(state, + aconnector->port, + pbn, pbn_div, + true); + if (vcpi < 0) + return vcpi; + + dm_conn_state->pbn = pbn; + dm_conn_state->vcpi_slots = vcpi; + } + return 0; +} + static void dm_drm_plane_reset(struct drm_plane *plane) { struct dm_plane_state *amdgpu_state = NULL; @@ -8022,11 +8085,6 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; - /* Perform validation of MST topology in the state*/ - ret = drm_dp_mst_atomic_check(state); - if (ret) - goto fail; - if (state->legacy_cursor_update) { /* * This is a fast cursor update coming from the plane update @@ -8098,6 +8156,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (!compute_mst_dsc_configs_for_state(state, dm_state->context)) goto fail; + ret = dm_update_mst_vcpi_slots_for_dsc(state, dm_state->context); + if (ret) + goto fail; + if (dc_validate_global_state(dc, dm_state->context, false) != DC_OK) { ret = -EINVAL; goto fail; @@ -8126,6 +8188,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, dc_retain_state(old_dm_state->context); } } + /* Perform validation of MST topology in the state*/ + ret = drm_dp_mst_atomic_check(state); + i
[PATCH v9 08/18] drm/amd/display: Validate DSC caps on MST endpoints
From: David Francis During MST mode enumeration, if a new dc_sink is created, populate it with dsc caps as appropriate. Use drm_dp_mst_dsc_aux_for_port to get the raw caps, then parse them onto dc_sink with dc_dsc_parse_dsc_dpcd. Reviewed-by: Wenjing Liu Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 27 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index ae36d99d0fb2..b544498d435e 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -323,6 +323,7 @@ struct amdgpu_dm_connector { struct drm_dp_mst_port *port; struct amdgpu_dm_connector *mst_port; struct amdgpu_encoder *mst_encoder; + struct drm_dp_aux *dsc_aux; /* TODO see if we can merge with ddc_bus or make a dm_connector */ struct amdgpu_i2c_adapter *i2c; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 81367c869134..7557edee7db0 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -25,6 +25,7 @@ #include #include +#include #include "dm_services.h" #include "amdgpu.h" #include "amdgpu_dm.h" @@ -180,6 +181,26 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .early_unregister = amdgpu_dm_mst_connector_early_unregister, }; +static bool validate_dsc_caps_on_connector(struct amdgpu_dm_connector *aconnector) +{ + struct dc_sink *dc_sink = aconnector->dc_sink; + struct drm_dp_mst_port *port = aconnector->port; + u8 dsc_caps[16] = { 0 }; + + aconnector->dsc_aux = drm_dp_mst_dsc_aux_for_port(port); + + if (!aconnector->dsc_aux) + return false; + + if (drm_dp_dpcd_read(aconnector->dsc_aux, DP_DSC_SUPPORT, dsc_caps, 16) < 0) + return false; + + if (!dc_dsc_parse_dsc_dpcd(dsc_caps, NULL, &dc_sink->sink_dsc_caps.dsc_dec_caps)) + return false; + + return true; +} + static int dm_dp_mst_get_modes(struct drm_connector *connector) { struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -222,10 +243,14 @@ static int dm_dp_mst_get_modes(struct drm_connector *connector) /* dc_link_add_remote_sink returns a new reference */ aconnector->dc_sink = dc_sink; - if (aconnector->dc_sink) + if (aconnector->dc_sink) { amdgpu_dm_update_freesync_caps( connector, aconnector->edid); + if (!validate_dsc_caps_on_connector(aconnector)) + memset(&aconnector->dc_sink->sink_dsc_caps, + 0, sizeof(aconnector->dc_sink->sink_dsc_caps)); + } } drm_connector_update_edid_property( -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3 5/5] MAINTAINERS: add entry for tidss
On Fri, Dec 13, 2019 at 01:17:59PM +0200, Tomi Valkeinen wrote: > Hi Daniel, > > On 13/12/2019 12:30, Daniel Vetter wrote: > > > > +DRM DRIVERS FOR TI KEYSTONE > > > +M: Jyri Sarha > > > +M: Tomi Valkeinen > > > +L: dri-devel@lists.freedesktop.org > > > +S: Maintained > > > +F: drivers/gpu/drm/tidss/ > > > +F: Documentation/devicetree/bindings/display/ti/ti,k2g-dss.yaml > > > +F: Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > > > +F: Documentation/devicetree/bindings/display/ti/ti,j721e-dss.yaml > > > +T: git git://anongit.freedesktop.org/drm/drm-misc > > > > Is the plan to also move other TI drivers over (like tilcdc) or just an > > experiment to see what happens? Asking since if eventually omapdrm moves > > that might be a bit much (or at least needs a discussion first). > > Hmm, yes, I think we should have a plan for these. > > tilcdc: small, old driver, and I don't see much changes for it. The HW is > very different from the ones supported by omapdrm and tidss (the two of > which have many commonalities). I think drm-misc is fine for tilcdc. > > omapdrm: big changes going on for now, but after the rewrite to get rid of > omapdrm specific drivers is done, I expect the patch count to drop, as the > HW is "legacy". > > tidss: the "new" driver, which should get most attention in the future (after > omapdrm rewrite). > > All in all, sometimes there have been very few patches for many months, and > then sometimes there's a big series. Yeah occasionally big series is totally fine for -misc. We're pulling in pretty big amounts of refactoring all the time, so really doesn't make a difference. > I haven't seen a need to have a maintained branch for omapdrm, as multiple > people working on conflicting items has been very rare (there aren't that > many people working on omapdrm). So I've picked patches to my private > branch, which I have rebased as needed. And then I've either pushed via > drm-misc if there's just a few patches, or sent a pull request if there's a > lot. > > Is such a mixed model ok? > > I'm not sure how much is too much for drm-misc, but probably omapdrm and > tidss combined (if pushing everything always via drm-misc) is a bit too > much. So perhaps a maintained TI tree would be an option too, and pushing > everything for omapdrm and tidss via that tree. tbh I dunno either when too much is too much for -misc. I think tilcdc and omapdrm should both easily fit (maybe after the big rewrite). If the shiny new one here becomes too big we can always reconsider. I think the really big drivers like amdgpu or intel don't belong in -misc, that one is clear. In between I guess we'll see. > I'm fine with all options, so I think we can go with whatever is most > acceptable from DRM maintainer point of view. Whatever floats the boat, with a preference for not having tiny trees (simply because those pull request tend to get lost in the noise). -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 4/4] drm/vc4: Use dma_resv locking wrappers
On Mon, Nov 25, 2019 at 10:43:56AM +0100, Daniel Vetter wrote: > I'll add more fancy logic to them soon, so everyone really has to use > them. Plus they already provide some nice additional debug > infrastructure on top of direct ww_mutex usage for the fences tracked > by dma_resv. > > Signed-off-by: Daniel Vetter Ping for some review/acks. Thanks, Daniel > --- > drivers/gpu/drm/vc4/vc4_gem.c | 11 +-- > 1 file changed, 5 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c > index 7a06cb6e31c5..e1cfc3ccd05a 100644 > --- a/drivers/gpu/drm/vc4/vc4_gem.c > +++ b/drivers/gpu/drm/vc4/vc4_gem.c > @@ -568,7 +568,7 @@ vc4_unlock_bo_reservations(struct drm_device *dev, > for (i = 0; i < exec->bo_count; i++) { > struct drm_gem_object *bo = &exec->bo[i]->base; > > - ww_mutex_unlock(&bo->resv->lock); > + dma_resv_unlock(bo->resv); > } > > ww_acquire_fini(acquire_ctx); > @@ -595,8 +595,7 @@ vc4_lock_bo_reservations(struct drm_device *dev, > retry: > if (contended_lock != -1) { > bo = &exec->bo[contended_lock]->base; > - ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, > -acquire_ctx); > + ret = dma_resv_lock_slow_interruptible(bo->resv, acquire_ctx); > if (ret) { > ww_acquire_done(acquire_ctx); > return ret; > @@ -609,19 +608,19 @@ vc4_lock_bo_reservations(struct drm_device *dev, > > bo = &exec->bo[i]->base; > > - ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx); > + ret = dma_resv_lock_interruptible(bo->resv, acquire_ctx); > if (ret) { > int j; > > for (j = 0; j < i; j++) { > bo = &exec->bo[j]->base; > - ww_mutex_unlock(&bo->resv->lock); > + dma_resv_unlock(bo->resv); > } > > if (contended_lock != -1 && contended_lock >= i) { > bo = &exec->bo[contended_lock]->base; > > - ww_mutex_unlock(&bo->resv->lock); > + dma_resv_unlock(bo->resv); > } > > if (ret == -EDEADLK) { > -- > 2.24.0 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 07/18] drm/amd/display: Initialize DSC PPS variables to 0
From: David Francis For DSC MST, sometimes monitors would break out in full-screen static. The issue traced back to the PPS generation code, where these variables were being used uninitialized and were picking up garbage. memset to 0 to avoid this Reviewed-by: Nicholas Kazlauskas Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 3 +++ drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c index 548aac02ca11..4fd51c76317a 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c @@ -518,6 +518,9 @@ bool dp_set_dsc_pps_sdp(struct pipe_ctx *pipe_ctx, bool enable) struct dsc_config dsc_cfg; uint8_t dsc_packed_pps[128]; + memset(&dsc_cfg, 0, sizeof(dsc_cfg)); + memset(dsc_packed_pps, 0, 128); + /* Enable DSC hw block */ dsc_cfg.pic_width = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right; dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c index 0111545dac75..6bdfee20b6a7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c @@ -206,6 +206,9 @@ static bool dsc2_get_packed_pps(struct display_stream_compressor *dsc, const str struct dsc_reg_values dsc_reg_vals; struct dsc_optc_config dsc_optc_cfg; + memset(&dsc_reg_vals, 0, sizeof(dsc_reg_vals)); + memset(&dsc_optc_cfg, 0, sizeof(dsc_optc_cfg)); + DC_LOG_DSC("Getting packed DSC PPS for DSC Config:"); dsc_config_log(dsc, dsc_cfg); DC_LOG_DSC("DSC Picture Parameter Set (PPS):"); -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 05/18] drm/dp_mst: Add helpers for MST DSC and virtual DPCD aux
From: David Francis Add drm_dp_mst_dsc_aux_for_port. To enable DSC, the DSC_ENABLED register might have to be written on the leaf port's DPCD, its parent's DPCD, or the MST manager's DPCD. This function finds the correct aux for the job. As part of this, add drm_dp_mst_is_virtual_dpcd. Virtual DPCD is a DP feature new in DP v1.4, which exposes certain DPCD registers on virtual ports. v2: Remember to unlock mutex on all paths v3: Refactor to match coding style and increase brevity v4: - Check DSC capable MST sink connected directly to the device. - Check branch's port_parent to be set Cc: Lyude Paul Reviewed-by: Wenjing Liu Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 143 ++ include/drm/drm_dp_mst_helper.h | 2 + 2 files changed, 145 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 5a4c2db15c35..d58adcde8d72 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -5003,3 +5003,146 @@ static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_aux *aux) { i2c_del_adapter(&aux->ddc); } + +/** + * drm_dp_mst_is_virtual_dpcd() - Is the given port a virtual DP Peer Device + * @port: The port to check + * + * A single physical MST hub object can be represented in the topology + * by multiple branches, with virtual ports between those branches. + * + * As of DP1.4, An MST hub with internal (virtual) ports must expose + * certain DPCD registers over those ports. See sections 2.6.1.1.1 + * and 2.6.1.1.2 of Display Port specification v1.4 for details. + * + * May acquire mgr->lock + * + * Returns: + * true if the port is a virtual DP peer device, false otherwise + */ +static bool drm_dp_mst_is_virtual_dpcd(struct drm_dp_mst_port *port) +{ + struct drm_dp_mst_port *downstream_port; + + if (!port || port->dpcd_rev < DP_DPCD_REV_14) + return false; + + /* Virtual DP Sink (Internal Display Panel) */ + if (port->port_num >= 8) + return true; + + /* DP-to-HDMI Protocol Converter */ + if (port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV && + !port->mcs && + port->ldps) + return true; + + /* DP-to-DP */ + mutex_lock(&port->mgr->lock); + if (port->pdt == DP_PEER_DEVICE_MST_BRANCHING && + port->mstb && + port->mstb->num_ports == 2) { + list_for_each_entry(downstream_port, &port->mstb->ports, next) { + if (downstream_port->pdt == DP_PEER_DEVICE_SST_SINK && + !downstream_port->input) { + mutex_unlock(&port->mgr->lock); + return true; + } + } + } + mutex_unlock(&port->mgr->lock); + + return false; +} + +/** + * drm_dp_mst_dsc_aux_for_port() - Find the correct aux for DSC + * @port: The port to check. A leaf of the MST tree with an attached display. + * + * Depending on the situation, DSC may be enabled via the endpoint aux, + * the immediately upstream aux, or the connector's physical aux. + * + * This is both the correct aux to read DSC_CAPABILITY and the + * correct aux to write DSC_ENABLED. + * + * This operation can be expensive (up to four aux reads), so + * the caller should cache the return. + * + * Returns: + * NULL if DSC cannot be enabled on this port, otherwise the aux device + */ +struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port) +{ + struct drm_dp_mst_port *immediate_upstream_port; + struct drm_dp_mst_port *fec_port; + u8 endpoint_fec; + u8 endpoint_dsc; + + if (!port) + return NULL; + + if (port->parent->port_parent) + immediate_upstream_port = port->parent->port_parent; + else + immediate_upstream_port = NULL; + + fec_port = immediate_upstream_port; + while (fec_port) { + /* +* Each physical link (i.e. not a virtual port) between the +* output and the primary device must support FEC +*/ + if (!drm_dp_mst_is_virtual_dpcd(fec_port) && + !fec_port->fec_capable) + return NULL; + + fec_port = fec_port->parent->port_parent; + } + + /* DP-to-DP peer device */ + if (drm_dp_mst_is_virtual_dpcd(immediate_upstream_port)) { + u8 upstream_dsc; + + if (drm_dp_dpcd_read(&port->aux, +DP_DSC_SUPPORT, &endpoint_dsc, 1) != 1) + return NULL; + if (drm_dp_dpcd_read(&port->aux, +DP_FEC_CAPABILITY, &endpoint_fec, 1) != 1) + return NULL; + if (drm_dp_dpcd_read(&immediate_upstream_port->aux,
[PATCH v9 17/18] drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs
From: Mikita Lipski [why] Whenever a connector on an MST network is changed or undergoes a modeset, the DSC configs for each stream on that topology will be recalculated. This can change their required bandwidth, requiring a full reprogramming, as though a modeset was performed, even if that stream did not change timing. [how] Adding helper to trigger modesets on MST DSC connectors by setting mode_changed flag on CRTCs in the same topology as affected connector v2: use drm_dp_mst_dsc_aux_for_port function to verify if the port is DSC capable v3: - added _must_check attribute - removed topology manager check - fix typos and indentations Reviewed-by: Lyude Paul Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 61 +++ include/drm/drm_dp_mst_helper.h | 3 ++ 2 files changed, 64 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index ce21662f6144..ec90323949fc 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4775,6 +4775,67 @@ drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr, return 0; } +/** + * drm_dp_mst_add_affected_dsc_crtcs + * @state: Pointer to the new struct drm_dp_mst_topology_state + * @port: Port pointer of connector with new state + * + * Whenever there is a change in mst topology + * DSC configuration would have to be recalculated + * therefore we need to trigger modeset on all affected + * CRTCs in that topology + * + * See also: + * drm_dp_mst_atomic_enable_dsc() + */ +int drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr) +{ + struct drm_dp_mst_topology_state *mst_state; + struct drm_dp_vcpi_allocation *pos; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + + mst_state = drm_atomic_get_mst_topology_state(state, mgr); + + if (IS_ERR(mst_state)) + return -EINVAL; + + list_for_each_entry(pos, &mst_state->vcpis, next) { + + connector = pos->port->connector; + + if (!connector) + return -EINVAL; + + conn_state = drm_atomic_get_connector_state(state, connector); + + if (IS_ERR(conn_state)) + return PTR_ERR(conn_state); + + crtc = conn_state->crtc; + + if (WARN_ON(!crtc)) + return -EINVAL; + + if (!drm_dp_mst_dsc_aux_for_port(pos->port)) + continue; + + crtc_state = drm_atomic_get_crtc_state(mst_state->base.state, crtc); + + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + DRM_DEBUG_ATOMIC("[MST MGR:%p] Setting mode_changed flag on CRTC %p\n", +mgr, crtc); + + crtc_state->mode_changed = true; + } + return 0; +} +EXPORT_SYMBOL(drm_dp_mst_add_affected_dsc_crtcs); + /** * drm_dp_mst_atomic_enable_dsc - Set DSC Enable Flag to On/Off * @state: Pointer to the new drm_atomic_state diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 2919d9776af3..942575de86a0 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -780,6 +780,9 @@ int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, int pbn, int pbn_div, bool enable); int __must_check +drm_dp_mst_add_affected_dsc_crtcs(struct drm_atomic_state *state, + struct drm_dp_mst_topology_mgr *mgr); +int __must_check drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port); -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 18/18] drm/amd/display: Trigger modesets on MST DSC connectors
From: Mikita Lipski Whenever a connector on an MST network is attached, detached, or undergoes a modeset, the DSC configs for each stream on that topology will be recalculated. This can change their required bandwidth, requiring a full reprogramming, as though a modeset was performed, even if that stream did not change timing. Therefore, whenever a crtc has drm_atomic_crtc_needs_modeset, for each crtc that shares a MST topology with that stream and supports DSC, add that crtc (and all affected connectors and planes) to the atomic state and set mode_changed on its state v2: Do this check only on Navi and before adding connectors and planes on modesetting crtcs v3: Call the drm_dp_mst_add_affected_dsc_crtcs() to update all affected CRTCs Reviewed-by: Lyude Paul Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 33 +++ 1 file changed, 33 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 2ac3a2f0b452..909665427110 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -7930,6 +7930,29 @@ dm_determine_update_type_for_commit(struct amdgpu_display_manager *dm, return ret; } +static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm_crtc *crtc) +{ + struct drm_connector *connector; + struct drm_connector_state *conn_state; + struct amdgpu_dm_connector *aconnector = NULL; + int i; + for_each_new_connector_in_state(state, connector, conn_state, i) { + if (conn_state->crtc != crtc) + continue; + + aconnector = to_amdgpu_dm_connector(connector); + if (!aconnector->port) + aconnector = NULL; + else + break; + } + + if (!aconnector) + return 0; + + return drm_dp_mst_add_affected_dsc_crtcs(state, &aconnector->mst_mgr); +} + /** * amdgpu_dm_atomic_check() - Atomic check implementation for AMDgpu DM. * @dev: The DRM device @@ -7982,6 +8005,16 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; + if (adev->asic_type >= CHIP_NAVI10) { + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + if (drm_atomic_crtc_needs_modeset(new_crtc_state)) { + ret = add_affected_mst_dsc_crtcs(state, crtc); + if (ret) + goto fail; + } + } + } + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { if (!drm_atomic_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->color_mgmt_changed && -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 15/18] drm/amd/display: MST DSC compute fair share
From: David Francis If there is limited link bandwidth on a MST network, it must be divided fairly between the streams on that network Implement an algorithm to determine the correct DSC config for each stream The algorithm: This [ ] ( ) represents the range of bandwidths possible for a given stream. The [] area represents the range of DSC configs, and the () represents no DSC. The bandwidth used increases from left to right. First, try disabling DSC on all streams [ ] (|) [ ](|) Check this against the bandwidth limits of the link and each branch (including each endpoint). If it passes, the job is done Second, try maximum DSC compression on all streams that support DSC [| ]( ) [|] ( ) If this does not pass, then enabling this combination of streams is impossible Otherwise, divide the remaining bandwidth evenly amongst the streams [| ] ( ) [| ]( ) If one or more of the streams reach minimum compression, evenly divide the reamining bandwidth amongst the remaining streams [|] ( ) [ |] ( ) [ | ] ( ) [ | ] ( ) If all streams can reach minimum compression, disable compression greedily [ |] ( ) [|]( ) [ ](|) Perform this algorithm on each full update, on each MST link with at least one DSC stream on it After the configs are computed, call dcn20_add_dsc_to_stream_resource on each stream with DSC enabled. It is only after all streams are created that we can know which of them will need DSC. Do all of this at the end of amdgpu atomic check. If it fails, fail check; This combination of timings cannot be supported. v2: Use drm_dp_mst_atomic_check to validate bw for certain dsc configurations v3: Use dc_dsc_policy structure to get min and max bpp rate for DSC configuration Cc: Lyude Paul Cc: Manasi Navare Reviewed-by: Wenjing Liu Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 + .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 364 ++ .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 3 + .../drm/amd/display/dc/dcn20/dcn20_resource.c | 7 +- .../drm/amd/display/dc/dcn20/dcn20_resource.h | 1 + 5 files changed, 376 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 753a79734817..93a230d956ee 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -8095,6 +8095,9 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, if (ret) goto fail; + if (!compute_mst_dsc_configs_for_state(state, dm_state->context)) + goto fail; + if (dc_validate_global_state(dc, dm_state->context, false) != DC_OK) { ret = -EINVAL; goto fail; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index c376c8ccd391..6d13d1c33530 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -40,6 +40,10 @@ #if defined(CONFIG_DEBUG_FS) #include "amdgpu_dm_debugfs.h" #endif + + +#include "dc/dcn20/dcn20_resource.h" + /* #define TRACE_DPCD */ #ifdef TRACE_DPCD @@ -499,3 +503,363 @@ int dm_mst_get_pbn_divider(struct dc_link *link) return dc_link_bandwidth_kbps(link, dc_link_get_link_cap(link)) / (8 * 1000 * 54); } + +struct dsc_mst_fairness_params { + struct dc_crtc_timing *timing; + struct dc_sink *sink; + struct dc_dsc_bw_range bw_range; + bool compression_possible; + struct drm_dp_mst_port *port; +}; + +struct dsc_mst_fairness_vars { + int pbn; + bool dsc_enabled; + int bpp_x16; +}; + +static int kbps_to_peak_pbn(int kbps) +{ + u64 peak_kbps = kbps; + + peak_kbps *= 1006; + peak_kbps /= 1000; + return (int) DIV_ROUND_UP(peak_kbps * 64, (54 * 8 * 1000)); +} + +static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *params, + struct dsc_mst_fairness_vars *vars, + int count) +{ + int i; + + for (i = 0; i < count; i++) { + memset(¶ms[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg)); + if (vars[i].dsc_enabled && dc_dsc_compute_config( + params[i].sink->ctx->dc->res_pool->dscs[0], + ¶ms[i].sink->sink_dsc_caps.dsc_dec_caps,
[PATCH v9 11/18] drm/dp_mst: Add DSC enablement helpers to DRM
From: Mikita Lipski Adding a helper function to be called by drivers outside of DRM to enable DSC on the MST ports. Function is called to recalculate VCPI allocation if DSC is enabled and raise the DSC flag to enable. In case of disabling DSC the flag is set to false and recalculation of VCPI slots is expected to be done in encoder's atomic_check. v2: squash separate functions into one and call it per port v3: Fix comment typos Reviewed-by: Lyude Paul Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 61 +++ include/drm/drm_dp_mst_helper.h | 5 +++ 2 files changed, 66 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index bb0844dfb3d2..7cd505e771ff 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4716,6 +4716,67 @@ drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr, return 0; } +/** + * drm_dp_mst_atomic_enable_dsc - Set DSC Enable Flag to On/Off + * @state: Pointer to the new drm_atomic_state + * @port: Pointer to the affected MST Port + * @pbn: Newly recalculated bw required for link with DSC enabled + * @pbn_div: Divider to calculate correct number of pbn per slot + * @enable: Boolean flag to enable or disable DSC on the port + * + * This function enables DSC on the given Port + * by recalculating its vcpi from pbn provided + * and sets dsc_enable flag to keep track of which + * ports have DSC enabled + * + */ +int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, +struct drm_dp_mst_port *port, +int pbn, int pbn_div, +bool enable) +{ + struct drm_dp_mst_topology_state *mst_state; + struct drm_dp_vcpi_allocation *pos; + bool found = false; + int vcpi = 0; + + mst_state = drm_atomic_get_mst_topology_state(state, port->mgr); + + if (IS_ERR(mst_state)) + return PTR_ERR(mst_state); + + list_for_each_entry(pos, &mst_state->vcpis, next) { + if (pos->port == port) { + found = true; + break; + } + } + + if (!found) { + DRM_DEBUG_ATOMIC("[MST PORT:%p] Couldn't find VCPI allocation in mst state %p\n", +port, mst_state); + return -EINVAL; + } + + if (pos->dsc_enabled == enable) { + DRM_DEBUG_ATOMIC("[MST PORT:%p] DSC flag is already set to %d, returning %d VCPI slots\n", +port, enable, pos->vcpi); + vcpi = pos->vcpi; + } + + if (enable) { + vcpi = drm_dp_atomic_find_vcpi_slots(state, port->mgr, port, pbn, pbn_div); + DRM_DEBUG_ATOMIC("[MST PORT:%p] Enabling DSC flag, reallocating %d VCPI slots on the port\n", +port, vcpi); + if (vcpi < 0) + return -EINVAL; + } + + pos->dsc_enabled = enable; + + return vcpi; +} +EXPORT_SYMBOL(drm_dp_mst_atomic_enable_dsc); /** * drm_dp_mst_atomic_check - Check that the new state of an MST topology in an * atomic update is valid diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 0f813d6346aa..830c94b7f45d 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -502,6 +502,7 @@ struct drm_dp_payload { struct drm_dp_vcpi_allocation { struct drm_dp_mst_port *port; int vcpi; + bool dsc_enabled; struct list_head next; }; @@ -773,6 +774,10 @@ drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int pbn, int pbn_div); +int drm_dp_mst_atomic_enable_dsc(struct drm_atomic_state *state, +struct drm_dp_mst_port *port, +int pbn, int pbn_div, +bool enable); int __must_check drm_dp_atomic_release_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 03/18] drm/dp_mst: Add MST support to DP DPCD R/W functions
From: David Francis Instead of having drm_dp_dpcd_read/write and drm_dp_mst_dpcd_read/write as entry points into the aux code, have drm_dp_dpcd_read/write handle both. This means that DRM drivers can make MST DPCD read/writes. v2: Fix spacing v3: Dump dpcd access on MST read/writes v4: Fix calling wrong function on DPCD write v5: delete deprecated include of drmP.h Reviewed-by: Lyude Paul Reviewed-by: Harry Wentland Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_aux_dev.c | 12 ++-- drivers/gpu/drm/drm_dp_helper.c | 30 -- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c index 0cfb386754c3..2510717d5a08 100644 --- a/drivers/gpu/drm/drm_dp_aux_dev.c +++ b/drivers/gpu/drm/drm_dp_aux_dev.c @@ -163,11 +163,7 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to) break; } - if (aux_dev->aux->is_remote) - res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, - todo); - else - res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo); + res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo); if (res <= 0) break; @@ -215,11 +211,7 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from) break; } - if (aux_dev->aux->is_remote) - res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf, - todo); - else - res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo); + res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo); if (res <= 0) break; diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2c7870aef469..2faef8bd911f 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "drm_crtc_helper_internal.h" @@ -266,7 +267,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, /** * drm_dp_dpcd_read() - read a series of bytes from the DPCD - * @aux: DisplayPort AUX channel + * @aux: DisplayPort AUX channel (SST or MST) * @offset: address of the (first) register to read * @buffer: buffer to store the register values * @size: number of bytes in @buffer @@ -295,13 +296,18 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset, * We just have to do it before any DPCD access and hope that the * monitor doesn't power down exactly after the throw away read. */ - ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, buffer, -1); - if (ret != 1) - goto out; + if (!aux->is_remote) { + ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, DP_DPCD_REV, +buffer, 1); + if (ret != 1) + goto out; + } - ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, buffer, -size); + if (aux->is_remote) + ret = drm_dp_mst_dpcd_read(aux, offset, buffer, size); + else + ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_READ, offset, +buffer, size); out: drm_dp_dump_access(aux, DP_AUX_NATIVE_READ, offset, buffer, ret); @@ -311,7 +317,7 @@ EXPORT_SYMBOL(drm_dp_dpcd_read); /** * drm_dp_dpcd_write() - write a series of bytes to the DPCD - * @aux: DisplayPort AUX channel + * @aux: DisplayPort AUX channel (SST or MST) * @offset: address of the (first) register to write * @buffer: buffer containing the values to write * @size: number of bytes in @buffer @@ -328,8 +334,12 @@ ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, { int ret; - ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, -size); + if (aux->is_remote) + ret = drm_dp_mst_dpcd_write(aux, offset, buffer, size); + else + ret = drm_dp_dpcd_access(aux, DP_AUX_NATIVE_WRITE, offset, +buffer, size); + drm_dp_dump_access(aux, DP_AUX_NATIVE_WRITE, offset, buffer, ret); return ret; } -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 02/18] drm/dp_mst: Parse FEC capability on MST ports
From: David Francis As of DP1.4, ENUM_PATH_RESOURCES returns a bit indicating if FEC can be supported up to that point in the MST network. The bit is the first byte of the ENUM_PATH_RESOURCES ack reply, bottom-most bit (refer to section 2.11.9.4 of DP standard, v1.4) That value is needed for FEC and DSC support Store it on drm_dp_mst_port Reviewed-by: Lyude Paul Reviewed-by: Harry Wentland Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++ include/drm/drm_dp_mst_helper.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 363e7e58e7e7..ba5328cdc853 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -846,6 +846,7 @@ static bool drm_dp_sideband_parse_enum_path_resources_ack(struct drm_dp_sideband { int idx = 1; repmsg->u.path_resources.port_number = (raw->msg[idx] >> 4) & 0xf; + repmsg->u.path_resources.fec_capable = raw->msg[idx] & 0x1; idx++; if (idx > raw->curlen) goto fail_len; @@ -2894,6 +2895,7 @@ drm_dp_send_enum_path_resources(struct drm_dp_mst_topology_mgr *mgr, path_res->avail_payload_bw_number); port->available_pbn = path_res->avail_payload_bw_number; + port->fec_capable = path_res->fec_capable; } } diff --git a/include/drm/drm_dp_mst_helper.h b/include/drm/drm_dp_mst_helper.h index 68656913cfe5..0cada01e8139 100644 --- a/include/drm/drm_dp_mst_helper.h +++ b/include/drm/drm_dp_mst_helper.h @@ -156,6 +156,8 @@ struct drm_dp_mst_port { * audio-capable. */ bool has_audio; + + bool fec_capable; }; /** @@ -383,6 +385,7 @@ struct drm_dp_port_number_req { struct drm_dp_enum_path_resources_ack_reply { u8 port_number; + bool fec_capable; u16 full_payload_bw_number; u16 avail_payload_bw_number; }; -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 12/18] drm/dp_mst: Add branch bandwidth validation to MST atomic check
From: Mikita Lipski [why] Adding PBN attribute to drm_dp_vcpi_allocation structure to keep track of how much bandwidth each Port requires. Adding drm_dp_mst_atomic_check_bw_limit to verify that state's bandwidth needs doesn't exceed available bandwidth. The funtion is called in drm_dp_mst_atomic_check after drm_dp_mst_atomic_check_topology_state to fully verify that the proposed topology is supported. v2: Fixing some typos and indentations Reviewed-by: Lyude Paul Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 66 ++- include/drm/drm_dp_mst_helper.h | 1 + 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 7cd505e771ff..f8b72ac79c66 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4052,7 +4052,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_vcpi_allocation *pos, *vcpi = NULL; - int prev_slots, req_slots; + int prev_slots, prev_bw, req_slots; topology_state = drm_atomic_get_mst_topology_state(state, mgr); if (IS_ERR(topology_state)) @@ -4063,6 +4063,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, if (pos->port == port) { vcpi = pos; prev_slots = vcpi->vcpi; + prev_bw = vcpi->pbn; /* * This should never happen, unless the driver tries @@ -4078,8 +4079,10 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, break; } } - if (!vcpi) + if (!vcpi) { prev_slots = 0; + prev_bw = 0; + } if (pbn_div <= 0) pbn_div = mgr->pbn_div; @@ -4089,6 +4092,9 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n", port->connector->base.id, port->connector->name, port, prev_slots, req_slots); + DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] PBN %d -> %d\n", +port->connector->base.id, port->connector->name, +port, prev_bw, pbn); /* Add the new allocation to the state */ if (!vcpi) { @@ -4101,6 +4107,7 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, list_add(&vcpi->next, &topology_state->vcpis); } vcpi->vcpi = req_slots; + vcpi->pbn = pbn; return req_slots; } @@ -4677,6 +4684,58 @@ static void drm_dp_mst_destroy_state(struct drm_private_obj *obj, kfree(mst_state); } +static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port, +struct drm_dp_mst_branch *branch) +{ + while (port->parent) { + if (port->parent == branch) + return true; + + if (port->parent->port_parent) + port = port->parent->port_parent; + else + break; + } + return false; +} + +static inline +int drm_dp_mst_atomic_check_bw_limit(struct drm_dp_mst_branch *branch, +struct drm_dp_mst_topology_state *mst_state) +{ + struct drm_dp_mst_port *port; + struct drm_dp_vcpi_allocation *vcpi; + int pbn_limit = 0, pbn_used = 0; + + list_for_each_entry(port, &branch->ports, next) { + if (port->mstb) + if (drm_dp_mst_atomic_check_bw_limit(port->mstb, mst_state)) + return -EINVAL; + + if (port->available_pbn > 0) + pbn_limit = port->available_pbn; + } + DRM_DEBUG_ATOMIC("[MST BRANCH:%p] branch has %d PBN available\n", +branch, pbn_limit); + + list_for_each_entry(vcpi, &mst_state->vcpis, next) { + if (!vcpi->pbn) + continue; + + if (drm_dp_mst_port_downstream_of_branch(vcpi->port, branch)) + pbn_used += vcpi->pbn; + } + DRM_DEBUG_ATOMIC("[MST BRANCH:%p] branch used %d PBN\n", +branch, pbn_used); + + if (pbn_used > pbn_limit) { + DRM_DEBUG_ATOMIC("[MST BRANCH:%p] No available bandwidth\n", +branch); + return -EINVAL; + } + return 0; +} + static inline int drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_topology_state *mst_state) @@ -4808,6 +4867,9 @@ int drm_dp_mst_atomic_check(struct drm_atomic_s
[PATCH v9 10/18] drm/dp_mst: Manually overwrite PBN divider for calculating timeslots
From: Mikita Lipski [why] For DSC case we cannot use topology manager's PBN divider variable. The default divider does not take FEC into account. Therefore the driver has to calculate its own divider based on the link rate and lane count its handling, as it is hw specific. [how] Pass pbn_div as an argument, which is used if its more than zero, otherwise default topology manager's pbn_div will be used. Cc: Lyude Paul Cc: Harry Wentland Cc: Manasi Navare Signed-off-by: Mikita Lipski --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 3 ++- drivers/gpu/drm/drm_dp_mst_topology.c | 9 +++-- drivers/gpu/drm/i915/display/intel_dp_mst.c | 2 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 3 ++- include/drm/drm_dp_mst_helper.h | 3 ++- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 9fc03fc1017d..753a79734817 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4972,7 +4972,8 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state, mst_mgr, mst_port, - dm_new_connector_state->pbn); + dm_new_connector_state->pbn, + 0); if (dm_new_connector_state->vcpi_slots < 0) { DRM_DEBUG_ATOMIC("failed finding vcpi slots: %d\n", (int)dm_new_connector_state->vcpi_slots); return dm_new_connector_state->vcpi_slots; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 74bed71f7315..bb0844dfb3d2 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4020,6 +4020,7 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, * @mgr: MST topology manager for the port * @port: port to find vcpi slots for * @pbn: bandwidth required for the mode in PBN + * @pbn_div: divider for DSC mode that takes FEC into account * * Allocates VCPI slots to @port, replacing any previous VCPI allocations it * may have had. Any atomic drivers which support MST must call this function @@ -4046,7 +4047,8 @@ static int drm_dp_init_vcpi(struct drm_dp_mst_topology_mgr *mgr, */ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_port *port, int pbn) + struct drm_dp_mst_port *port, int pbn, + int pbn_div) { struct drm_dp_mst_topology_state *topology_state; struct drm_dp_vcpi_allocation *pos, *vcpi = NULL; @@ -4079,7 +4081,10 @@ int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state, if (!vcpi) prev_slots = 0; - req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div); + if (pbn_div <= 0) + pbn_div = mgr->pbn_div; + + req_slots = DIV_ROUND_UP(pbn, pbn_div); DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] [MST PORT:%p] VCPI %d -> %d\n", port->connector->base.id, port->connector->name, diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 92be17711287..a068f54a6793 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -65,7 +65,7 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, false); slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, - port, crtc_state->pbn); + port, crtc_state->pbn, 0); if (slots == -EDEADLK) return slots; if (slots >= 0) diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 1c9e23d5a6fd..edb78966c5b6 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -787,7 +787,8 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port, - asyh->dp.pbn); + asyh->dp.pbn, +
[PATCH v9 13/18] drm/dp_mst: Rename drm_dp_mst_atomic_check_topology_state
From: Mikita Lipski [why] drm_dp_mst_atomic_check_topology_state() should be renamed to reflect more specific type of check. Since it is verifying payload allocation limit it should be renamed into drm_dp_mst_atomic_check_vcpi_alloc_limit() Cc: Lyude Paul Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index f8b72ac79c66..ce21662f6144 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4737,8 +4737,8 @@ int drm_dp_mst_atomic_check_bw_limit(struct drm_dp_mst_branch *branch, } static inline int -drm_dp_mst_atomic_check_topology_state(struct drm_dp_mst_topology_mgr *mgr, - struct drm_dp_mst_topology_state *mst_state) +drm_dp_mst_atomic_check_vcpi_alloc_limit(struct drm_dp_mst_topology_mgr *mgr, +struct drm_dp_mst_topology_state *mst_state) { struct drm_dp_vcpi_allocation *vcpi; int avail_slots = 63, payload_count = 0; @@ -4864,7 +4864,7 @@ int drm_dp_mst_atomic_check(struct drm_atomic_state *state) int i, ret = 0; for_each_new_mst_mgr_in_state(state, mgr, mst_state, i) { - ret = drm_dp_mst_atomic_check_topology_state(mgr, mst_state); + ret = drm_dp_mst_atomic_check_vcpi_alloc_limit(mgr, mst_state); if (ret) break; ret = drm_dp_mst_atomic_check_bw_limit(mgr->mst_primary, mst_state); -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 14/18] drm/amd/display: Add PBN per slot calculation for DSC
From: Mikita Lipski [why] Need to calculate VCPI slots differently for DSC to take in account current link rate, link count and FEC. [how] Add helper to get pbn_div from dc_link Cc: Harry Wentland Cc: Lyude Paul Signed-off-by: Mikita Lipski --- .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c | 8 .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 7557edee7db0..c376c8ccd391 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -491,3 +491,11 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, aconnector->connector_id); } +int dm_mst_get_pbn_divider(struct dc_link *link) +{ + if (!link) + return 0; + + return dc_link_bandwidth_kbps(link, + dc_link_get_link_cap(link)) / (8 * 1000 * 54); +} diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 2da851b40042..a553ea046185 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -29,6 +29,8 @@ struct amdgpu_display_manager; struct amdgpu_dm_connector; +int dm_mst_get_pbn_divider(struct dc_link *link); + void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector); -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 00/18] DSC MST support for DRM and AMDGPU
From: Mikita Lipski This set of patches is a continuation of DSC enablement patches for AMDGPU. This set enables DSC on MST. It also contains implementation of both encoder and connector atomic check routines. These patches have been introduced in multiple iterations to the mailing list before. These patches were developed by David Francis as part of his work on DSC. v2: squashed previously 3 separate atomic check patches, separate atomic check for dsc connectors, track vcpi and pbn on connectors. v3: Moved modeset trigger on affected MST displays to DRM v4: Fix warnings, use current mode's bpc rather than display's maximum capable one v5: Moving branch's bandwidth validation to DRM, Added function to enable DSC per port in DRM v6: Compute fair share uses DRM helper for BW validation v7: Add helper to overwrite PBN divider per slot, Add helper function to trigger modeset on affected DSC connectors in DRM v8: Rebased on top of the MST refactor patches that were on DRM-tip Some cosmetic and cleanup changes v9: - PBN calculation updated (preventing flooring the remainder) together with selftest - Move branch->num_ports deprecator to port unlink function - Added capability check for MST DSC capable sinks connected directly to GPU, also removed Lyude's reviewed-by since the functionality has changed in patch: "drm/dp_mst: Add helpers for MST DSC and virtual DPCD aux" - Renaming of drm_dp_mst_atomic_check_topology_state - Bug fixes after testing with MST DSC capable sink - More state and sanity checks added - Typos fix and indentation fixes David Francis (9): drm/dp_mst: Add PBN calculation for DSC modes drm/dp_mst: Parse FEC capability on MST ports drm/dp_mst: Add MST support to DP DPCD R/W functions drm/dp_mst: Fill branch->num_ports drm/dp_mst: Add helpers for MST DSC and virtual DPCD aux drm/amd/display: Initialize DSC PPS variables to 0 drm/amd/display: Validate DSC caps on MST endpoints drm/amd/display: Write DSC enable to MST DPCD drm/amd/display: MST DSC compute fair share Mikita Lipski (9): drm/dp_mst: Add new quirk for Synaptics MST hubs drm/dp_mst: Manually overwrite PBN divider for calculating timeslots drm/dp_mst: Add DSC enablement helpers to DRM drm/dp_mst: Add branch bandwidth validation to MST atomic check drm/dp_mst: Rename drm_dp_mst_atomic_check_topology_state drm/amd/display: Add PBN per slot calculation for DSC drm/amd/display: Recalculate VCPI slots for new DSC connectors drm/dp_mst: Add helper to trigger modeset on affected DSC MST CRTCs drm/amd/display: Trigger modesets on MST DSC connectors .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 117 - .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 1 + .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 19 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.c | 399 +- .../display/amdgpu_dm/amdgpu_dm_mst_types.h | 5 + .../drm/amd/display/dc/core/dc_link_hwss.c| 3 + .../gpu/drm/amd/display/dc/dcn20/dcn20_dsc.c | 3 + .../drm/amd/display/dc/dcn20/dcn20_resource.c | 7 +- .../drm/amd/display/dc/dcn20/dcn20_resource.h | 1 + drivers/gpu/drm/drm_dp_aux_dev.c | 12 +- drivers/gpu/drm/drm_dp_helper.c | 32 +- drivers/gpu/drm/drm_dp_mst_topology.c | 389 - drivers/gpu/drm/i915/display/intel_dp_mst.c | 5 +- drivers/gpu/drm/nouveau/dispnv50/disp.c | 5 +- drivers/gpu/drm/radeon/radeon_dp_mst.c| 2 +- .../drm/selftests/test-drm_dp_mst_helper.c| 10 +- include/drm/drm_dp_helper.h | 7 + include/drm/drm_dp_mst_helper.h | 20 +- 18 files changed, 986 insertions(+), 51 deletions(-) -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 06/18] drm/dp_mst: Add new quirk for Synaptics MST hubs
From: Mikita Lipski Synaptics DP1.4 hubs (BRANCH_ID 0x90CC24) do not support virtual DPCD registers, but do support DSC. The DSC caps can be read from the physical aux, like in SST DSC. These hubs have many different DEVICE_IDs. Add a new quirk to detect this case. v2: Fix error when checking return of drm_dp_read_desc Reviewed-by: Wenjing Liu Reviewed-by: Lyude Paul Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_helper.c | 2 ++ drivers/gpu/drm/drm_dp_mst_topology.c | 27 +++ include/drm/drm_dp_helper.h | 7 +++ 3 files changed, 36 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 2faef8bd911f..374cedc6c2ac 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -1165,6 +1165,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = { { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) }, /* CH7511 seems to leave SINK_COUNT zeroed */ { OUI(0x00, 0x00, 0x00), DEVICE_ID('C', 'H', '7', '5', '1', '1'), false, BIT(DP_DPCD_QUIRK_NO_SINK_COUNT) }, + /* Synaptics DP1.4 MST hubs can support DSC without virtual DPCD */ + { OUI(0x90, 0xCC, 0x24), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) }, }; #undef OUI diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index d58adcde8d72..74bed71f7315 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -5075,6 +5075,7 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port) { struct drm_dp_mst_port *immediate_upstream_port; struct drm_dp_mst_port *fec_port; + struct drm_dp_desc desc = { 0 }; u8 endpoint_fec; u8 endpoint_dsc; @@ -5127,6 +5128,32 @@ struct drm_dp_aux *drm_dp_mst_dsc_aux_for_port(struct drm_dp_mst_port *port) if (drm_dp_mst_is_virtual_dpcd(port)) return &port->aux; + /* +* Synaptics quirk +* Applies to ports for which: +* - Physical aux has Synaptics OUI +* - DPv1.4 or higher +* - Port is on primary branch device +* - Not a VGA adapter (DP_DWN_STRM_PORT_TYPE_ANALOG) +*/ + if (drm_dp_read_desc(port->mgr->aux, &desc, true)) + return NULL; + + if (drm_dp_has_quirk(&desc, DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD) && + port->mgr->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14 && + port->parent == port->mgr->mst_primary) { + u8 downstreamport; + + if (drm_dp_dpcd_read(&port->aux, DP_DOWNSTREAMPORT_PRESENT, +&downstreamport, 1) < 0) + return NULL; + + if ((downstreamport & DP_DWN_STRM_PORT_PRESENT) && + ((downstreamport & DP_DWN_STRM_PORT_TYPE_MASK) +!= DP_DWN_STRM_PORT_TYPE_ANALOG)) + return port->mgr->aux; + } + /* * The check below verifies if the MST sink * connected to the GPU is capable of DSC - diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h index b2057009aabc..7972c8bf97cf 100644 --- a/include/drm/drm_dp_helper.h +++ b/include/drm/drm_dp_helper.h @@ -1522,6 +1522,13 @@ enum drm_dp_quirk { * The driver should ignore SINK_COUNT during detection. */ DP_DPCD_QUIRK_NO_SINK_COUNT, + /** +* @DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD: +* +* The device supports MST DSC despite not supporting Virtual DPCD. +* The DSC caps can be read from the physical aux instead. +*/ + DP_DPCD_QUIRK_DSC_WITHOUT_VIRTUAL_DPCD, }; /** -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 01/18] drm/dp_mst: Add PBN calculation for DSC modes
From: David Francis With DSC, bpp can be fractional in multiples of 1/16. Change drm_dp_calc_pbn_mode to reflect this, adding a new parameter bool dsc. When this parameter is true, treat the bpp parameter as having units not of bits per pixel, but 1/16 of a bit per pixel v2: Don't add separate function for this v3: In the equation divide bpp by 16 as it is expected not to leave any remainder Reviewed-by: Manasi Navare Reviewed-by: Lyude Paul Reviewed-by: Harry Wentland Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 +- drivers/gpu/drm/drm_dp_mst_topology.c | 12 +++- drivers/gpu/drm/i915/display/intel_dp_mst.c| 3 ++- drivers/gpu/drm/nouveau/dispnv50/disp.c| 2 +- drivers/gpu/drm/radeon/radeon_dp_mst.c | 2 +- drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c | 10 ++ include/drm/drm_dp_mst_helper.h| 3 +-- 7 files changed, 23 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 455c51c38720..9fc03fc1017d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -4967,7 +4967,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, is_y420); bpp = convert_dc_color_depth_into_bpc(color_depth) * 3; clock = adjusted_mode->clock; - dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp); + dm_new_connector_state->pbn = drm_dp_calc_pbn_mode(clock, bpp, false); } dm_new_connector_state->vcpi_slots = drm_dp_atomic_find_vcpi_slots(state, mst_mgr, diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index ae5809a1f19a..363e7e58e7e7 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -4342,10 +4342,11 @@ EXPORT_SYMBOL(drm_dp_check_act_status); * drm_dp_calc_pbn_mode() - Calculate the PBN for a mode. * @clock: dot clock for the mode * @bpp: bpp for the mode. + * @dsc: DSC mode. If true, bpp has units of 1/16 of a bit per pixel * * This uses the formula in the spec to calculate the PBN value for a mode. */ -int drm_dp_calc_pbn_mode(int clock, int bpp) +int drm_dp_calc_pbn_mode(int clock, int bpp, bool dsc) { /* * margin 5300ppm + 300ppm ~ 0.6% as per spec, factor is 1.006 @@ -4356,7 +4357,16 @@ int drm_dp_calc_pbn_mode(int clock, int bpp) * peak_kbps *= (1006/1000) * peak_kbps *= (64/54) * peak_kbps *= 8convert to bytes +* +* If the bpp is in units of 1/16, further divide by 16. Put this +* factor in the numerator rather than the denominator to avoid +* integer overflow */ + + if (dsc) + return DIV_ROUND_UP_ULL(mul_u32_u32(clock * (bpp / 16), 64 * 1006), + 8 * 54 * 1000 * 1000); + return DIV_ROUND_UP_ULL(mul_u32_u32(clock * bpp, 64 * 1006), 8 * 54 * 1000 * 1000); } diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index 03d1cba0b696..92be17711287 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -61,7 +61,8 @@ static int intel_dp_mst_compute_link_config(struct intel_encoder *encoder, crtc_state->pipe_bpp = bpp; crtc_state->pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock, - crtc_state->pipe_bpp); + crtc_state->pipe_bpp, + false); slots = drm_dp_atomic_find_vcpi_slots(state, &intel_dp->mst_mgr, port, crtc_state->pbn); diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 549486f1d937..1c9e23d5a6fd 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -782,7 +782,7 @@ nv50_msto_atomic_check(struct drm_encoder *encoder, const int bpp = connector->display_info.bpc * 3; const int clock = crtc_state->adjusted_mode.clock; - asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp); + asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp, false); } slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_ms
[PATCH v9 04/18] drm/dp_mst: Fill branch->num_ports
From: David Francis This field on drm_dp_mst_branch was never filled It is initialized to zero when the port is kzallocced. When a port is added to the list, increment num_ports, and when a port is removed from the list, decrement num_ports. v2: remember to decrement on port removal v3: don't explicitly init to 0 v4: move decrement of num_ports to unlink_port function Reviewed-by: Lyude Paul Reviewed-by: Harry Wentland Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- drivers/gpu/drm/drm_dp_mst_topology.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index ba5328cdc853..5a4c2db15c35 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -2157,6 +2157,7 @@ drm_dp_mst_topology_unlink_port(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { mutex_lock(&mgr->lock); + port->parent->num_ports--; list_del(&port->next); mutex_unlock(&mgr->lock); drm_dp_mst_topology_put_port(port); @@ -2256,6 +2257,7 @@ drm_dp_mst_handle_link_address_port(struct drm_dp_mst_branch *mstb, mutex_lock(&mgr->lock); drm_dp_mst_topology_get_port(port); list_add(&port->next, &mstb->ports); + mstb->num_ports++; mutex_unlock(&mgr->lock); } -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v9 09/18] drm/amd/display: Write DSC enable to MST DPCD
From: David Francis Rework the dm_helpers_write_dsc_enable callback to handle the MST case. Use the cached dsc_aux field. Reviewed-by: Wenjing Liu Signed-off-by: David Francis Signed-off-by: Mikita Lipski --- .../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 19 ++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c index 66f266a5e10b..069b7a6f5597 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c @@ -37,6 +37,7 @@ #include "dc.h" #include "amdgpu_dm.h" #include "amdgpu_dm_irq.h" +#include "amdgpu_dm_mst_types.h" #include "dm_helpers.h" @@ -516,8 +517,24 @@ bool dm_helpers_dp_write_dsc_enable( ) { uint8_t enable_dsc = enable ? 1 : 0; + struct amdgpu_dm_connector *aconnector; + + if (!stream) + return false; + + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) { + aconnector = (struct amdgpu_dm_connector *)stream->dm_stream_context; + + if (!aconnector->dsc_aux) + return false; + + return (drm_dp_dpcd_write(aconnector->dsc_aux, DP_DSC_ENABLE, &enable_dsc, 1) >= 0); + } + + if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT) + return dm_helpers_dp_write_dpcd(ctx, stream->link, DP_DSC_ENABLE, &enable_dsc, 1); - return dm_helpers_dp_write_dpcd(ctx, stream->sink->link, DP_DSC_ENABLE, &enable_dsc, 1); + return false; } bool dm_helpers_is_dp_sink_present(struct dc_link *link) -- 2.17.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/4] drm/etnaviv: Use dma_resv locking wrappers
On Mon, Nov 25, 2019 at 10:43:53AM +0100, Daniel Vetter wrote: > I'll add more fancy logic to them soon, so everyone really has to use > them. Plus they already provide some nice additional debug > infrastructure on top of direct ww_mutex usage for the fences tracked > by dma_resv. > > Signed-off-by: Daniel Vetter > Cc: Lucas Stach > Cc: Russell King > Cc: Christian Gmeiner > Cc: etna...@lists.freedesktop.org Ping for some review/acks. Thanks, Daniel > --- > drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 8 +++- > 1 file changed, 3 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > index aa3e4c3b063a..947b21868e72 100644 > --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c > @@ -113,7 +113,7 @@ static void submit_unlock_object(struct > etnaviv_gem_submit *submit, int i) > if (submit->bos[i].flags & BO_LOCKED) { > struct drm_gem_object *obj = &submit->bos[i].obj->base; > > - ww_mutex_unlock(&obj->resv->lock); > + dma_resv_unlock(obj->resv); > submit->bos[i].flags &= ~BO_LOCKED; > } > } > @@ -133,8 +133,7 @@ static int submit_lock_objects(struct etnaviv_gem_submit > *submit, > contended = i; > > if (!(submit->bos[i].flags & BO_LOCKED)) { > - ret = ww_mutex_lock_interruptible(&obj->resv->lock, > - ticket); > + ret = dma_resv_lock(obj->resv, ticket); > if (ret == -EALREADY) > DRM_ERROR("BO at index %u already on submit > list\n", > i); > @@ -161,8 +160,7 @@ static int submit_lock_objects(struct etnaviv_gem_submit > *submit, > obj = &submit->bos[contended].obj->base; > > /* we lost out in a seqno race, lock and retry.. */ > - ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock, > -ticket); > + ret = dma_resv_lock_slow_interruptible(obj->resv, ticket); > if (!ret) { > submit->bos[contended].flags |= BO_LOCKED; > slow_locked = contended; > -- > 2.24.0 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 3/4] drm/msm: Use dma_resv locking wrappers
On Mon, Nov 25, 2019 at 10:43:55AM +0100, Daniel Vetter wrote: > I'll add more fancy logic to them soon, so everyone really has to use > them. Plus they already provide some nice additional debug > infrastructure on top of direct ww_mutex usage for the fences tracked > by dma_resv. > > Signed-off-by: Daniel Vetter > Cc: Rob Clark > Cc: Sean Paul > Cc: linux-arm-...@vger.kernel.org > Cc: freedr...@lists.freedesktop.org Ping for some review/acks. Thanks, Daniel > --- > drivers/gpu/drm/msm/msm_gem_submit.c | 10 +- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c > b/drivers/gpu/drm/msm/msm_gem_submit.c > index 7d04c47d0023..385d4965a8d0 100644 > --- a/drivers/gpu/drm/msm/msm_gem_submit.c > +++ b/drivers/gpu/drm/msm/msm_gem_submit.c > @@ -157,7 +157,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit > *submit, > msm_gem_unpin_iova(&msm_obj->base, submit->aspace); > > if (submit->bos[i].flags & BO_LOCKED) > - ww_mutex_unlock(&msm_obj->base.resv->lock); > + dma_resv_unlock(msm_obj->base.resv); > > if (backoff && !(submit->bos[i].flags & BO_VALID)) > submit->bos[i].iova = 0; > @@ -180,8 +180,8 @@ static int submit_lock_objects(struct msm_gem_submit > *submit) > contended = i; > > if (!(submit->bos[i].flags & BO_LOCKED)) { > - ret = > ww_mutex_lock_interruptible(&msm_obj->base.resv->lock, > - &submit->ticket); > + ret = dma_resv_lock_interruptible(msm_obj->base.resv, > + &submit->ticket); > if (ret) > goto fail; > submit->bos[i].flags |= BO_LOCKED; > @@ -202,8 +202,8 @@ static int submit_lock_objects(struct msm_gem_submit > *submit) > if (ret == -EDEADLK) { > struct msm_gem_object *msm_obj = submit->bos[contended].obj; > /* we lost out in a seqno race, lock and retry.. */ > - ret = > ww_mutex_lock_slow_interruptible(&msm_obj->base.resv->lock, > - &submit->ticket); > + ret = dma_resv_lock_slow_interruptible(msm_obj->base.resv, > +&submit->ticket); > if (!ret) { > submit->bos[contended].flags |= BO_LOCKED; > slow_locked = contended; > -- > 2.24.0 > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 03/10] drm/atmel: plane_state->fb iff plane_state->crtc
Hi Daniel. On Fri, Dec 13, 2019 at 06:26:05PM +0100, Daniel Vetter wrote: > Checking both is one too much, so wrap a WARN_ON around it to stope > the copypasta. > > Signed-off-by: Daniel Vetter > Cc: Sam Ravnborg > Cc: Boris Brezillon > Cc: Nicolas Ferre > Cc: Alexandre Belloni > Cc: Ludovic Desroches > Cc: linux-arm-ker...@lists.infradead.org Applied to drm-misc-next. Looked through the whole series: Acked-by: Sam Ravnborg ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] udmabuf: fix dma-buf cpu access
I'm just going to put Chia's review comment here since it sums the issue rather nicely: "(1) Semantically, a dma-buf is in DMA domain. CPU access from the importer must be surrounded by {begin,end}_cpu_access. This gives the exporter a chance to move the buffer to the CPU domain temporarily. (2) When the exporter itself has other means to do CPU access, it is only reasonable for the exporter to move the buffer to the CPU domain before access, and to the DMA domain after access. The exporter can potentially reuse {begin,end}_cpu_access for that purpose. Because of (1), udmabuf does need to implement the {begin,end}_cpu_access hooks. But "begin" should mean dma_sync_sg_for_cpu and "end" should mean dma_sync_sg_for_device. Because of (2), if userspace wants to continuing accessing through the memfd mapping, it should call udmabuf's {begin,end}_cpu_access to avoid cache issues." Reported-by: Chia-I Wu Suggested-by: Chia-I Wu Fixes: 284562e1f34 ("udmabuf: implement begin_cpu_access/end_cpu_access hooks") --- drivers/dma-buf/udmabuf.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 61b0a2cff874..acb26c627d27 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -122,9 +122,8 @@ static int begin_cpu_udmabuf(struct dma_buf *buf, if (IS_ERR(ubuf->sg)) return PTR_ERR(ubuf->sg); } else { - dma_sync_sg_for_device(dev, ubuf->sg->sgl, - ubuf->sg->nents, - direction); + dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, + direction); } return 0; @@ -139,7 +138,7 @@ static int end_cpu_udmabuf(struct dma_buf *buf, if (!ubuf->sg) return -EINVAL; - dma_sync_sg_for_cpu(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); + dma_sync_sg_for_device(dev, ubuf->sg->sgl, ubuf->sg->nents, direction); return 0; } -- 2.24.1.735.g03f4e72817-goog ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 02/12] drm/i915: Clear the repeater bit on HDCP disable
On Fri, Dec 13, 2019 at 03:59:02PM +0530, Ramalingam C wrote: > On 2019-12-12 at 14:02:20 -0500, Sean Paul wrote: > > From: Sean Paul > > > > On HDCP disable, clear the repeater bit. This ensures if we connect a > > non-repeater sink after a repeater, the bit is in the state we expect. > > > > Fixes: ee5e5e7a5e0f ("drm/i915: Add HDCP framework + base implementation") > > Cc: Chris Wilson > > Cc: Ramalingam C > > Cc: Daniel Vetter > > Cc: Sean Paul > > Cc: Jani Nikula > > Cc: Joonas Lahtinen > > Cc: Rodrigo Vivi > > Cc: intel-...@lists.freedesktop.org > > Cc: # v4.17+ > > Signed-off-by: Sean Paul > > > > Changes in v2: > > -Added to the set > > --- > > drivers/gpu/drm/i915/display/intel_hdcp.c | 5 + > > 1 file changed, 5 insertions(+) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c > > b/drivers/gpu/drm/i915/display/intel_hdcp.c > > index eaab9008feef..c4394c8e10eb 100644 > > --- a/drivers/gpu/drm/i915/display/intel_hdcp.c > > +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c > > @@ -773,6 +773,7 @@ static int _intel_hdcp_disable(struct intel_connector > > *connector) > > struct intel_digital_port *intel_dig_port = conn_to_dig_port(connector); > > enum port port = intel_dig_port->base.port; > > enum transcoder cpu_transcoder = hdcp->cpu_transcoder; > > + u32 repeater_ctl; > > int ret; > > > > DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n", > > @@ -787,6 +788,10 @@ static int _intel_hdcp_disable(struct intel_connector > > *connector) > > return -ETIMEDOUT; > > } > > > > + repeater_ctl = intel_hdcp_get_repeater_ctl(dev_priv, cpu_transcoder, > > + port); > > + I915_WRITE(HDCP_REP_CTL, I915_READ(HDCP_REP_CTL) & ~repeater_ctl); > Do you think it will help to (double) clear HDCP_REP_CTL when detect a > sink which is non repeater!? But yes disable will be executed on all > HDCP exits. > Yeah, that's probably a better idea. I was a little undecided on where to put it and I think I settled on the disable path since that matches the way we handle HDCP signalling. However if we always write REP_CTL, that cuts our callsites back down to 1, which seems like a Good Thing. Will revise. Sean > > + > LGTM > > Reviewed-by: Ramalingam C > > > ret = hdcp->shim->toggle_signalling(intel_dig_port, false); > > if (ret) { > > DRM_ERROR("Failed to disable HDCP signalling\n"); > > -- > > Sean Paul, Software Engineer, Google / Chromium OS > > -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 07/12] drm/i915: Protect workers against disappearing connectors
On Fri, Dec 13, 2019 at 04:40:33PM +0530, Ramalingam C wrote: > On 2019-12-12 at 14:02:25 -0500, Sean Paul wrote: > > From: Sean Paul > > > > This patch adds some protection against connectors being destroyed > > before the HDCP workers are finished. > > > > For check_work, we do a synchronous cancel after the connector is > > unregistered which will ensure that it is finished before destruction. > > > > In the case of prop_work, we can't do a synchronous wait since it needs > > to take connection_mutex which could cause deadlock. Instead, we'll take > > a reference on the connector when scheduling prop_work and give it up > > once we're done. > > > > Signed-off-by: Sean Paul > Will there be an instance where prop_work is scheduled but before > execution cancelled from the queue itself? This will leak the connector > reference. No, prop_work is really quite simple, it just grabs some locks and updates the property value. > > Atleast hdcp stack is not requesting for such action. So Looks good to me. > > Reviewed-by: Ramalingam C Thanks, I'm going to dig into what we should do when hdcp_cleanup is called from connector_init failure paths and revise this patch. > > > > Changes in v2: > > - Added to the set > > --- > > drivers/gpu/drm/i915/display/intel_hdcp.c | 38 --- > > 1 file changed, 33 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c > > b/drivers/gpu/drm/i915/display/intel_hdcp.c > > index 798e7e1a19fc..c79dca2c74d1 100644 > > --- a/drivers/gpu/drm/i915/display/intel_hdcp.c > > +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c > > @@ -863,8 +863,10 @@ static void intel_hdcp_update_value(struct > > intel_connector *connector, > > return; > > > > hdcp->value = value; > > - if (update_property) > > + if (update_property) { > > + drm_connector_get(&connector->base); > > schedule_work(&hdcp->prop_work); > > + } > > } > > > > /* Implements Part 3 of the HDCP authorization procedure */ > > @@ -954,6 +956,8 @@ static void intel_hdcp_prop_work(struct work_struct > > *work) > > > > mutex_unlock(&hdcp->mutex); > > drm_modeset_unlock(&dev->mode_config.connection_mutex); > > + > > + drm_connector_put(&connector->base); > > } > > > > bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port) > > @@ -1802,6 +1806,9 @@ static void intel_hdcp_check_work(struct work_struct > > *work) > >check_work); > > struct intel_connector *connector = intel_hdcp_to_connector(hdcp); > > > > + if (drm_connector_is_unregistered(&connector->base)) > > + return; > > + > > if (!intel_hdcp2_check_link(connector)) > > schedule_delayed_work(&hdcp->check_work, > > DRM_HDCP2_CHECK_PERIOD_MS); > > @@ -2076,12 +2083,33 @@ void intel_hdcp_component_fini(struct > > drm_i915_private *dev_priv) > > > > void intel_hdcp_cleanup(struct intel_connector *connector) > > { > > - if (!connector->hdcp.shim) > > + struct intel_hdcp *hdcp = &connector->hdcp; > > + > > + if (!hdcp->shim) > > return; > > > > - mutex_lock(&connector->hdcp.mutex); > > - kfree(connector->hdcp.port_data.streams); > > - mutex_unlock(&connector->hdcp.mutex); > > + WARN_ON(!drm_connector_is_unregistered(&connector->base)); > > + > > + /* > > +* Now that the connector is unregistered, check_work won't be run, but > > +* cancel any outstanding instances of it > > +*/ > > + cancel_delayed_work_sync(&hdcp->check_work); > > + > > + /* > > +* We don't cancel prop_work in the same way as check_work since it > > +* requires connection_mutex which could be held while calling this > > +* function. Instead, we rely on the connector references grabbed before > > +* scheduling prop_work to ensure the connector is alive when prop_work > > +* is run. So if we're in the destroy path (which is where this > > +* function should be called), we're "guaranteed" that prop_work is not > > +* active (tl;dr This Should Never Happen). > > +*/ > > + WARN_ON(work_pending(&hdcp->prop_work)); > > + > > + mutex_lock(&hdcp->mutex); > > + kfree(hdcp->port_data.streams); > > + mutex_unlock(&hdcp->mutex); > > } > > > > void intel_hdcp_atomic_check(struct drm_connector *connector, > > -- > > Sean Paul, Software Engineer, Google / Chromium OS > > -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 08/12] drm/i915: Don't fully disable HDCP on a port if multiple pipes are using it
On Fri, Dec 13, 2019 at 05:28:25PM +0530, Ramalingam C wrote: > On 2019-12-12 at 14:02:26 -0500, Sean Paul wrote: > > From: Sean Paul > > > > This patch is required for HDCP over MST. If a port is being used for > > multiple HDCP streams, we don't want to fully disable HDCP on a port if > > one of them is disabled. Instead, we just disable the HDCP signalling on > > that particular pipe and exit early. The last pipe to disable HDCP will > > also bring down HDCP on the port. > Sean, Hey Ram, Thanks for the quick reviews! > > We have a complication here. till ICL this will work as the HDCP > instance is port based. But from TGL, HDCP is transcoder based. > > We need to handle MST HDCP enable and disable differently for <=gen11 and > >gen11. > > > > In order to achieve this, we need to keep a refcount in intel_digital_port > > and protect it using a new hdcp_mutex. > > > > Signed-off-by: Sean Paul > > Link: > > https://patchwork.freedesktop.org/patch/msgid/20191203173638.94919-8-s...@poorly.run > > #v1 > > > > Changes in v2: > > - Move the toggle_signalling call into _intel_hdcp_disable so it's called > > from check_work > > --- /snip > > --- a/drivers/gpu/drm/i915/display/intel_dp.c > > +++ b/drivers/gpu/drm/i915/display/intel_dp.c > > @@ -7580,6 +7580,8 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, > > intel_encoder = &intel_dig_port->base; > > encoder = &intel_encoder->base; > > > > + mutex_init(&intel_dig_port->hdcp_mutex); > its initialized at ddi_init itself. I thought it would be safer to initialize the mutex for non-ddi based DP and HDMI encoders as well. > > + > > if (drm_encoder_init(&dev_priv->drm, &intel_encoder->base, > > &intel_dp_enc_funcs, DRM_MODE_ENCODER_TMDS, > > "DP %c", port_name(port))) > > diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c > > b/drivers/gpu/drm/i915/display/intel_hdcp.c > > index c79dca2c74d1..fbbd4da7c491 100644 > > --- a/drivers/gpu/drm/i915/display/intel_hdcp.c > > +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c > > @@ -779,6 +779,19 @@ static int _intel_ > hdcp_disable(struct intel_connector *connector) > > DRM_DEBUG_KMS("[%s:%d] HDCP is being disabled...\n", > > connector->base.name, connector->base.base.id); > > > > + /* > > +* If there are other connectors on this port using HDCP, don't disable > > +* it. Instead, toggle the HDCP signalling off on that particular > > +* connector/pipe and exit. > > +*/ > > + if (intel_dig_port->num_hdcp_streams > 0) { > > + ret = hdcp->shim->toggle_signalling(intel_dig_port, > > + cpu_transcoder, false); > > + if (ret) > > + DRM_ERROR("Failed to disable HDCP signalling\n"); > > + return ret; > > + } > This wont work for TGL+, where HDCP instance is transcoder based. we > need to disable the HDCP per stream for TGL+ Hmm, I'm not sure how that would work for MST. Presumably you would still have one port, but multiple transcoders feeding into it? Any chance you could send me a bspec for HDMI on TGL+ so I can make adjustments? :-) I also don't have any TGL hardware at my disposal, but hopefully soon. Sean > > + /snip > > diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c > > b/drivers/gpu/drm/i915/display/intel_hdmi.c > > index 5066efadca85..905b188782ed 100644 > > --- a/drivers/gpu/drm/i915/display/intel_hdmi.c > > +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c > > @@ -3247,6 +3247,8 @@ void intel_hdmi_init(struct drm_i915_private > > *dev_priv, > > > > intel_encoder = &intel_dig_port->base; > > > > + mutex_init(&intel_dig_port->hdcp_mutex); > its initialized at ddi_init itself. > > -Ram > > + > > drm_encoder_init(&dev_priv->drm, &intel_encoder->base, > > &intel_hdmi_enc_funcs, DRM_MODE_ENCODER_TMDS, > > "HDMI %c", port_name(port)); > > -- > > Sean Paul, Software Engineer, Google / Chromium OS > > -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3] drm: Funnel drm logs to tracepoints
On Fri, Dec 13, 2019 at 11:54:36AM -0500, Steven Rostedt wrote: > On Fri, 13 Dec 2019 11:47:03 -0500 > Sean Paul wrote: > > > > Why is there a separate trace event for each of these? > > > > > > > To make it easier on userspace to enable just a single drm category. > > > > But trace events can easily be filtered. Say you have a field called > category, you could then just set in the trace event filter: > > echo 'category == 1 || category == 5 || (category > 8 && category < 12)' > > /sys/kernel/tracing/drm_print/drm_category_log/filter > echo 1 > /sys/kernel/tracing/drm_print/drm_category_log/enable Hmm, true. I suppose the only downside would be that this would cause all logs to be processed/assigned as trace events before the filter is applied. That's a lot of extra work each frame. Sean > > -- Steve -- Sean Paul, Software Engineer, Google / Chromium OS ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/panel: Add Boe Himax8279d MIPI-DSI LCD panel
Hi Jerry. Thanks! On Thu, Dec 12, 2019 at 07:52:08PM +0800, Jerry Han wrote: > Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI > panel. > > V11: > - Use the backlight support in drm_panel to simplify the driver (Sam) ... > - Support Boe Himax8279d 8.0" 1200x1920 TFT LCD panel, it is a MIPI DSI > panel. > > Signed-off-by: Jerry Han > Reviewed-by: Sam Ravnborg > Reviewed-by: Derek Basehore > Reviewed-by: Emil Velikov > Reported-by: kbuild test robot > Cc: Jitao Shi > Cc: Rock wang > --- Applied to drm-misc-next with the following changes: - fix build in boe_panel_get_modes() - fix backlight - drm_panel_of_backlight() must be called after drm_panel_init() Sam diff --git a/drivers/gpu/drm/panel/panel-boe-himax8279d.c b/drivers/gpu/drm/panel/panel-boe-himax8279d.c index 3a6ee2069158..74d58ee7d04c 100644 --- a/drivers/gpu/drm/panel/panel-boe-himax8279d.c +++ b/drivers/gpu/drm/panel/panel-boe-himax8279d.c @@ -219,26 +219,27 @@ static int boe_panel_enable(struct drm_panel *panel) return 0; } -static int boe_panel_get_modes(struct drm_panel *panel) +static int boe_panel_get_modes(struct drm_panel *panel, + struct drm_connector *connector) { struct panel_info *pinfo = to_panel_info(panel); const struct drm_display_mode *m = pinfo->desc->display_mode; struct drm_display_mode *mode; - mode = drm_mode_duplicate(panel->drm, m); + mode = drm_mode_duplicate(connector->dev, m); if (!mode) { - DRM_DEV_ERROR(panel->drm->dev, "failed to add mode %ux%u@%u\n", + DRM_DEV_ERROR(pinfo->base.dev, "failed to add mode %ux%u@%u\n", m->hdisplay, m->vdisplay, m->vrefresh); return -ENOMEM; } drm_mode_set_name(mode); - drm_mode_probed_add(panel->connector, mode); + drm_mode_probed_add(connector, mode); - panel->connector->display_info.width_mm = pinfo->desc->width_mm; - panel->connector->display_info.height_mm = pinfo->desc->height_mm; - panel->connector->display_info.bpc = pinfo->desc->bpc; + connector->display_info.width_mm = pinfo->desc->width_mm; + connector->display_info.height_mm = pinfo->desc->height_mm; + connector->display_info.bpc = pinfo->desc->bpc; return 1; } @@ -888,13 +889,13 @@ static int panel_add(struct panel_info *pinfo) return ret; } + drm_panel_init(&pinfo->base, dev, &panel_funcs, + DRM_MODE_CONNECTOR_DSI); + ret = drm_panel_of_backlight(&pinfo->base); if (ret) return ret; - drm_panel_init(&pinfo->base, dev, &panel_funcs, - DRM_MODE_CONNECTOR_DSI); - return drm_panel_add(&pinfo->base); } ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 10/12] arm64: dts: rockchip: Add PX30 CRTCs graph LVDS endpoints
Hi Miquel, Am Freitag, 13. Dezember 2019, 19:10:49 CET schrieb Miquel Raynal: > Add the display subsystem routes with the two available CRTCs: vopb > and vopl (big and little). For each CRTC, add the LVDS endpoints. MIPI > DSI endpoints will come later. > > Signed-off-by: Miquel Raynal > --- > arch/arm64/boot/dts/rockchip/px30.dtsi | 20 > 1 file changed, 20 insertions(+) > > diff --git a/arch/arm64/boot/dts/rockchip/px30.dtsi > b/arch/arm64/boot/dts/rockchip/px30.dtsi > index b2af0f02ecbe..1c96ba556daf 100644 > --- a/arch/arm64/boot/dts/rockchip/px30.dtsi > +++ b/arch/arm64/boot/dts/rockchip/px30.dtsi > @@ -190,6 +190,16 @@ > compatible = "rockchip,display-subsystem"; > ports = <&vopb_out>, <&vopl_out>; > status = "disabled"; > + > + route { > + route_vopb_lvds: route-vopb-lvds { > + connect = <&vopb_out_lvds>; > + }; > + > + route_vopl_lvds: route-vopl-lvds { > + connect = <&vopl_out_lvds>; > + }; > + }; where does this route-stuff come from? The vendor tree? Because so far I've not seen this in mainline-drm in general nor the Rockchip drm driver itself. > }; > > gmac_clkin: external-gmac-clock { > @@ -976,6 +986,11 @@ > vopb_out: port { > #address-cells = <1>; > #size-cells = <0>; > + > + vopb_out_lvds: endpoint@0 { > + reg = <0>; > + remote-endpoint = <&lvds_vopb_in>; > + }; This (and the one below) would create dangling phandle references and compile errors, because the referenced phandles only get introduced in patch12. So ideally merge this into the last patch. Heiko > }; > }; > > @@ -1008,6 +1023,11 @@ > vopl_out: port { > #address-cells = <1>; > #size-cells = <0>; > + > + vopl_out_lvds: endpoint@0 { > + reg = <0>; > + remote-endpoint = <&lvds_vopl_in>; > + }; > }; > }; > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm: rcar-du: lvds: Get mode from state
The R-Car LVDS encoder driver implements the bridge .mode_set() operation for the sole purpose of storing the mode in the LVDS private data, to be used later when enabling the encoder. Switch to the bridge .atomic_enable() and .atomic_disable() operations in order to access the global atomic state, and get the mode from the state instead. Remove both the unneeded .mode_set() operation and the display_mode and mode fields storing state data from the rcar_lvds private structure. As a side effect we get the CRTC from the state, replace the CRTC pointer retrieved through the bridge's encoder that shouldn't be used by atomic drivers. Signed-off-by: Laurent Pinchart --- Changes since v1: - Call .atomic_enable() on the companion - Set companion->encoder in .attach() The patch has been tested on the Draak board with the HDMI output in LVDS dual-link mode, and on the Salvator-XS board with the HDMI, VGA and LVDS outputs in single-link mode. --- drivers/gpu/drm/rcar-du/rcar_lvds.c | 158 +++- 1 file changed, 85 insertions(+), 73 deletions(-) diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index 8c6c172bbf2e..c550bfd59e71 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -65,9 +65,6 @@ struct rcar_lvds { struct clk *dotclkin[2];/* External DU clocks */ } clocks; - struct drm_display_mode display_mode; - enum rcar_lvds_mode mode; - struct drm_bridge *companion; bool dual_link; }; @@ -402,10 +399,51 @@ EXPORT_SYMBOL_GPL(rcar_lvds_clk_disable); * Bridge */ -static void rcar_lvds_enable(struct drm_bridge *bridge) +static enum rcar_lvds_mode rcar_lvds_get_lvds_mode(struct rcar_lvds *lvds, + const struct drm_connector *connector) +{ + const struct drm_display_info *info; + enum rcar_lvds_mode mode; + + /* +* There is no API yet to retrieve LVDS mode from a bridge, only panels +* are supported. +*/ + if (!lvds->panel) + return RCAR_LVDS_MODE_JEIDA; + + info = &connector->display_info; + if (!info->num_bus_formats || !info->bus_formats) { + dev_err(lvds->dev, "no LVDS bus format reported\n"); + return RCAR_LVDS_MODE_JEIDA; + } + + switch (info->bus_formats[0]) { + case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG: + case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA: + mode = RCAR_LVDS_MODE_JEIDA; + break; + case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG: + mode = RCAR_LVDS_MODE_VESA; + break; + default: + dev_err(lvds->dev, "unsupported LVDS bus format 0x%04x\n", + info->bus_formats[0]); + return RCAR_LVDS_MODE_JEIDA; + } + + if (info->bus_flags & DRM_BUS_FLAG_DATA_LSB_TO_MSB) + mode |= RCAR_LVDS_MODE_MIRROR; + + return mode; +} + +static void rcar_lvds_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct rcar_lvds *lvds = bridge_to_rcar_lvds(bridge); - const struct drm_display_mode *mode = &lvds->display_mode; + struct drm_connector *connector; + struct drm_crtc *crtc; u32 lvdhcr; u32 lvdcr0; int ret; @@ -414,9 +452,14 @@ static void rcar_lvds_enable(struct drm_bridge *bridge) if (ret < 0) return; + /* Retrieve the connector and CRTC through the atomic state. */ + connector = drm_atomic_get_new_connector_for_encoder(state, +bridge->encoder); + crtc = drm_atomic_get_new_connector_state(state, connector)->crtc; + /* Enable the companion LVDS encoder in dual-link mode. */ if (lvds->dual_link && lvds->companion) - lvds->companion->funcs->enable(lvds->companion); + lvds->companion->funcs->atomic_enable(lvds->companion, state); /* * Hardcode the channels and control signals routing for now. @@ -452,18 +495,20 @@ static void rcar_lvds_enable(struct drm_bridge *bridge) * PLL clock configuration on all instances but the companion in * dual-link mode. */ - if (!lvds->dual_link || lvds->companion) + if (!lvds->dual_link || lvds->companion) { + const struct drm_crtc_state *crtc_state = + drm_atomic_get_new_crtc_state(state, crtc); + const struct drm_display_mode *mode = + &crtc_state->adjusted_mode; + lvds->info->pll_setup(lvds, mode->clock * 1000); + } /* Set the LVDS mode and select the input. */ - lvdcr0 = lvds->mode << LVDCR0_LVMD_SHIFT; + lvdcr0 = rcar_lvds_get_lvds_mode(lvds, connector) << LVDCR0_LVMD_SHIFT; if (lvds->bridge.encoder)