drm/exynos: fimd: vrefresh is zero
Hello, while playing around with FIMD enabled, I noticed that when first using the device a zero division was triggered in fimd_calc_clkdiv(). I remembered that I had a similar issue some time ago. I added a stub fimd_atomic_check() which shows that vrefresh is zero when fimd_calc_clkdiv() is called. [ 164.059361] [drm:exynos_plane_mode_set] plane : offset_x/y(0,0), width/height(1366,768) [ 164.067175] [drm:fimd_atomic_check] xres=1366, yres=768, refresh=0, intl=0 [ 164.074198] [drm:drm_atomic_helper_check_planes] [CRTC:24:crtc-0] atomic driver check failed I went back to the git log and noticed that some time ago in 50bbfbffa5c894def440ce8157dfe53e60960d35 the fimd_mode_fixup() call was removed. I'm now wondering where exactly vrefresh is set to a sane value. As far as I can see of_get_videomode() is used to fetch the video mode from the DT, and drm_display_mode_from_videomode() is used to convert it. However vrefresh is nowhere set. So is something broken here, or am I missing something? With best wishes, Tobias
[RFC 0/2] New feature: Framebuffer processors
Hey Marek, I had a quick look at the series and I really like the new approach. I was wondering about the following though. If I understand this correctly I can only perform m2m operations on buffers which are registered as framebuffers. Is this possible to weaken that requirements such that arbitrary GEM objects can be used as input and output? Anyway, great work! With best wishes, Tobias Marek Szyprowski wrote: > Dear all, > > This is the initial proposal for extending DRM API with generic support for > hardware modules, which can be used for processing image data from the one > memory buffer to another. Typical memory-to-memory operations are: > rotation, scaling, colour space conversion or mix of them. In this proposal > I named such hardware modules a framebuffer processors. > > Embedded SoCs are known to have a number of hardware blocks, which perform > such operations. They can be used in paralel to the main GPU module to > offload CPU from processing grapics or video data. One of example use of > such modules is implementing video overlay, which usually requires color > space conversion from NV12 (or similar) to RGB32 color space and scaling to > target window size. > > Till now there was no generic, hardware independent API for performing such > operations. Exynos DRM driver has its own custom extension called IPP > (Image Post Processing), but frankly speaking, it is over-engineered and not > really used in open-source. I didn't indentify similar API in other DRM > drivers, besides those which expose complete support for the whole GPU. > > However, the need for commmon API has been already mentioned on the mailing > list. Here are some example threads: > 1. "RFC: hardware accelerated bitblt using dma engine" > http://www.spinics.net/lists/dri-devel/msg114250.html > 2. "[PATCH 00/25] Exynos DRM: new life of IPP (Image Post Processing) > subsystem" > https://lists.freedesktop.org/archives/dri-devel/2015-November/094115.html > https://lists.freedesktop.org/archives/dri-devel/2015-November/094533.html > > The proposed API is heavily inspired by atomic KMS approach - it is also > based on DRM objects and their properties. A new DRM object is introduced: > framebuffer processor (called fbproc for convenience). Such fbproc objects > have a set of standard DRM properties, which describes the operation to be > performed by respective hardware module. In typical case those properties > are a source fb id and rectangle (x, y, width, height) and destination fb > id and rectangle. Optionally a rotation property can be also specified if > supported by the given hardware. To perform an operation on image data, > userspace provides a set of properties and their values for given fbproc > object in a similar way as object and properties are provided for > performing atomic page flip / mode setting. > > The proposed API consists of the 3 new ioctls: > - DRM_IOCTL_MODE_GETFBPROCRESOURCES: to enumerate all available fbproc > objects, > - DRM_IOCTL_MODE_GETFBPROC: to query capabilities of given fbproc object, > - DRM_IOCTL_MODE_FBPROC: to perform operation described by given property > set. > > The proposed API is extensible. Drivers can attach their own, custom > properties to add support for more advanced picture processing (for example > blending). > > Please note that this API is intended to be used for simple memory-to-memory > image processing hardware not the full-blown GPU blitters, which usually > have more features. Typically blitters provides much more operations beside > simple pixel copying and operate best if its command queue is controlled from > respective dedicated code in userspace. > > The patchset consist of 4 parts: > 1. generic code for DRM core for handling fbproc objects and ioctls > 2. example, quick conversion of Exynos Rotator driver to fbproc API > 3. libdrm extensions for handling fbproc objects > 4. simple example of userspace code for performing 180 degree rotation of the >framebuffer > > Patches were tested on Exynos 4412-based Odroid U3 board, on top > of Linux v4.8-rc1 kernel. > > TODO: > 1. agree on the API shape > 2. add more documentation, especially to the kernel docs > 3. add more userspace examples > > Best regards > Marek Szyprowski > Samsung R&D Institute Poland > > > Marek Szyprowski (2): > drm: add support for framebuffer processor objects > drm/exynos: register rotator as fbproc instead of custom ipp framework > > drivers/gpu/drm/Makefile| 3 +- > drivers/gpu/drm/drm_atomic.c| 5 + > drivers/gpu/drm/drm_crtc.c | 6 + > drivers/gpu/drm/drm_crtc_internal.h | 12 + > drivers/gpu/drm/drm_fbproc.c| 754 > > drivers/gpu/drm/drm_ioctl.c | 3 + > drivers/gpu/drm/exynos/Kconfig | 1 - > drivers/gpu/drm/exynos/exynos_drm_drv.c | 3 +- > drivers/gpu/drm/exynos/exynos_drm_rotator.c | 353 +++--
[RFC 0/2] New feature: Framebuffer processors
Hello Marek, Marek Szyprowski wrote: > Dear Tobias > > > On 2016-08-22 12:07, Tobias Jakobi wrote: >> Hey Marek, >> >> I had a quick look at the series and I really like the new approach. >> >> I was wondering about the following though. If I understand this >> correctly I can only perform m2m operations on buffers which are >> registered as framebuffers. Is this possible to weaken that requirements >> such that arbitrary GEM objects can be used as input and output? > > Thanks for you comment. > > I'm open for discussion if the API should be based on framebuffers or > GEM objects. > > Initially I thought that GEM objects would be enough, but later I > noticed that in such case user would need to provide at least width, > height, stride, start offset and pixel format - all parameters that > are already used to create framebuffer object. Operating on GEM > buffers will also make support for images composed from multiple > buffers (like separate GEM objects for luma/chroma parts in case of > planar formats) a bit harder. Same about already introduced API for > fb-modifiers. I just don't want to duplicate all of it in fbproc API. yes, that makes perfectly sense. Passing the buffer parameters (geometry, pixel format, etc.) each time is probably not a good (and efficient) idea. I'm still wondering if there can't arise a situation where I simply can't register a buffer as framebuffer. I'm specifically looking at internal_framebuffer_create() and the driver specific fb_create(). Now internal_framebuffer_create() itself only does some minimal checking, but e.g. it does check against certain minimum/maximum geometry parameters. How do we know that these parameters match the ones for the block that performs the m2m operations? I could image that a block could perform scaling operations on buffers with a much larger geometry than the core allows to bind as framebuffers. So if I have such a buffer with large geometry I might want to scale it down, so that I can display it. But that's not possible since I can't even bind the src as fb. Does that make sense? With best wishes, Tobias > Operating on framebuffer objects also helps to reduce errors in > userspace. One can already queue the result of processing to the > display hardware and this way avoid common issues related to debugging > why the processed image is not displayed correctly due to incorrectly > defined pitch/fourcc/start offset/etc. This is however not really a > strong advantage of framebuffers. > > >> >> Anyway, great work! >> >> With best wishes, >> Tobias >> >> >> Marek Szyprowski wrote: >>> Dear all, >>> >>> This is the initial proposal for extending DRM API with generic >>> support for >>> hardware modules, which can be used for processing image data from >>> the one >>> memory buffer to another. Typical memory-to-memory operations are: >>> rotation, scaling, colour space conversion or mix of them. In this >>> proposal >>> I named such hardware modules a framebuffer processors. >>> >>> Embedded SoCs are known to have a number of hardware blocks, which >>> perform >>> such operations. They can be used in paralel to the main GPU module to >>> offload CPU from processing grapics or video data. One of example use of >>> such modules is implementing video overlay, which usually requires color >>> space conversion from NV12 (or similar) to RGB32 color space and >>> scaling to >>> target window size. >>> >>> Till now there was no generic, hardware independent API for >>> performing such >>> operations. Exynos DRM driver has its own custom extension called IPP >>> (Image Post Processing), but frankly speaking, it is over-engineered >>> and not >>> really used in open-source. I didn't indentify similar API in other DRM >>> drivers, besides those which expose complete support for the whole GPU. >>> >>> However, the need for commmon API has been already mentioned on the >>> mailing >>> list. Here are some example threads: >>> 1. "RFC: hardware accelerated bitblt using dma engine" >>> http://www.spinics.net/lists/dri-devel/msg114250.html >>> 2. "[PATCH 00/25] Exynos DRM: new life of IPP (Image Post Processing) >>> subsystem" >>> https://lists.freedesktop.org/archives/dri-devel/2015-November/094115.html >>> >>> https://lists.freedesktop.org/archives/dri-devel/2015-November/094533.html >>> >>> >>> The proposed API is heavily inspired by atomic KM
[PATCH] exynos-drm: Fix error messages to print flags and size
Hello, I think this patch was never picked up. So just a short 'ping' from my side. With best wishes, Tobias Shuah Khan wrote: > Fix exynos_drm_gem_create() error messages to include flags and size when > flags and size are invalid. > > Signed-off-by: Shuah Khan > --- > drivers/gpu/drm/exynos/exynos_drm_gem.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c > b/drivers/gpu/drm/exynos/exynos_drm_gem.c > index cdf9f1a..4c4cb0e 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c > @@ -231,12 +231,12 @@ struct exynos_drm_gem *exynos_drm_gem_create(struct > drm_device *dev, > int ret; > > if (flags & ~(EXYNOS_BO_MASK)) { > - DRM_ERROR("invalid flags.\n"); > + DRM_ERROR("invalid GEM buffer flags: %u\n", flags); > return ERR_PTR(-EINVAL); > } > > if (!size) { > - DRM_ERROR("invalid size.\n"); > + DRM_ERROR("invalid GEM buffer size: %lu\n", size); > return ERR_PTR(-EINVAL); > } > >
[patch] drm/exynos: fix a timeout loop
Hello Dan, sorry for the blunder! Patch looks good to me. Reviewed-by: Tobias Jakobi With best wishes, Tobias Dan Carpenter wrote: > We were trying to print an error message if we timed out here, but the > loop actually ends with "tries" set to UINT_MAX and not zero. Fix this > by changing from tries-- to --tries. > > A for loop would actually be the most natural way to do this. My fix > means we only loop 99 times instead of 100 but that's probably ok. > > Fixes: a696394c5224 ('drm/exynos: mixer: simplify loop in vp_win_reset()') > Signed-off-by: Dan Carpenter > > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c > b/drivers/gpu/drm/exynos/exynos_mixer.c > index edb20a3..fcc7e4f 100644 > --- a/drivers/gpu/drm/exynos/exynos_mixer.c > +++ b/drivers/gpu/drm/exynos/exynos_mixer.c > @@ -701,7 +701,7 @@ static void vp_win_reset(struct mixer_context *ctx) > unsigned int tries = 100; > > vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING); > - while (tries--) { > + while (--tries) { > /* waiting until VP_SRESET_PROCESSING is 0 */ > if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) > break; > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >
exynos-drm: display manager fails to start without IOMMU problem
Hello Shuah, just a short note that more misleading comments about default allocation flags can be found in libdrm. https://cgit.freedesktop.org/mesa/drm/tree/exynos/exynos_drm.c See e.g. the comment for exynos_bo_create(). In my opinion, the whole approach to _set_ a bit to get non-contigious memory is messed up. It would make more sense to me to set a bit to request an additional property (here "being contiguous") of the memory. Anyway, clearing up this situation is highly appreciated! More comments below. With best wishes, Tobias Shuah Khan wrote: > Restarting the thread with a different subject line: > > I haven't given up on this yet. I am still seeing the following failure: > > Additional debug messages I added: > [ 15.287403] exynos_drm_gem_create_ioctl() 1 > [ 15.287419] exynos_drm_gem_create() flags 1 > > [ 15.311511] [drm:exynos_drm_framebuffer_init] *ERROR* Non-contiguous GEM > memory is not supported. > > Additional debug message I added: > [ 15.318981] [drm:exynos_user_fb_create] *ERROR* failed to initialize > framebuffer > > This is what happens: > > 1. exynos_drm_gem_create_ioctl() gets called with EXYNOS_BO_NONCONTIG request > 2. exynos_drm_gem_create(0 goes ahead and creates the GEM buffers > 3. exynos_user_fb_create() tries to associate GEM to fb and fails during >check_fb_gem_memory_type() > > At this point, there is no recovery and lightdm fails > > xf86-video-armsoc/src/drmmode_exynos/drmmode_exynos.c assumes contiguous > allocations are not supported in some exynos drm versions: The following > commit introduced this change: > > https://git.linaro.org/arm/xorg/driver/xf86-video-armsoc.git/commitdiff/3be1f6273441fe95dd442f44064387322e16b7e9 > > excerpts from the diff:- if (create_gem->buf_type == ARMSOC_BO_SCANOUT) > - create_exynos.flags = EXYNOS_BO_CONTIG; > - else > - create_exynos.flags = EXYNOS_BO_NONCONTIG; > + > + /* Contiguous allocations are not supported in some exynos drm > versions. > +* When they are supported all allocations are effectively contiguous > +* anyway, so for simplicity we always request non contiguous buffers. > +*/ > + create_exynos.flags = EXYNOS_BO_NONCONTIG; > > There might have been logic on exynos_drm that forced Contig when it coudn't > support NONCONTIG. At least, that is what this comment suggests. This > assumption > doesn't appear to be a good one and not sure if this change was made to fix a > bug. > > After the IOMMU support, this assumption is no longer true. Hence, with IOMMU > support, latest kernels have a mismatch with the installed xf86-video-armsoc > > This is what I am running into. This leads to the following question: > > 1. How do we ensure exynos_drm kernel changes don't break user-space >specifically xf86-video-armsoc > 2. This seems to have gone undetected for a while. I see a change in >exynos_drm_gem_dumb_create() that is probably addressing this type >of breakage. Commit 122beea84bb90236b1ae545f08267af58591c21b adds >handling for IOMMU NONCONTIG case. I don't think that this commit is related to the issue, since it is only used for the generic dumb buffer ioctl, while armsoc is using an Exynos specific ioctl. So in particular you shouldn't see the issue with xf86-video-modesetting. Might be worth trying that one out? > > Anyway, I am interested in getting the exynos_drm kernel side code > and xf86-video-armsoc in sync to resolve the issue. > > Could you recommend a going forward plan? > > I can submit a patch to xf86-video-armsoc. I am also looking ahead to > see if we can avoid such breaks in the future by keeping kernel and > xf86-video-armsoc in sync. > > thanks, > -- Shuah > > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >
Re: [PATCH libdrm 2/3] exynos/fimg2d: remove unused-function build warning
Hello Seung-Woo, looks good to me. Also, g2d_reset() never worked in the first place, since the kernel driver rejects writes to SOFT_RESET_REG. Reviewed-by: Tobias Jakobi With best wishes, Tobias Seung-Woo Kim wrote: > The function g2d_reset() is not anymore used after the commit > e3c97d1a2473 ("exynos/fimg2d: add g2d_validate_xyz() functions"), > so it should be removed. > > Signed-off-by: Seung-Woo Kim > --- > exynos/exynos_fimg2d.c | 14 -- > 1 files changed, 0 insertions(+), 14 deletions(-) > > diff --git a/exynos/exynos_fimg2d.c b/exynos/exynos_fimg2d.c > index 7f1d105..61340c3 100644 > --- a/exynos/exynos_fimg2d.c > +++ b/exynos/exynos_fimg2d.c > @@ -293,20 +293,6 @@ static void g2d_set_direction(struct g2d_context *ctx, > } > > /* > - * g2d_reset - reset fimg2d hardware. > - * > - * @ctx: a pointer to g2d_context structure. > - * > - */ > -static void g2d_reset(struct g2d_context *ctx) > -{ > - ctx->cmd_nr = 0; > - ctx->cmd_buf_nr = 0; > - > - g2d_add_cmd(ctx, SOFT_RESET_REG, 0x01); > -} > - > -/* > * g2d_flush - submit all commands and values in user side command buffer > * to command queue aware of fimg2d dma. > * > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH libdrm 1/3] exynos: fix type-punned pointer build warning
Hello Seung-Woo, Reviewed-by: Tobias Jakobi With best wishes, Tobias Seung-Woo Kim wrote: > As like the commit ecc2a097294d ("xf86drm: Fix type-punned pointer > build warning"), this fixes following build warning. > >exynos_drm.c: In function 'exynos_handle_event': >exynos_drm.c:420:15: warning: dereferencing type-punned pointer will break > strict-aliasing rules [-Wstrict-aliasing] > e = (struct drm_event *) &buffer[i]; > ^ > > Signed-off-by: Seung-Woo Kim > --- > exynos/exynos_drm.c |2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c > index b961e52..f6204f1 100644 > --- a/exynos/exynos_drm.c > +++ b/exynos/exynos_drm.c > @@ -417,7 +417,7 @@ exynos_handle_event(struct exynos_device *dev, struct > exynos_event_context *ctx) > > i = 0; > while (i < len) { > - e = (struct drm_event *) &buffer[i]; > + e = (struct drm_event *)(buffer + i); > switch (e->type) { > case DRM_EVENT_VBLANK: > if (evctx->version < 1 || > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 0/8] drm/exynos: misc fixes and more
Hello, some recent work I did on Exynos. Patches are based on [1] and [2]. Summary: (a) Enables support for NV12MT in the mixer. (b) Sanitizes buffer pitch for HW with restrictions. (c) Misc fixes While testing the NV12MT part, I made these interesting observations. (1) I used 1920x1080 XRGB on the primary plane, and 1280x768 on the video plane. With this configuration, it does not matter if you're using NV12 or NV12MT, the video plane occasionally flickers or shows heavy artifacting. Reducing the size of the primary plane, e.g. to 32x32 solves this issue, so my guess is that this is memory bandwidth issue. Does someone know if one can check for buffer underflows of the mixer with respect to data passed from the VP? (2) Using 1920x1080i (so an interlaced mode) and NV12, the board immediately dies with an IOMMU pagefault at address zero. I'm currently investigating this, and it looks like that the VP setup is wrong here. In particular it should be the source (!) height and vertical position that should be halfed in interlaced mode, and not the destination. Need to look more into this. Anyway, both the issues are independant of the patches, so please review! :-) With best wishes, Tobias [1] http://www.spinics.net/lists/linux-samsung-soc/msg58640.html [2] http://www.spinics.net/lists/linux-samsung-soc/msg58644.html Tobias Jakobi (8): drm/exynos: mixer: fix chroma comment in vp_video_buffer() drm/exynos: mixer: enable NV12MT support for the video plane drm/exynos: mixer: simplify {vp_video,mixer_graph}_buffer() drm/exynos: mixer: remove src offset from mixer_graph_buffer() drm/exynos: introduce BYTE_PITCH capability drm/exynos: add BYTE_PITCH cap for all supported planes drm/exynos: consistent use of cpp drm/exynos: simplify set_pixfmt() in DECON and FIMD drivers drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 17 +-- drivers/gpu/drm/exynos/exynos7_drm_decon.c| 13 +++- drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 ++ drivers/gpu/drm/exynos/exynos_drm_fb.c| 2 ++ drivers/gpu/drm/exynos/exynos_drm_fimd.c | 17 --- drivers/gpu/drm/exynos/exynos_drm_plane.c | 37 ++ drivers/gpu/drm/exynos/exynos_mixer.c | 44 --- 7 files changed, 71 insertions(+), 61 deletions(-) -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 2/8] drm/exynos: mixer: enable NV12MT support for the video plane
The video processor supports a tiled variant of the NV12 format, known as NV12MT in V4L2 terms. The support was removed in commit 083500baefd5f4c215a5a93aef2492c1aa775828 due to not being a real pixel format, but rather NV12MT with a special memory layout. With the introduction of FB modifiers, we can now properly support this format again. Tested with a hacked up modetest from libdrm's test suite on an ODROID-X2 (Exynos4412). Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 + drivers/gpu/drm/exynos/exynos_drm_fb.c| 2 ++ drivers/gpu/drm/exynos/exynos_drm_plane.c | 27 +++ drivers/gpu/drm/exynos/exynos_mixer.c | 6 +- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index cf6e08c..ee62b0b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -91,6 +91,7 @@ struct exynos_drm_plane { #define EXYNOS_DRM_PLANE_CAP_DOUBLE(1 << 0) #define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1) #define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2) +#define EXYNOS_DRM_PLANE_CAP_TILE (1 << 3) /* * Exynos DRM plane configuration structure. diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index c77a5ac..35b7ab2 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -238,4 +238,6 @@ void exynos_drm_mode_config_init(struct drm_device *dev) dev->mode_config.funcs = &exynos_drm_mode_config_funcs; dev->mode_config.helper_private = &exynos_drm_mode_config_helpers; + + dev->mode_config.allow_fb_modifiers = true; } diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index c2f17f3..fa6333d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -180,6 +180,29 @@ static struct drm_plane_funcs exynos_plane_funcs = { }; static int +exynos_drm_plane_check_format(const struct exynos_drm_plane_config *config, + struct exynos_drm_plane_state *state) +{ + struct drm_framebuffer *fb = state->base.fb; + + switch (fb->modifier) { + case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: + if (!(config->capabilities & EXYNOS_DRM_PLANE_CAP_TILE)) + return -ENOTSUPP; + break; + + case 0: + break; + + default: + DRM_ERROR("unsupported pixel format modifier"); + return -ENOTSUPP; + } + + return 0; +} + +static int exynos_drm_plane_check_size(const struct exynos_drm_plane_config *config, struct exynos_drm_plane_state *state) { @@ -223,6 +246,10 @@ static int exynos_plane_atomic_check(struct drm_plane *plane, /* translate state into exynos_state */ exynos_plane_mode_set(exynos_state); + ret = exynos_drm_plane_check_format(exynos_plane->config, exynos_state); + if (ret) + return ret; + ret = exynos_drm_plane_check_size(exynos_plane->config, exynos_state); return ret; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 77f18f6..35edbf2 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -149,7 +149,8 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = { .pixel_formats = vp_formats, .num_pixel_formats = ARRAY_SIZE(vp_formats), .capabilities = EXYNOS_DRM_PLANE_CAP_SCALE | - EXYNOS_DRM_PLANE_CAP_ZPOS, + EXYNOS_DRM_PLANE_CAP_ZPOS | + EXYNOS_DRM_PLANE_CAP_TILE, }, }; @@ -501,6 +502,9 @@ static void vp_video_buffer(struct mixer_context *ctx, return; } + if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) + tiled_mode = true; + luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0); chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1); -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 1/8] drm/exynos: mixer: fix chroma comment in vp_video_buffer()
The current comment sounds like the division is done to compensate for some hardware erratum. But the chroma plane having half the height of the luma plane is just the way NV12/NV21 is defined, so clarify this behaviour. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 9648dd5..77f18f6 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -533,7 +533,7 @@ static void vp_video_buffer(struct mixer_context *ctx, /* setting size of input image */ vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | VP_IMG_VSIZE(fb->height)); - /* chroma height has to reduced by 2 to avoid chroma distorions */ + /* the chroma plane for NV12/NV21 is half the height of the luma plane */ vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | VP_IMG_VSIZE(fb->height / 2)); -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 3/8] drm/exynos: mixer: simplify {vp_video, mixer_graph}_buffer()
DRM core already checks the validity of the pixelformats, to we can simplify the checks here. The same applies to the FB modifier, which is now check in common Exynos plane code. Also rename the booleans to reflect what true/false actually encodes. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 31 +++ 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 35edbf2..32970fb 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -485,32 +485,18 @@ static void vp_video_buffer(struct mixer_context *ctx, unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; dma_addr_t luma_addr[2], chroma_addr[2]; - bool tiled_mode = false; - bool crcb_mode = false; + bool is_tiled, is_nv21; u32 val; - switch (fb->format->format) { - case DRM_FORMAT_NV12: - crcb_mode = false; - break; - case DRM_FORMAT_NV21: - crcb_mode = true; - break; - default: - DRM_ERROR("pixel format for vp is wrong [%d].\n", - fb->format->format); - return; - } - - if (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE) - tiled_mode = true; + is_nv21 = (fb->format->format == DRM_FORMAT_NV21); + is_tiled = (fb->modifier == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE); luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0); chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1); if (mode->flags & DRM_MODE_FLAG_INTERLACE) { __set_bit(MXR_BIT_INTERLACE, &ctx->flags); - if (tiled_mode) { + if (is_tiled) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; } else { @@ -530,8 +516,8 @@ static void vp_video_buffer(struct mixer_context *ctx, vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); /* setup format */ - val = (crcb_mode ? VP_MODE_NV21 : VP_MODE_NV12); - val |= (tiled_mode ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); + val = (is_nv21 ? VP_MODE_NV21 : VP_MODE_NV12); + val |= (is_tiled ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); /* setting size of input image */ @@ -621,12 +607,9 @@ static void mixer_graph_buffer(struct mixer_context *ctx, case DRM_FORMAT_XRGB: case DRM_FORMAT_ARGB: + default: fmt = MXR_FORMAT_ARGB; break; - - default: - DRM_DEBUG_KMS("pixelformat unsupported by mixer\n"); - return; } /* ratio is already checked by common plane code */ -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 5/8] drm/exynos: introduce BYTE_PITCH capability
In some of drivers we compute something like 'pitch / cpp' at some point, silently assuming that the pitch (which is in bytes) is divisible by the buffer's cpp. This is not always true, in particular DRM core does not check for pitch alignment in the common case. Introduce a new cap which signals that the hardware supports a pitch with 'byte-granularity'. If the cap is not set, assume that we need pitch aligned to cpp. We set the cap later for the drivers/planes that support it. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_drv.h | 1 + drivers/gpu/drm/exynos/exynos_drm_plane.c | 10 ++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index ee62b0b..8d957a9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -92,6 +92,7 @@ struct exynos_drm_plane { #define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1) #define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2) #define EXYNOS_DRM_PLANE_CAP_TILE (1 << 3) +#define EXYNOS_DRM_PLANE_CAP_BYTE_PITCH(1 << 4) /* * Exynos DRM plane configuration structure. diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c index fa6333d..b31a226 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_plane.c +++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c @@ -185,6 +185,16 @@ exynos_drm_plane_check_format(const struct exynos_drm_plane_config *config, { struct drm_framebuffer *fb = state->base.fb; + /* +* Some blocks only allow to specify a buffer pitch in terms +* of pixels. In these cases, we need to ensure that the pitch +* provided by userspace is divisible by the cpp. +*/ + if (!(config->capabilities & EXYNOS_DRM_PLANE_CAP_BYTE_PITCH)) { + if (fb->pitches[0] % fb->format->cpp[0]) + return -ENOTSUPP; + } + switch (fb->modifier) { case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE: if (!(config->capabilities & EXYNOS_DRM_PLANE_CAP_TILE)) -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 4/8] drm/exynos: mixer: remove src offset from mixer_graph_buffer()
We always translate the dma address such that the offsets of the source image are zero. Hence we can remove manipulation of the MXR_GRAPHIC_SXY(win) register. We leave the register defines (in regs_mixer.h) in place, since they document the hardware. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 11 ++- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 32970fb..b712f2a 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -585,7 +585,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx, unsigned long flags; unsigned int win = plane->index; unsigned int x_ratio = 0, y_ratio = 0; - unsigned int src_x_offset, src_y_offset, dst_x_offset, dst_y_offset; + unsigned int dst_x_offset, dst_y_offset; dma_addr_t dma_addr; unsigned int fmt; u32 val; @@ -619,12 +619,10 @@ static void mixer_graph_buffer(struct mixer_context *ctx, dst_x_offset = state->crtc.x; dst_y_offset = state->crtc.y; - /* converting dma address base and source offset */ + /* translate dma address base s.t. the source image offset is zero */ dma_addr = exynos_drm_fb_dma_addr(fb, 0) + (state->src.x * fb->format->cpp[0]) + (state->src.y * fb->pitches[0]); - src_x_offset = 0; - src_y_offset = 0; if (mode->flags & DRM_MODE_FLAG_INTERLACE) __set_bit(MXR_BIT_INTERLACE, &ctx->flags); @@ -655,11 +653,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx, val |= MXR_GRP_WH_V_SCALE(y_ratio); mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); - /* setup offsets in source image */ - val = MXR_GRP_SXY_SX(src_x_offset); - val |= MXR_GRP_SXY_SY(src_y_offset); - mixer_reg_write(res, MXR_GRAPHIC_SXY(win), val); - /* setup offsets in display image */ val = MXR_GRP_DXY_DX(dst_x_offset); val |= MXR_GRP_DXY_DY(dst_y_offset); -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 6/8] drm/exynos: add BYTE_PITCH cap for all supported planes
Both FIMD and DECON5433 support a pitch in bytes. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 1 + drivers/gpu/drm/exynos/exynos_drm_fimd.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 0fd6f7a..099e22e 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -533,6 +533,7 @@ static int decon_bind(struct device *dev, struct device *master, void *data) ctx->configs[win].num_pixel_formats = ARRAY_SIZE(decon_formats); ctx->configs[win].zpos = win; ctx->configs[win].type = decon_win_types[tmp]; + ctx->configs[win].capabilities = EXYNOS_DRM_PLANE_CAP_BYTE_PITCH; ret = exynos_plane_init(drm_dev, &ctx->planes[win], win, 1 << ctx->pipe, &ctx->configs[win]); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index a9fa444..ae738b8 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -1007,6 +1007,7 @@ static int fimd_bind(struct device *dev, struct device *master, void *data) ctx->configs[i].num_pixel_formats = ARRAY_SIZE(fimd_formats); ctx->configs[i].zpos = i; ctx->configs[i].type = fimd_win_types[i]; + ctx->configs[i].capabilities = EXYNOS_DRM_PLANE_CAP_BYTE_PITCH; ret = exynos_plane_init(drm_dev, &ctx->planes[i], i, 1 << ctx->pipe, &ctx->configs[i]); if (ret) -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[RFC 7/8] drm/exynos: consistent use of cpp
A recent commit (272725c7db4da1fd3229d944fc76d2e98e3a144e) has removed the use of 'bits_per_pixel' in DRM. However the corresponding Exynos driver code still uses the ambiguous 'bpp', even though it is now initialized from fb->cpp[0]. Consistenly use 'cpp' in FIMD, DECON7 and DECON5433 drivers. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 12 ++-- drivers/gpu/drm/exynos/exynos7_drm_decon.c| 6 +++--- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 8 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 099e22e..4343252 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -247,7 +247,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, return; } - DRM_DEBUG_KMS("bpp = %u\n", fb->format->cpp[0] * 8); + DRM_DEBUG_KMS("cpp = %u\n", fb->format->cpp[0]); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -296,7 +296,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, struct decon_context *ctx = crtc->ctx; struct drm_framebuffer *fb = state->base.fb; unsigned int win = plane->index; - unsigned int bpp = fb->format->cpp[0]; + unsigned int cpp = fb->format->cpp[0]; unsigned int pitch = fb->pitches[0]; dma_addr_t dma_addr = exynos_drm_fb_dma_addr(fb, 0); u32 val; @@ -335,11 +335,11 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, writel(val, ctx->addr + DECON_VIDW0xADD1B0(win)); if (!(ctx->out_type & IFTYPE_HDMI)) - val = BIT_VAL(pitch - state->crtc.w * bpp, 27, 14) - | BIT_VAL(state->crtc.w * bpp, 13, 0); + val = BIT_VAL(pitch - state->crtc.w * cpp, 27, 14) + | BIT_VAL(state->crtc.w * cpp, 13, 0); else - val = BIT_VAL(pitch - state->crtc.w * bpp, 29, 15) - | BIT_VAL(state->crtc.w * bpp, 14, 0); + val = BIT_VAL(pitch - state->crtc.w * cpp, 29, 15) + | BIT_VAL(state->crtc.w * cpp, 14, 0); writel(val, ctx->addr + DECON_VIDW0xADD2(win)); decon_win_set_pixfmt(ctx, win, fb); diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index f9ab19e..c6d06cc 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -330,7 +330,7 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, break; } - DRM_DEBUG_KMS("bpp = %d\n", fb->format->cpp[0] * 8); + DRM_DEBUG_KMS("cpp = %d\n", fb->format->cpp[0]); /* * In case of exynos, setting dma-burst to 16Word causes permanent @@ -407,7 +407,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, unsigned int last_x; unsigned int last_y; unsigned int win = plane->index; - unsigned int bpp = fb->format->cpp[0]; + unsigned int cpp = fb->format->cpp[0]; unsigned int pitch = fb->pitches[0]; if (ctx->suspended) @@ -427,7 +427,7 @@ static void decon_update_plane(struct exynos_drm_crtc *crtc, val = (unsigned long)exynos_drm_fb_dma_addr(fb, 0); writel(val, ctx->regs + VIDW_BUF_START(win)); - padding = (pitch / bpp) - fb->width; + padding = (pitch / cpp) - fb->width; /* buffer size */ writel(fb->width + padding, ctx->regs + VIDW_WHOLE_X(win)); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index ae738b8..098a32d 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -736,13 +736,13 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, unsigned long val, size, offset; unsigned int last_x, last_y, buf_offsize, line_size; unsigned int win = plane->index; - unsigned int bpp = fb->format->cpp[0]; + unsigned int cpp = fb->format->cpp[0]; unsigned int pitch = fb->pitches[0]; if (ctx->suspended) return; - offset = state->src.x * bpp; + offset = state->src.x * cpp; offset += state->src.y * pitch; /* buffer start address */ @@ -761,8 +761,8 @@ static void fimd_update_plane(struct exynos_drm_crtc *crtc, state->crtc.w, state->crtc.h); /* buffer size */ - buf_offsize = pitch - (state->crtc.w * bpp); -
[RFC 8/8] drm/exynos: simplify set_pixfmt() in DECON and FIMD drivers
DRM core already checks the validity of the pixelformat. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 4 +--- drivers/gpu/drm/exynos/exynos7_drm_decon.c| 7 +-- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 8 +--- 3 files changed, 3 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 4343252..7efa92d 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -238,13 +238,11 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, val |= WINCONx_BURSTLEN_16WORD; break; case DRM_FORMAT_ARGB: + default: val |= WINCONx_BPPMODE_32BPP_A; val |= WINCONx_WSWP_F | WINCONx_BLD_PIX_F | WINCONx_ALPHA_SEL_F; val |= WINCONx_BURSTLEN_16WORD; break; - default: - DRM_ERROR("Proper pixel format is not set\n"); - return; } DRM_DEBUG_KMS("cpp = %u\n", fb->format->cpp[0]); diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c index c6d06cc..0d60e38 100644 --- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c @@ -318,16 +318,11 @@ static void decon_win_set_pixfmt(struct decon_context *ctx, unsigned int win, val |= WINCONx_BURSTLEN_16WORD; break; case DRM_FORMAT_BGRA: + default: val |= WINCONx_BPPMODE_32BPP_BGRA | WINCONx_BLD_PIX | WINCONx_ALPHA_SEL; val |= WINCONx_BURSTLEN_16WORD; break; - default: - DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n"); - - val |= WINCONx_BPPMODE_24BPP_xRGB; - val |= WINCONx_BURSTLEN_16WORD; - break; } DRM_DEBUG_KMS("cpp = %d\n", fb->format->cpp[0]); diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 098a32d..0529c58 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c @@ -603,18 +603,12 @@ static void fimd_win_set_pixfmt(struct fimd_context *ctx, unsigned int win, val |= WINCONx_BURSTLEN_16WORD; break; case DRM_FORMAT_ARGB: + default: val |= WINCON1_BPPMODE_25BPP_A1888 | WINCON1_BLD_PIX | WINCON1_ALPHA_SEL; val |= WINCONx_WSWP; val |= WINCONx_BURSTLEN_16WORD; break; - default: - DRM_DEBUG_KMS("invalid pixel size so using unpacked 24bpp.\n"); - - val |= WINCON0_BPPMODE_24BPP_888; - val |= WINCONx_WSWP; - val |= WINCONx_BURSTLEN_16WORD; - break; } /* -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] exynos: add C++ support to exynos_drmif header
Add the usual extern "C" when compiling in C++ mode. Signed-off-by: Tobias Jakobi --- exynos/exynos_drmif.h | 8 1 file changed, 8 insertions(+) diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h index 626e399..154439b 100644 --- a/exynos/exynos_drmif.h +++ b/exynos/exynos_drmif.h @@ -31,6 +31,10 @@ #include #include "exynos_drm.h" +#if defined(__cplusplus) +extern "C" { +#endif + struct exynos_device { int fd; }; @@ -109,4 +113,8 @@ int exynos_handle_event(struct exynos_device *dev, struct exynos_event_context *ctx); +#if defined(__cplusplus) +} +#endif + #endif /* EXYNOS_DRMIF_H_ */ -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] exynos: add C++ support to exynos_drmif header
Hello Eric, Eric Engestrom wrote: > On Wednesday, 2017-04-05 16:22:24 +0200, Tobias Jakobi wrote: >> Add the usual extern "C" when compiling in C++ mode. > > Thanks, but why specifically this header? The other exynos/*.h headers > also lack the c++ mangling guard. I'm currently writing a small C++ project using the exynos_bo_{create,destroy}() calls, and noticed this. > A quick grep shows that only 15/101 headers in libdrm have it. > Can I interest you in fixing a few more headers? :) Not at the moment. - Tobias > In any case, this patch is: > Reviewed-by: Eric Engestrom > (I assume you'll push it yourself?) > > Btw, can you run this in your local libdrm repo? > $ git config --local format.subjectPrefix "PATCH libdrm" > > Cheers, > Eric > > >> >> Signed-off-by: Tobias Jakobi >> --- >> exynos/exynos_drmif.h | 8 >> 1 file changed, 8 insertions(+) >> >> diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h >> index 626e399..154439b 100644 >> --- a/exynos/exynos_drmif.h >> +++ b/exynos/exynos_drmif.h >> @@ -31,6 +31,10 @@ >> #include >> #include "exynos_drm.h" >> >> +#if defined(__cplusplus) >> +extern "C" { >> +#endif >> + >> struct exynos_device { >> int fd; >> }; >> @@ -109,4 +113,8 @@ int exynos_handle_event(struct exynos_device *dev, >> struct exynos_event_context *ctx); >> >> >> +#if defined(__cplusplus) >> +} >> +#endif >> + >> #endif /* EXYNOS_DRMIF_H_ */ >> -- >> 2.7.3 >> ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: clean up description of exynos_drm_crtc
Hello Inki, Inki Dae wrote: > This patch removes unnecessary descriptions on > exynos_drm_crtc structure and adds one description > which specifies what pipe_clk member does. > > pipe_clk support had been added by below patch without any description, >drm/exynos: add support for pipeline clock to the framework I would put the commit id here. That makes it easier to look up the commit your refer to. > Signed-off-by: Inki Dae > --- > drivers/gpu/drm/exynos/exynos_drm_drv.h | 6 ++ > 1 file changed, 2 insertions(+), 4 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h > b/drivers/gpu/drm/exynos/exynos_drm_drv.h > index 527bf1d..b0462cc 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h > @@ -152,12 +152,10 @@ struct exynos_drm_clk { > * > * @base: crtc object. > * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. > - * @enabled: if the crtc is enabled or not > - * @event: vblank event that is currently queued for flip > - * @wait_update: wait all pending planes updates to finish > - * @pending_update: number of pending plane updates in this crtc > * @ops: pointer to callbacks for exynos drm specific functionality > * @ctx: A pointer to the crtc's implementation specific context > + * @pipe_clk: A pipe clock structure which includes a callback function > + for enabling DP clock of FIMD and HDMI PHY clock. This is wrong/inconsistent with the rest of the documentation. pipe_clk is not a struct, but a pointer. I would suggest to follow. Just document that we have a pointer to here (compare docu for 'ops' and 'ctx'). And then put the later bits ("...callback function for enabling DP clock...") directly to the definition of 'struct exynos_drm_clk' (which is currently lacking any kind of docu). - Tobias > */ > struct exynos_drm_crtc { > struct drm_crtc base; > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: clean up description of exynos_drm_crtc
Hello Inki, Inki Dae wrote: > Hello Tobias, > > > 2017년 04월 07일 02:10에 Tobias Jakobi 이(가) 쓴 글: >> Hello Inki, >> >> >> Inki Dae wrote: >>> This patch removes unnecessary descriptions on >>> exynos_drm_crtc structure and adds one description >>> which specifies what pipe_clk member does. >>> >>> pipe_clk support had been added by below patch without any description, >>> drm/exynos: add support for pipeline clock to the framework >> I would put the commit id here. That makes it easier to look up the >> commit your refer to. >> >> >>> Signed-off-by: Inki Dae >>> --- >>> drivers/gpu/drm/exynos/exynos_drm_drv.h | 6 ++ >>> 1 file changed, 2 insertions(+), 4 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>> b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>> index 527bf1d..b0462cc 100644 >>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>> @@ -152,12 +152,10 @@ struct exynos_drm_clk { >>> * >>> * @base: crtc object. >>> * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. >>> - * @enabled: if the crtc is enabled or not >>> - * @event: vblank event that is currently queued for flip >>> - * @wait_update: wait all pending planes updates to finish >>> - * @pending_update: number of pending plane updates in this crtc >>> * @ops: pointer to callbacks for exynos drm specific functionality >>> * @ctx: A pointer to the crtc's implementation specific context >>> + * @pipe_clk: A pipe clock structure which includes a callback function >>> + for enabling DP clock of FIMD and HDMI PHY clock. >> This is wrong/inconsistent with the rest of the documentation. pipe_clk >> is not a struct, but a pointer. >> >> I would suggest to follow. Just document that we have a pointer to > escription> here (compare docu for 'ops' and 'ctx'). >> And then put the later bits ("...callback function for enabling DP >> clock...") directly to the definition of 'struct exynos_drm_clk' (which >> is currently lacking any kind of docu). > > Thanks for pointing it out. My mistake. :) > > How about this simply? > "A pointer to exynos_drm_clk structure for enabling and disabling DP clock of > FIMD and HDMI PHY clocks" Not what I meant. You're describing 'struct exynos_drm_clk', and that does not belong here. If you describe 'struct exynos_drm_clk', then this should go in front of the struct's definition. How abouting something like this in front of the struct's definition:: > /* > * Exynos DRM pipeline clock structure. > * > * @enable: callback to enable/disable the clock. > * > * Used for proper clock synchronization of components belonging > * to the same pipeline. Used e.g. for enabling the DP clock of > * the FIMD or the HDMI PHY clock. > */ > struct exynos_drm_clk { > For 'pipe_clk' I would just go with this: > @pipe_clk: A pointet to the crtc's pipeline clock. I hope this helps. - Tobias > Thanks, > Inki Dae > >> >> >> - Tobias >> >>> */ >>> struct exynos_drm_crtc { >>> struct drm_crtc base; >>> >> >> >> >> ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] exynos: add C++ support to exynos_drmif header
Emil Velikov wrote: > FTR, only the installed headers (~50) need the extern C guard. > None of that is not a blocker for this patch, so I've just pushed it to > master. Thanks Emil. I'll see what I can do about the other ones. - Tobias > Thanks! > Emil > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3] drm/exynos: mixer: document YCbCr magic numbers
Inki Dae wrote: > 2017-03-29 20:56 GMT+09:00 Tobias Jakobi : >> Hello Daniel, >> >> same question here. Patch doesn't introduce any functional changes (just >> adds code documentation), so can you merge it through drm-misc? >> > > Sorry for late. Confirmed just now. I will check it on next Monday. You have added the wrong patch (v2 instead of v3). - Tobias > Thanks, > Inki Dae > >> With best wishes, >> Tobias >> >> >> Tobias Jakobi wrote: >>> The output stage of the mixer uses YCbCr for the internal >>> computations, which is the reason that some registers take >>> YCbCr related data as input. In particular this applies >>> to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. >>> >>> Document the formatting of the data which we write to >>> these registers. >>> >>> While at it, unify wording of comments in the register header. >>> >>> Reviewed-by: Andrzej Hajda >>> Signed-off-by: Tobias Jakobi >>> --- >>> Changes in v2: >>> - use floating point values as input for the macros, as >>> suggested by Andrzej >>> - the floating point values have been tuned to exactly match >>> the values that are currently used >>> >>> Changes in v3: >>> - use only three digit values (pointed out by Andrzej) >>> >>> drivers/gpu/drm/exynos/exynos_mixer.c | 33 >>> + >>> drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- >>> 2 files changed, 30 insertions(+), 10 deletions(-) >>> >>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>> index 41d0c36..9648dd5 100644 >>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>> @@ -45,6 +45,22 @@ >>> #define MIXER_WIN_NR 3 >>> #define VP_DEFAULT_WIN 2 >>> >>> +/* >>> + * Mixer color space conversion coefficient triplet. >>> + * Used for CSC from RGB to YCbCr. >>> + * Each coefficient is a 10-bit fixed point number with >>> + * sign and no integer part, i.e. >>> + * [0:8] = fractional part (representing a value y = x / 2^9) >>> + * [9] = sign >>> + * Negative values are encoded with two's complement. >>> + */ >>> +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) >>> +#define MXR_CSC_CT(a0, a1, a2) \ >>> + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) >>> + >>> +/* YCbCr value, used for mixer background color configuration. */ >>> +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) >>> + >>> /* The pixelformats that are natively supported by the mixer. */ >>> #define MXR_FORMAT_RGB5654 >>> #define MXR_FORMAT_ARGB1555 5 >>> @@ -391,13 +407,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >>> *ctx, unsigned int height) >>> case 1080: >>> default: >>> val = MXR_CFG_RGB709_16_235; >>> + /* Configure the BT.709 CSC matrix for full range RGB. */ >>> mixer_reg_write(res, MXR_CM_COEFF_Y, >>> - (1 << 30) | (94 << 20) | (314 << 10) | >>> - (32 << 0)); >>> + MXR_CSC_CT( 0.184, 0.614, 0.063) | >>> + MXR_CM_COEFF_RGB_FULL); >>> mixer_reg_write(res, MXR_CM_COEFF_CB, >>> - (972 << 20) | (851 << 10) | (225 << 0)); >>> + MXR_CSC_CT(-0.102, -0.338, 0.440)); >>> mixer_reg_write(res, MXR_CM_COEFF_CR, >>> - (225 << 20) | (820 << 10) | (1004 << 0)); >>> + MXR_CSC_CT( 0.440, -0.399, -0.040)); >>> break; >>> } >>> >>> @@ -715,10 +732,10 @@ static void mixer_win_reset(struct mixer_context *ctx) >>> /* reset default layer priority */ >>> mixer_reg_write(res, MXR_LAYER_CFG, 0); >>> >>> - /* setting background color */ >>> - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); >>> - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); >>> - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); >>> + /* set all background colors to RGB (0,0,0) */ >>> +
Re: [PATCH] drm/exynos: clean up description of exynos_drm_crtc
Inki Dae wrote: > 2017-04-07 20:40 GMT+09:00 Tobias Jakobi : >> Hello Inki, >> >> >> Inki Dae wrote: >>> Hello Tobias, >>> >>> >>> 2017년 04월 07일 02:10에 Tobias Jakobi 이(가) 쓴 글: >>>> Hello Inki, >>>> >>>> >>>> Inki Dae wrote: >>>>> This patch removes unnecessary descriptions on >>>>> exynos_drm_crtc structure and adds one description >>>>> which specifies what pipe_clk member does. >>>>> >>>>> pipe_clk support had been added by below patch without any description, >>>>> drm/exynos: add support for pipeline clock to the framework >>>> I would put the commit id here. That makes it easier to look up the >>>> commit your refer to. >>>> >>>> >>>>> Signed-off-by: Inki Dae >>>>> --- >>>>> drivers/gpu/drm/exynos/exynos_drm_drv.h | 6 ++ >>>>> 1 file changed, 2 insertions(+), 4 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>> b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>> index 527bf1d..b0462cc 100644 >>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>> @@ -152,12 +152,10 @@ struct exynos_drm_clk { >>>>> * >>>>> * @base: crtc object. >>>>> * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. >>>>> - * @enabled: if the crtc is enabled or not >>>>> - * @event: vblank event that is currently queued for flip >>>>> - * @wait_update: wait all pending planes updates to finish >>>>> - * @pending_update: number of pending plane updates in this crtc >>>>> * @ops: pointer to callbacks for exynos drm specific functionality >>>>> * @ctx: A pointer to the crtc's implementation specific context >>>>> + * @pipe_clk: A pipe clock structure which includes a callback function >>>>> + for enabling DP clock of FIMD and HDMI PHY clock. >>>> This is wrong/inconsistent with the rest of the documentation. pipe_clk >>>> is not a struct, but a pointer. >>>> >>>> I would suggest to follow. Just document that we have a pointer to >>> escription> here (compare docu for 'ops' and 'ctx'). >>>> And then put the later bits ("...callback function for enabling DP >>>> clock...") directly to the definition of 'struct exynos_drm_clk' (which >>>> is currently lacking any kind of docu). >>> >>> Thanks for pointing it out. My mistake. :) >>> >>> How about this simply? >>> "A pointer to exynos_drm_clk structure for enabling and disabling DP clock >>> of FIMD and HDMI PHY clocks" >> Not what I meant. You're describing 'struct exynos_drm_clk', and that >> does not belong here. If you describe 'struct exynos_drm_clk', then this >> should go in front of the struct's definition. >> >> How abouting something like this in front of the struct's definition:: >>> /* >>> * Exynos DRM pipeline clock structure. >>> * >>> * @enable: callback to enable/disable the clock. >>> * >>> * Used for proper clock synchronization of components belonging >>> * to the same pipeline. Used e.g. for enabling the DP clock of >>> * the FIMD or the HDMI PHY clock. >>> */ >>> struct exynos_drm_clk { >>> >> >> For 'pipe_clk' I would just go with this: >>> @pipe_clk: A pointet to the crtc's pipeline clock. > > More simple and looks better. In this form (commit a07d468cb2efd347a9e279e4f68661f0f370d10f in exynos-drm-next), the description is incomplete. Please read my mails again. - Tobias > > Thanks, > Inki Dae > >> >> I hope this helps. >> >> - Tobias >> >> >>> Thanks, >>> Inki Dae >>> >>>> >>>> >>>> - Tobias >>>> >>>>> */ >>>>> struct exynos_drm_crtc { >>>>> struct drm_crtc base; >>>>> >>>> >>>> >>>> >>>> >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" >> in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: clean up description of exynos_drm_crtc
Inki Dae wrote: > > > 2017년 04월 10일 19:29에 Tobias Jakobi 이(가) 쓴 글: >> Inki Dae wrote: >>> 2017-04-07 20:40 GMT+09:00 Tobias Jakobi : >>>> Hello Inki, >>>> >>>> >>>> Inki Dae wrote: >>>>> Hello Tobias, >>>>> >>>>> >>>>> 2017년 04월 07일 02:10에 Tobias Jakobi 이(가) 쓴 글: >>>>>> Hello Inki, >>>>>> >>>>>> >>>>>> Inki Dae wrote: >>>>>>> This patch removes unnecessary descriptions on >>>>>>> exynos_drm_crtc structure and adds one description >>>>>>> which specifies what pipe_clk member does. >>>>>>> >>>>>>> pipe_clk support had been added by below patch without any description, >>>>>>> drm/exynos: add support for pipeline clock to the framework >>>>>> I would put the commit id here. That makes it easier to look up the >>>>>> commit your refer to. >>>>>> >>>>>> >>>>>>> Signed-off-by: Inki Dae >>>>>>> --- >>>>>>> drivers/gpu/drm/exynos/exynos_drm_drv.h | 6 ++ >>>>>>> 1 file changed, 2 insertions(+), 4 deletions(-) >>>>>>> >>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>> b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>> index 527bf1d..b0462cc 100644 >>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>> @@ -152,12 +152,10 @@ struct exynos_drm_clk { >>>>>>> * >>>>>>> * @base: crtc object. >>>>>>> * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. >>>>>>> - * @enabled: if the crtc is enabled or not >>>>>>> - * @event: vblank event that is currently queued for flip >>>>>>> - * @wait_update: wait all pending planes updates to finish >>>>>>> - * @pending_update: number of pending plane updates in this crtc >>>>>>> * @ops: pointer to callbacks for exynos drm specific functionality >>>>>>> * @ctx: A pointer to the crtc's implementation specific context >>>>>>> + * @pipe_clk: A pipe clock structure which includes a callback function >>>>>>> + for enabling DP clock of FIMD and HDMI PHY clock. >>>>>> This is wrong/inconsistent with the rest of the documentation. pipe_clk >>>>>> is not a struct, but a pointer. >>>>>> >>>>>> I would suggest to follow. Just document that we have a pointer to >>>>> escription> here (compare docu for 'ops' and 'ctx'). >>>>>> And then put the later bits ("...callback function for enabling DP >>>>>> clock...") directly to the definition of 'struct exynos_drm_clk' (which >>>>>> is currently lacking any kind of docu). >>>>> >>>>> Thanks for pointing it out. My mistake. :) >>>>> >>>>> How about this simply? >>>>> "A pointer to exynos_drm_clk structure for enabling and disabling DP >>>>> clock of FIMD and HDMI PHY clocks" >>>> Not what I meant. You're describing 'struct exynos_drm_clk', and that >>>> does not belong here. If you describe 'struct exynos_drm_clk', then this >>>> should go in front of the struct's definition. >>>> >>>> How abouting something like this in front of the struct's definition:: >>>>> /* >>>>> * Exynos DRM pipeline clock structure. >>>>> * >>>>> * @enable: callback to enable/disable the clock. >>>>> * >>>>> * Used for proper clock synchronization of components belonging >>>>> * to the same pipeline. Used e.g. for enabling the DP clock of >>>>> * the FIMD or the HDMI PHY clock. >>>>> */ >>>>> struct exynos_drm_clk { >>>>> >>>> >>>> For 'pipe_clk' I would just go with this: >>>>> @pipe_clk: A pointet to the crtc's pipeline clock. >>> >>> More simple and looks better. >> In this form (commit a07d468cb2efd347a9e279e4f68661f0f370d10f in >> exynos-drm-next), the description is incomplete. Please read
Re: [PATCH v3] drm/exynos: mixer: document YCbCr magic numbers
Inki Dae wrote: > > > 2017년 04월 10일 19:27에 Tobias Jakobi 이(가) 쓴 글: >> Inki Dae wrote: >>> 2017-03-29 20:56 GMT+09:00 Tobias Jakobi : >>>> Hello Daniel, >>>> >>>> same question here. Patch doesn't introduce any functional changes (just >>>> adds code documentation), so can you merge it through drm-misc? >>>> >>> >>> Sorry for late. Confirmed just now. I will check it on next Monday. >> You have added the wrong patch (v2 instead of v3). > > Tobias, > > you had posted this patch with other one like below, > [PATCH v2 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt() > [PATCH v2 2/2] drm/exynos: mixer: document YCbCr magic numbers > > And than you have posted it without any comment again, v3, > [PATCH v3] drm/exynos: mixer: document YCbCr magic numbers > > Please use --cover-letter option to make patch series and keep the patch set > to be consistent with previous version. This is not necessary. There were only changes to 'drm/exynos: mixer: document YCbCr magic numbers' and we're talking about _two_ patches here (which can be applied independently). > > I can merge the new one - really trivial - but I think it'd be better you to > resend this patch series for other people. > > This patch set has been removed from my tree. Please resend (not v4) this > patch set like below, > [PATCH v3 0/2] drm/exynos: clean up mixer driver?? > [PATCH v3 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt() > [PATCH v3 2/2] drm/exynos: mixer: document YCbCr magic numbers Not necessary, just pick up the two patches which for which I already pinged you. For you convenience, here are the two on dri-devel patchwork: https://patchwork.kernel.org/patch/9617085/ https://patchwork.kernel.org/patch/9617493/ - Tobias > > Thanks, > Inki Dae > >> >> - Tobias >> >> >>> Thanks, >>> Inki Dae >>> >>>> With best wishes, >>>> Tobias >>>> >>>> >>>> Tobias Jakobi wrote: >>>>> The output stage of the mixer uses YCbCr for the internal >>>>> computations, which is the reason that some registers take >>>>> YCbCr related data as input. In particular this applies >>>>> to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. >>>>> >>>>> Document the formatting of the data which we write to >>>>> these registers. >>>>> >>>>> While at it, unify wording of comments in the register header. >>>>> >>>>> Reviewed-by: Andrzej Hajda >>>>> Signed-off-by: Tobias Jakobi >>>>> --- >>>>> Changes in v2: >>>>> - use floating point values as input for the macros, as >>>>> suggested by Andrzej >>>>> - the floating point values have been tuned to exactly match >>>>> the values that are currently used >>>>> >>>>> Changes in v3: >>>>> - use only three digit values (pointed out by Andrzej) >>>>> >>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 33 >>>>> + >>>>> drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- >>>>> 2 files changed, 30 insertions(+), 10 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> index 41d0c36..9648dd5 100644 >>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> @@ -45,6 +45,22 @@ >>>>> #define MIXER_WIN_NR 3 >>>>> #define VP_DEFAULT_WIN 2 >>>>> >>>>> +/* >>>>> + * Mixer color space conversion coefficient triplet. >>>>> + * Used for CSC from RGB to YCbCr. >>>>> + * Each coefficient is a 10-bit fixed point number with >>>>> + * sign and no integer part, i.e. >>>>> + * [0:8] = fractional part (representing a value y = x / 2^9) >>>>> + * [9] = sign >>>>> + * Negative values are encoded with two's complement. >>>>> + */ >>>>> +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) >>>>> +#define MXR_CSC_CT(a0, a1, a2) \ >>>>> + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) >>>>> + >>>>> +/* YCbCr value, used for mixer background color conf
Re: [PATCH] drm/exynos: clean up description of exynos_drm_crtc
Another thing that I noticed. Why wasn't the v2 that ended up in your git ever submitted to the mailing list? Because it should have, in particular to spot these obvious errors. - Tobias Tobias Jakobi wrote: > Inki Dae wrote: >> >> >> 2017년 04월 10일 19:29에 Tobias Jakobi 이(가) 쓴 글: >>> Inki Dae wrote: >>>> 2017-04-07 20:40 GMT+09:00 Tobias Jakobi : >>>>> Hello Inki, >>>>> >>>>> >>>>> Inki Dae wrote: >>>>>> Hello Tobias, >>>>>> >>>>>> >>>>>> 2017년 04월 07일 02:10에 Tobias Jakobi 이(가) 쓴 글: >>>>>>> Hello Inki, >>>>>>> >>>>>>> >>>>>>> Inki Dae wrote: >>>>>>>> This patch removes unnecessary descriptions on >>>>>>>> exynos_drm_crtc structure and adds one description >>>>>>>> which specifies what pipe_clk member does. >>>>>>>> >>>>>>>> pipe_clk support had been added by below patch without any description, >>>>>>>> drm/exynos: add support for pipeline clock to the framework >>>>>>> I would put the commit id here. That makes it easier to look up the >>>>>>> commit your refer to. >>>>>>> >>>>>>> >>>>>>>> Signed-off-by: Inki Dae >>>>>>>> --- >>>>>>>> drivers/gpu/drm/exynos/exynos_drm_drv.h | 6 ++ >>>>>>>> 1 file changed, 2 insertions(+), 4 deletions(-) >>>>>>>> >>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>> b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>> index 527bf1d..b0462cc 100644 >>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>> @@ -152,12 +152,10 @@ struct exynos_drm_clk { >>>>>>>> * >>>>>>>> * @base: crtc object. >>>>>>>> * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. >>>>>>>> - * @enabled: if the crtc is enabled or not >>>>>>>> - * @event: vblank event that is currently queued for flip >>>>>>>> - * @wait_update: wait all pending planes updates to finish >>>>>>>> - * @pending_update: number of pending plane updates in this crtc >>>>>>>> * @ops: pointer to callbacks for exynos drm specific functionality >>>>>>>> * @ctx: A pointer to the crtc's implementation specific context >>>>>>>> + * @pipe_clk: A pipe clock structure which includes a callback >>>>>>>> function >>>>>>>> + for enabling DP clock of FIMD and HDMI PHY clock. >>>>>>> This is wrong/inconsistent with the rest of the documentation. pipe_clk >>>>>>> is not a struct, but a pointer. >>>>>>> >>>>>>> I would suggest to follow. Just document that we have a pointer to >>>>>> escription> here (compare docu for 'ops' and 'ctx'). >>>>>>> And then put the later bits ("...callback function for enabling DP >>>>>>> clock...") directly to the definition of 'struct exynos_drm_clk' (which >>>>>>> is currently lacking any kind of docu). >>>>>> >>>>>> Thanks for pointing it out. My mistake. :) >>>>>> >>>>>> How about this simply? >>>>>> "A pointer to exynos_drm_clk structure for enabling and disabling DP >>>>>> clock of FIMD and HDMI PHY clocks" >>>>> Not what I meant. You're describing 'struct exynos_drm_clk', and that >>>>> does not belong here. If you describe 'struct exynos_drm_clk', then this >>>>> should go in front of the struct's definition. >>>>> >>>>> How abouting something like this in front of the struct's definition:: >>>>>> /* >>>>>> * Exynos DRM pipeline clock structure. >>>>>> * >>>>>> * @enable: callback to enable/disable the clock. >>>>>> * >>>>>> * Used for proper clock synchronization of components belonging >>>>>> * to the same pi
Re: [RFC 0/8] drm/exynos: misc fixes and more
Hello Inki, please don't forget to review this series. Also some pointers concerning the video plane flickering and the interlacing issue would be very welcome. Looking at the current register defines for MXR_INT_EN suggests that there are at least three more type of interrupt available. Any chance these could be documented? I hope to get some more insight into this issue, which apparantly is caused by insufficient bandwidth. For the interlacing issue I have done partial progress. I now longer see a IOMMU pagefault, but the video plane is heavily corrupted. Also the dimensions look wrong. While I can somehow guess that VP_MODE_LINE_SKIP does, the VP_MODE_FIELD_ID_AUTO_TOGGLING flag still remains a mystery to me. If possible, I request some documentation for this as well. With best wishes, Tobias Tobias Jakobi wrote: > Hello, > > some recent work I did on Exynos. Patches are based on [1] and [2]. > > Summary: > (a) Enables support for NV12MT in the mixer. > (b) Sanitizes buffer pitch for HW with restrictions. > (c) Misc fixes > > While testing the NV12MT part, I made these interesting observations. > > (1) I used 1920x1080 XRGB on the primary plane, and 1280x768 on the > video plane. With this configuration, it does not matter if you're > using NV12 or NV12MT, the video plane occasionally flickers or shows > heavy artifacting. Reducing the size of the primary plane, e.g. to > 32x32 solves this issue, so my guess is that this is memory bandwidth > issue. Does someone know if one can check for buffer underflows of the > mixer with respect to data passed from the VP? > > (2) Using 1920x1080i (so an interlaced mode) and NV12, the board > immediately dies with an IOMMU pagefault at address zero. I'm > currently investigating this, and it looks like that the VP setup > is wrong here. In particular it should be the source (!) height > and vertical position that should be halfed in interlaced mode, and > not the destination. Need to look more into this. > > Anyway, both the issues are independant of the patches, so please > review! :-) > > With best wishes, > Tobias > > > [1] http://www.spinics.net/lists/linux-samsung-soc/msg58640.html > [2] http://www.spinics.net/lists/linux-samsung-soc/msg58644.html > > Tobias Jakobi (8): > drm/exynos: mixer: fix chroma comment in vp_video_buffer() > drm/exynos: mixer: enable NV12MT support for the video plane > drm/exynos: mixer: simplify {vp_video,mixer_graph}_buffer() > drm/exynos: mixer: remove src offset from mixer_graph_buffer() > drm/exynos: introduce BYTE_PITCH capability > drm/exynos: add BYTE_PITCH cap for all supported planes > drm/exynos: consistent use of cpp > drm/exynos: simplify set_pixfmt() in DECON and FIMD drivers > > drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 17 +-- > drivers/gpu/drm/exynos/exynos7_drm_decon.c| 13 +++- > drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 ++ > drivers/gpu/drm/exynos/exynos_drm_fb.c| 2 ++ > drivers/gpu/drm/exynos/exynos_drm_fimd.c | 17 --- > drivers/gpu/drm/exynos/exynos_drm_plane.c | 37 ++ > drivers/gpu/drm/exynos/exynos_mixer.c | 44 > --- > 7 files changed, 71 insertions(+), 61 deletions(-) > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: clean up description of exynos_drm_crtc
Hello Inki, Inki Dae wrote: > 2017년 04월 11일 17:17에 Tobias Jakobi 이(가) 쓴 글: >> Another thing that I noticed. Why wasn't the v2 that ended up in your >> git ever submitted to the mailing list? Because it should have, in >> particular to spot these obvious errors. > > Only comment about this. > > This patch cleans up description of struct exynos_drm_clk - removed > unnecessary descriptions and adds one missed before. > I think no problem to update the description without v2 because no code > change and description enough. I think you miss the point here. I checked the mail thread again and you responded with "More simple and looks better." when I suggested to put the largest part of your description in front of 'struct exynos_drm_clk'. I even went so far as to prepare the comment for you. And then you proceed by ignoring everything and merging some completly different patch. I find this disrespectful. I'm quoting your words here (from [1]): > I'd like to say *maintainer is really not a place for power*, and maintainer > would implicitly have a role to encourage in contribution activity of > contributer. If you really mean this, you should also act accordingly. And that does not mean saying "A" to someone and then doing "B". > If you want to update the description more then you can post it. > Ps. I am not a leisurely person to respond to every little thing. I don't expect you to respond to every little thing. But I expect proper and honest communication. Also a response delay of four weeks is simply not acceptable. And I don't think I'm the only one on dri-devel that thinks that way. With best wishes, Tobias [1] http://www.spinics.net/lists/dri-devel/msg131304.html > > Thanks, > Inki Dae > >> >> - Tobias >> >> >> Tobias Jakobi wrote: >>> Inki Dae wrote: >>>> >>>> >>>> 2017년 04월 10일 19:29에 Tobias Jakobi 이(가) 쓴 글: >>>>> Inki Dae wrote: >>>>>> 2017-04-07 20:40 GMT+09:00 Tobias Jakobi : >>>>>>> Hello Inki, >>>>>>> >>>>>>> >>>>>>> Inki Dae wrote: >>>>>>>> Hello Tobias, >>>>>>>> >>>>>>>> >>>>>>>> 2017년 04월 07일 02:10에 Tobias Jakobi 이(가) 쓴 글: >>>>>>>>> Hello Inki, >>>>>>>>> >>>>>>>>> >>>>>>>>> Inki Dae wrote: >>>>>>>>>> This patch removes unnecessary descriptions on >>>>>>>>>> exynos_drm_crtc structure and adds one description >>>>>>>>>> which specifies what pipe_clk member does. >>>>>>>>>> >>>>>>>>>> pipe_clk support had been added by below patch without any >>>>>>>>>> description, >>>>>>>>>> drm/exynos: add support for pipeline clock to the framework >>>>>>>>> I would put the commit id here. That makes it easier to look up the >>>>>>>>> commit your refer to. >>>>>>>>> >>>>>>>>> >>>>>>>>>> Signed-off-by: Inki Dae >>>>>>>>>> --- >>>>>>>>>> drivers/gpu/drm/exynos/exynos_drm_drv.h | 6 ++ >>>>>>>>>> 1 file changed, 2 insertions(+), 4 deletions(-) >>>>>>>>>> >>>>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>>>> b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>>>> index 527bf1d..b0462cc 100644 >>>>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h >>>>>>>>>> @@ -152,12 +152,10 @@ struct exynos_drm_clk { >>>>>>>>>> * >>>>>>>>>> * @base: crtc object. >>>>>>>>>> * @type: one of EXYNOS_DISPLAY_TYPE_LCD and HDMI. >>>>>>>>>> - * @enabled: if the crtc is enabled or not >>>>>>>>>> - * @event: vblank event that is currently queued for flip >>>>>>>>>> - * @wait_update: wait all pending planes updates to finish >>>>>>>>>> - * @pending_update: number of pending plane updates in this crtc >>>>>>>>
Re: [PATCH v3] drm/exynos: mixer: document YCbCr magic numbers
Hello Inki, Inki Dae wrote: > Tobias, why did you post the patch set 1/2 and 2/2 before? > If these patches can be applied independently - you found out later - then > you need to clarify why you posted them separately. after I posted v1 of the patchset, Andrzej responded with a Reviewed-By for patch 1/2 and suggestions for patch 2/2. I then integrated the suggestions and added the Reviewed-By tag, hence changing both patch 1/2 and 2/2. I then posted v2 of the patchset, because _both_ patches changed. Andrzej then pointed out that the values used in patch 2/2 could be further simplied. I then posted a v3 of patch 2/2, because only this one patch changed. When I pinged you concerning the patches, I specifically did this with v3 of 2/2, and v2 of 1/2. It was perfectly clear which patches I wanted you to pick up. I can understand when maintainers of high-volume subsystems sometimes get patch versions mixed up. But drm-exynos only gets very few patches each cycle. If you have problems dealing with your maintainer duties in a timely manner, I would suggest to contact Daniel Vetter so that exynos is added to drm-misc. I personally think exynos would benefit from such a move. With best wishes, Tobias > > Thanks, > Inki Dae > >> >> >>> >>> I can merge the new one - really trivial - but I think it'd be better you >>> to resend this patch series for other people. >>> >>> This patch set has been removed from my tree. Please resend (not v4) this >>> patch set like below, >>> [PATCH v3 0/2] drm/exynos: clean up mixer driver?? >>> [PATCH v3 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt() >>> [PATCH v3 2/2] drm/exynos: mixer: document YCbCr magic numbers >> Not necessary, just pick up the two patches which for which I already >> pinged you. For you convenience, here are the two on dri-devel patchwork: >> https://patchwork.kernel.org/patch/9617085/ >> https://patchwork.kernel.org/patch/9617493/ >> >> - Tobias >> >> >> >>> >>> Thanks, >>> Inki Dae >>> >>>> >>>> - Tobias >>>> >>>> >>>>> Thanks, >>>>> Inki Dae >>>>> >>>>>> With best wishes, >>>>>> Tobias >>>>>> >>>>>> >>>>>> Tobias Jakobi wrote: >>>>>>> The output stage of the mixer uses YCbCr for the internal >>>>>>> computations, which is the reason that some registers take >>>>>>> YCbCr related data as input. In particular this applies >>>>>>> to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. >>>>>>> >>>>>>> Document the formatting of the data which we write to >>>>>>> these registers. >>>>>>> >>>>>>> While at it, unify wording of comments in the register header. >>>>>>> >>>>>>> Reviewed-by: Andrzej Hajda >>>>>>> Signed-off-by: Tobias Jakobi >>>>>>> --- >>>>>>> Changes in v2: >>>>>>> - use floating point values as input for the macros, as >>>>>>> suggested by Andrzej >>>>>>> - the floating point values have been tuned to exactly match >>>>>>> the values that are currently used >>>>>>> >>>>>>> Changes in v3: >>>>>>> - use only three digit values (pointed out by Andrzej) >>>>>>> >>>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 33 >>>>>>> + >>>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- >>>>>>> 2 files changed, 30 insertions(+), 10 deletions(-) >>>>>>> >>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> index 41d0c36..9648dd5 100644 >>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> @@ -45,6 +45,22 @@ >>>>>>> #define MIXER_WIN_NR 3 >>>>>>> #define VP_DEFAULT_WIN 2 >>>>>>> >>>>>>> +/* >>>>>>> + * Mixer color space conversion coefficient triplet. >>>>>>> + * Used for CSC from RGB to YCbCr. >>>>>>> + * Each coefficient is a 10-bit fixed point numbe
Re: [RFC 0/8] drm/exynos: misc fixes and more
Hello Inki, Inki Dae wrote: > Hello Tobias, > > 2017년 04월 11일 19:52에 Tobias Jakobi 이(가) 쓴 글: >> Hello Inki, >> >> please don't forget to review this series. > > Thanks for your contribution, and don't worry about that. Will review this > series. Thank you for the confirmation! In the meantime, i.e. until we have figured out the IOMMU pagefault, it would make sense to reject the combination "interlaced mode + video plane". Should I prepare a patch for that? With best wishes, Tobias > Just sharing a plan for -next, > > I plan to have pull-request after reviewing a patch set[1] posted by Andrzej. > After that, I will start to review your patch set - we would need to enough > review this RFC patch set. > > It would be very helpful to me if other people could review this. > > > Thanks, > Inki Dae > > [1] https://lists.freedesktop.org/archives/dri-devel/2017-April/138112.html > > >> >> Also some pointers concerning the video plane flickering and the >> interlacing issue would be very welcome. >> >> Looking at the current register defines for MXR_INT_EN suggests that >> there are at least three more type of interrupt available. Any chance >> these could be documented? I hope to get some more insight into this >> issue, which apparantly is caused by insufficient bandwidth. >> >> For the interlacing issue I have done partial progress. I now longer see >> a IOMMU pagefault, but the video plane is heavily corrupted. Also the >> dimensions look wrong. >> >> While I can somehow guess that VP_MODE_LINE_SKIP does, the >> VP_MODE_FIELD_ID_AUTO_TOGGLING flag still remains a mystery to me. If >> possible, I request some documentation for this as well. >> >> >> With best wishes, >> Tobias >> >> >> >> Tobias Jakobi wrote: >>> Hello, >>> >>> some recent work I did on Exynos. Patches are based on [1] and [2]. >>> >>> Summary: >>> (a) Enables support for NV12MT in the mixer. >>> (b) Sanitizes buffer pitch for HW with restrictions. >>> (c) Misc fixes >>> >>> While testing the NV12MT part, I made these interesting observations. >>> >>> (1) I used 1920x1080 XRGB on the primary plane, and 1280x768 on the >>> video plane. With this configuration, it does not matter if you're >>> using NV12 or NV12MT, the video plane occasionally flickers or shows >>> heavy artifacting. Reducing the size of the primary plane, e.g. to >>> 32x32 solves this issue, so my guess is that this is memory bandwidth >>> issue. Does someone know if one can check for buffer underflows of the >>> mixer with respect to data passed from the VP? >>> >>> (2) Using 1920x1080i (so an interlaced mode) and NV12, the board >>> immediately dies with an IOMMU pagefault at address zero. I'm >>> currently investigating this, and it looks like that the VP setup >>> is wrong here. In particular it should be the source (!) height >>> and vertical position that should be halfed in interlaced mode, and >>> not the destination. Need to look more into this. >>> >>> Anyway, both the issues are independant of the patches, so please >>> review! :-) >>> >>> With best wishes, >>> Tobias >>> >>> >>> [1] http://www.spinics.net/lists/linux-samsung-soc/msg58640.html >>> [2] http://www.spinics.net/lists/linux-samsung-soc/msg58644.html >>> >>> Tobias Jakobi (8): >>> drm/exynos: mixer: fix chroma comment in vp_video_buffer() >>> drm/exynos: mixer: enable NV12MT support for the video plane >>> drm/exynos: mixer: simplify {vp_video,mixer_graph}_buffer() >>> drm/exynos: mixer: remove src offset from mixer_graph_buffer() >>> drm/exynos: introduce BYTE_PITCH capability >>> drm/exynos: add BYTE_PITCH cap for all supported planes >>> drm/exynos: consistent use of cpp >>> drm/exynos: simplify set_pixfmt() in DECON and FIMD drivers >>> >>> drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 17 +-- >>> drivers/gpu/drm/exynos/exynos7_drm_decon.c| 13 +++- >>> drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 ++ >>> drivers/gpu/drm/exynos/exynos_drm_fb.c| 2 ++ >>> drivers/gpu/drm/exynos/exynos_drm_fimd.c | 17 --- >>> drivers/gpu/drm/exynos/exynos_drm_plane.c | 37 ++ >>> drivers/gpu/drm/exynos/exynos_mixer.c | 44 >>> --- >>> 7 files changed, 71 insertions(+), 61 deletions(-) >>> >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" >> in >> the body of a message to majord...@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html >> >> >> ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [RFC 0/4] Exynos DRM: add Picture Processor extension
Hello everyone, Marek Szyprowski wrote: > Hi Laurent, > > On 2017-04-20 12:25, Laurent Pinchart wrote: >> Hi Marek, >> >> (CC'ing Sakari Ailus) >> >> Thank you for the patches. >> >> On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote: >>> Dear all, >>> >>> This is an updated proposal for extending EXYNOS DRM API with generic >>> support for hardware modules, which can be used for processing image >>> data >>> from the one memory buffer to another. Typical memory-to-memory >>> operations >>> are: rotation, scaling, colour space conversion or mix of them. This >>> is a >>> follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer >>> processors", which has been rejected as "not really needed in the DRM >>> core": >>> http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html >>> >>> >>> In this proposal I moved all the code to Exynos DRM driver, so now this >>> will be specific only to Exynos DRM. I've also changed the name from >>> framebuffer processor (fbproc) to picture processor (pp) to avoid >>> confusion >>> with fbdev API. >>> >>> Here is a bit more information what picture processors are: >>> >>> Embedded SoCs are known to have a number of hardware blocks, which >>> perform >>> such operations. They can be used in paralel to the main GPU module to >>> offload CPU from processing grapics or video data. One of example use of >>> such modules is implementing video overlay, which usually requires color >>> space conversion from NV12 (or similar) to RGB32 color space and >>> scaling to >>> target window size. >>> >>> The proposed API is heavily inspired by atomic KMS approach - it is also >>> based on DRM objects and their properties. A new DRM object is >>> introduced: >>> picture processor (called pp for convenience). Such objects have a >>> set of >>> standard DRM properties, which describes the operation to be >>> performed by >>> respective hardware module. In typical case those properties are a >>> source >>> fb id and rectangle (x, y, width, height) and destination fb id and >>> rectangle. Optionally a rotation property can be also specified if >>> supported by the given hardware. To perform an operation on image data, >>> userspace provides a set of properties and their values for given fbproc >>> object in a similar way as object and properties are provided for >>> performing atomic page flip / mode setting. >>> >>> The proposed API consists of the 3 new ioctls: >>> - DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture >>>processors, >>> - DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture >>>processor, >>> - DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given >>>property set. >>> >>> The proposed API is extensible. Drivers can attach their own, custom >>> properties to add support for more advanced picture processing (for >>> example >>> blending). >>> >>> This proposal aims to replace Exynos DRM IPP (Image Post Processing) >>> subsystem. IPP API is over-engineered in general, but not really >>> extensible >>> on the other side. It is also buggy, with significant design flaws - the >>> biggest issue is the fact that the API covers memory-2-memory picture >>> operations together with CRTC writeback and duplicating features, which >>> belongs to video plane. Comparing with IPP subsystem, the PP >>> framework is >>> smaller (1807 vs 778 lines) and allows driver simplification (Exynos >>> rotator driver smaller by over 200 lines). >> This seems to be the kind of hardware that is typically supported by >> V4L2. >> Stupid question, why DRM ? > > Let me elaborate a bit on the reasons for implementing it in Exynos DRM: > > 1. we want to replace existing Exynos IPP subsystem: > - it is used only in some internal/vendor trees, not in open-source > - we want it to have sane and potentially extensible userspace API > - but we don't want to loose its functionality > > 2. we want to have simple API for performing single image processing > operation: > - typically it will be used by compositing window manager, this means that >some parameters of the processing might change on each vblank (like >destination rectangle for example). This api allows such change on each >operation without any additional cost. V4L2 requires to reinitialize >queues with new configuration on such change, what means that a bunch of >ioctls has to be called. > - validating processing parameters in V4l2 API is really complicated, >because the parameters (format, src&dest rectangles, rotation) are being >set incrementally, so we have to either allow some impossible, > transitional >configurations or complicate the configuration steps even more (like >calling some ioctls multiple times for both input and output). In the > end >all parameters have to be again validated just before performing the >operation. > > 3. generic approach (to add it to DRM core) has been rejected: > http://www.mail-arc
Re: [RFC 0/4] Exynos DRM: add Picture Processor extension
Hello everyone, Nicolas Dufresne wrote: > Le mercredi 26 avril 2017 à 01:21 +0300, Sakari Ailus a écrit : >> Hi Marek, >> >> On Thu, Apr 20, 2017 at 01:23:09PM +0200, Marek Szyprowski wrote: >>> Hi Laurent, >>> >>> On 2017-04-20 12:25, Laurent Pinchart wrote: Hi Marek, (CC'ing Sakari Ailus) Thank you for the patches. On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote: > Dear all, > > This is an updated proposal for extending EXYNOS DRM API with generic > support for hardware modules, which can be used for processing image data > from the one memory buffer to another. Typical memory-to-memory operations > are: rotation, scaling, colour space conversion or mix of them. This is a > follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer > processors", which has been rejected as "not really needed in the DRM > core": > http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html > > In this proposal I moved all the code to Exynos DRM driver, so now this > will be specific only to Exynos DRM. I've also changed the name from > framebuffer processor (fbproc) to picture processor (pp) to avoid > confusion > with fbdev API. > > Here is a bit more information what picture processors are: > > Embedded SoCs are known to have a number of hardware blocks, which perform > such operations. They can be used in paralel to the main GPU module to > offload CPU from processing grapics or video data. One of example use of > such modules is implementing video overlay, which usually requires color > space conversion from NV12 (or similar) to RGB32 color space and scaling > to > target window size. > > The proposed API is heavily inspired by atomic KMS approach - it is also > based on DRM objects and their properties. A new DRM object is introduced: > picture processor (called pp for convenience). Such objects have a set of > standard DRM properties, which describes the operation to be performed by > respective hardware module. In typical case those properties are a source > fb id and rectangle (x, y, width, height) and destination fb id and > rectangle. Optionally a rotation property can be also specified if > supported by the given hardware. To perform an operation on image data, > userspace provides a set of properties and their values for given fbproc > object in a similar way as object and properties are provided for > performing atomic page flip / mode setting. > > The proposed API consists of the 3 new ioctls: > - DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture > processors, > - DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture > processor, > - DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given > property set. > > The proposed API is extensible. Drivers can attach their own, custom > properties to add support for more advanced picture processing (for > example > blending). > > This proposal aims to replace Exynos DRM IPP (Image Post Processing) > subsystem. IPP API is over-engineered in general, but not really > extensible > on the other side. It is also buggy, with significant design flaws - the > biggest issue is the fact that the API covers memory-2-memory picture > operations together with CRTC writeback and duplicating features, which > belongs to video plane. Comparing with IPP subsystem, the PP framework is > smaller (1807 vs 778 lines) and allows driver simplification (Exynos > rotator driver smaller by over 200 lines). > > Just a side note, we have written code in GStreamer using the Exnynos 4 > FIMC IPP driver. I don't know how many, if any, deployment still exist > (Exynos 4 is relatively old now), but there exist userspace for the > FIMC driver. We use this for color transformation (from tiled to > linear) and scaling. The FIMC driver is in fact quite stable in > upstream kernel today. The GScaler V4L2 M2M driver on Exynos 5 is > largely based on it and has received some maintenance to properly work > in GStreamer. unlike this DRM API, you can reuse the same userspace > code across multiple platforms (which we do already). We have also > integrated this driver in Chromium in the past (not upstream though). > > I am well aware that the blitter driver has not got much attention > though. But again, V4L2 offers a generic interface to userspace > application. Fixing this driver could enable some work like this one: > > https://bugzilla.gnome.org/show_bug.cgi?id=772766 > > This work in progress feature is a generic hardware accelerated video > mixer. It has been tested with IMX.6 v4l2 m2m blitter driver (which I > believe is in staging right now). Again, unlike the exynos/drm, this > code could be reused between platforms. > > In general, the
Re: [RFC 0/4] Exynos DRM: add Picture Processor extension
Hello again, Nicolas Dufresne wrote: > Le mercredi 26 avril 2017 à 01:21 +0300, Sakari Ailus a écrit : >> Hi Marek, >> >> On Thu, Apr 20, 2017 at 01:23:09PM +0200, Marek Szyprowski wrote: >>> Hi Laurent, >>> >>> On 2017-04-20 12:25, Laurent Pinchart wrote: Hi Marek, (CC'ing Sakari Ailus) Thank you for the patches. On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote: > Dear all, > > This is an updated proposal for extending EXYNOS DRM API with generic > support for hardware modules, which can be used for processing image data > from the one memory buffer to another. Typical memory-to-memory operations > are: rotation, scaling, colour space conversion or mix of them. This is a > follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer > processors", which has been rejected as "not really needed in the DRM > core": > http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html > > In this proposal I moved all the code to Exynos DRM driver, so now this > will be specific only to Exynos DRM. I've also changed the name from > framebuffer processor (fbproc) to picture processor (pp) to avoid > confusion > with fbdev API. > > Here is a bit more information what picture processors are: > > Embedded SoCs are known to have a number of hardware blocks, which perform > such operations. They can be used in paralel to the main GPU module to > offload CPU from processing grapics or video data. One of example use of > such modules is implementing video overlay, which usually requires color > space conversion from NV12 (or similar) to RGB32 color space and scaling > to > target window size. > > The proposed API is heavily inspired by atomic KMS approach - it is also > based on DRM objects and their properties. A new DRM object is introduced: > picture processor (called pp for convenience). Such objects have a set of > standard DRM properties, which describes the operation to be performed by > respective hardware module. In typical case those properties are a source > fb id and rectangle (x, y, width, height) and destination fb id and > rectangle. Optionally a rotation property can be also specified if > supported by the given hardware. To perform an operation on image data, > userspace provides a set of properties and their values for given fbproc > object in a similar way as object and properties are provided for > performing atomic page flip / mode setting. > > The proposed API consists of the 3 new ioctls: > - DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture > processors, > - DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture > processor, > - DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given > property set. > > The proposed API is extensible. Drivers can attach their own, custom > properties to add support for more advanced picture processing (for > example > blending). > > This proposal aims to replace Exynos DRM IPP (Image Post Processing) > subsystem. IPP API is over-engineered in general, but not really > extensible > on the other side. It is also buggy, with significant design flaws - the > biggest issue is the fact that the API covers memory-2-memory picture > operations together with CRTC writeback and duplicating features, which > belongs to video plane. Comparing with IPP subsystem, the PP framework is > smaller (1807 vs 778 lines) and allows driver simplification (Exynos > rotator driver smaller by over 200 lines). > > Just a side note, we have written code in GStreamer using the Exnynos 4 > FIMC IPP driver. I don't know how many, if any, deployment still exist > (Exynos 4 is relatively old now), but there exist userspace for the > FIMC driver. I was searching for this code, but I didn't find anything. Are you sure you really mean the FIMC IPP in Exynos DRM, and not just the FIMC driver from the V4L2 subsystem? With best wishes, Tobias > We use this for color transformation (from tiled to > linear) and scaling. The FIMC driver is in fact quite stable in > upstream kernel today. The GScaler V4L2 M2M driver on Exynos 5 is > largely based on it and has received some maintenance to properly work > in GStreamer. unlike this DRM API, you can reuse the same userspace > code across multiple platforms (which we do already). We have also > integrated this driver in Chromium in the past (not upstream though). > > I am well aware that the blitter driver has not got much attention > though. But again, V4L2 offers a generic interface to userspace > application. Fixing this driver could enable some work like this one: > > https://bugzilla.gnome.org/show_bug.cgi?id=772766 > > This work in progress feature is a generic hardware accelerated video > mixe
Re: [RFC 0/4] Exynos DRM: add Picture Processor extension
Hey, Nicolas Dufresne wrote: > Le mercredi 26 avril 2017 à 18:52 +0200, Tobias Jakobi a écrit : >> Hello again, >> >> >> Nicolas Dufresne wrote: >>> Le mercredi 26 avril 2017 à 01:21 +0300, Sakari Ailus a écrit : >>>> Hi Marek, >>>> >>>> On Thu, Apr 20, 2017 at 01:23:09PM +0200, Marek Szyprowski wrote: >>>>> Hi Laurent, >>>>> >>>>> On 2017-04-20 12:25, Laurent Pinchart wrote: >>>>>> Hi Marek, >>>>>> >>>>>> (CC'ing Sakari Ailus) >>>>>> >>>>>> Thank you for the patches. >>>>>> >>>>>> On Thursday 20 Apr 2017 11:13:36 Marek Szyprowski wrote: >>>>>>> Dear all, >>>>>>> >>>>>>> This is an updated proposal for extending EXYNOS DRM API with generic >>>>>>> support for hardware modules, which can be used for processing image >>>>>>> data >>>>>>> from the one memory buffer to another. Typical memory-to-memory >>>>>>> operations >>>>>>> are: rotation, scaling, colour space conversion or mix of them. This is >>>>>>> a >>>>>>> follow-up of my previous proposal "[RFC 0/2] New feature: Framebuffer >>>>>>> processors", which has been rejected as "not really needed in the DRM >>>>>>> core": >>>>>>> http://www.mail-archive.com/dri-devel@lists.freedesktop.org/msg146286.html >>>>>>> >>>>>>> In this proposal I moved all the code to Exynos DRM driver, so now this >>>>>>> will be specific only to Exynos DRM. I've also changed the name from >>>>>>> framebuffer processor (fbproc) to picture processor (pp) to avoid >>>>>>> confusion >>>>>>> with fbdev API. >>>>>>> >>>>>>> Here is a bit more information what picture processors are: >>>>>>> >>>>>>> Embedded SoCs are known to have a number of hardware blocks, which >>>>>>> perform >>>>>>> such operations. They can be used in paralel to the main GPU module to >>>>>>> offload CPU from processing grapics or video data. One of example use of >>>>>>> such modules is implementing video overlay, which usually requires color >>>>>>> space conversion from NV12 (or similar) to RGB32 color space and >>>>>>> scaling to >>>>>>> target window size. >>>>>>> >>>>>>> The proposed API is heavily inspired by atomic KMS approach - it is also >>>>>>> based on DRM objects and their properties. A new DRM object is >>>>>>> introduced: >>>>>>> picture processor (called pp for convenience). Such objects have a set >>>>>>> of >>>>>>> standard DRM properties, which describes the operation to be performed >>>>>>> by >>>>>>> respective hardware module. In typical case those properties are a >>>>>>> source >>>>>>> fb id and rectangle (x, y, width, height) and destination fb id and >>>>>>> rectangle. Optionally a rotation property can be also specified if >>>>>>> supported by the given hardware. To perform an operation on image data, >>>>>>> userspace provides a set of properties and their values for given fbproc >>>>>>> object in a similar way as object and properties are provided for >>>>>>> performing atomic page flip / mode setting. >>>>>>> >>>>>>> The proposed API consists of the 3 new ioctls: >>>>>>> - DRM_IOCTL_EXYNOS_PP_GET_RESOURCES: to enumerate all available picture >>>>>>> processors, >>>>>>> - DRM_IOCTL_EXYNOS_PP_GET: to query capabilities of given picture >>>>>>> processor, >>>>>>> - DRM_IOCTL_EXYNOS_PP_COMMIT: to perform operation described by given >>>>>>> property set. >>>>>>> >>>>>>> The proposed API is extensible. Drivers can attach their own, custom >>>>>>> properties to add support for more advanced picture processing (for >>>>>>> example >>>>>>> blending). >>>>>>> >>
Re: [PATCH v2 1/2] drm/cma-helper: Add multi buffer support for cma fbdev
Hello, I'm not sure if I'm missing something here, but I don't see how this is supposed to work. This just multiplies the height of the drm_mode_fb_cmd2 object with the number of buffers. Let's say I have width=1024, height=768, then now I have a framebuffer which has height=2304 (in the num_buffers=3 case). At some point this FB is set as the primary plane, giving us a 1024x2304 mode. I don't think that this is intended. In my opinion this multi-buffer thing should touch drm_mode_fb_cmd2 at all. The underlying BO should be larger, but not the FB itself. If this is supposed to work, then the fbdev helpers should create as many FBs as there are buffers, and then offset each of these FB into the BO. What I'm also not seeing is code that handles the fbdev's virtual resolutions. After all num_buffers should only increase those. Same for the panning ioctl(). So, is this just a part of a larger series? I remember seeing such a hack in the Hardkernel vendor kernel. But there it only worked because of some bug in the crtc (mixer) code. With best wishes, Tobias P.S.: I'm signed up to dri-devel in digest mode, so sorry if this mail doesn't properly show up in the corresponding ml thread. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 0/8] ARM: sun8i: a33: Mali improvements
Hello, I was wondering about the following. Wasn't there some strict requirement about code going upstream, which also included that there was a full open-source driver stack for it? I don't see how this is the case for Mali, neither in the kernel, nor in userspace. I'm aware that the Mali kernel driver is open-source. But it is not upstream, maintained out of tree, and won't land upstream in its current form (no resemblence to a DRM driver at all). And let's not talk about the userspace part. So, why should this be here? With best wishes, Tobias P.S.: I'm signed up to dri-devel in digest mode, so sorry if this mail doesn't properly show up in the corresponding ml thread. ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 0/8] ARM: sun8i: a33: Mali improvements
Hello Maxime, Maxime Ripard wrote: > Hi, > > On Thu, Feb 16, 2017 at 01:43:06PM +0100, Tobias Jakobi wrote: >> I was wondering about the following. Wasn't there some strict >> requirement about code going upstream, which also included that there >> was a full open-source driver stack for it? >> >> I don't see how this is the case for Mali, neither in the kernel, nor in >> userspace. I'm aware that the Mali kernel driver is open-source. But it >> is not upstream, maintained out of tree, and won't land upstream in its >> current form (no resemblence to a DRM driver at all). And let's not talk >> about the userspace part. >> >> So, why should this be here? > > The device tree is a representation of the hardware itself. The state > of the driver support doesn't change the hardware you're running on, > just like your BIOS/UEFI on x86 won't change the device it reports to > Linux based on whether it has a driver for it. Like Emil already said, the new bindings and the DT entries are solely introduced to support a proprietary out-of-tree module. The current workflow when introducing new DT entries is the following: - upstream a driver that uses the entries - THEN add the new entries I'm against adding such entries without having any upstream "consumer". With best wishes, Tobias > So yes, unfortunately, we don't have a driver upstream at the > moment. But that doesn't prevent us from describing the hardware > accurately. > > Maxime > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 1/2] drm/cma-helper: Add multi buffer support for cma fbdev
Hello Maxime, Maxime Ripard wrote: > Hi, > > On Thu, Feb 16, 2017 at 01:28:24PM +0100, Tobias Jakobi wrote: >> Hello, >> >> I'm not sure if I'm missing something here, but I don't see how this is >> supposed to work. >> >> This just multiplies the height of the drm_mode_fb_cmd2 object with the >> number of buffers. Let's say I have width=1024, height=768, then now I >> have a framebuffer which has height=2304 (in the num_buffers=3 case). At >> some point this FB is set as the primary plane, giving us a 1024x2304 >> mode. I don't think that this is intended. >> >> In my opinion this multi-buffer thing should touch drm_mode_fb_cmd2 at >> all. The underlying BO should be larger, but not the FB itself. If this >> is supposed to work, then the fbdev helpers should create as many FBs as >> there are buffers, and then offset each of these FB into the BO. > > This only increases the virtual resolution, not the visible one. hmm, OK, I guess I need to test this again then. The last time I checked such an approach was on vanilla-4.7.y IIRC. And there it failed miserably. >> What I'm also not seeing is code that handles the fbdev's virtual >> resolutions. After all num_buffers should only increase those. Same for >> the panning ioctl(). > > This is already implemented through drm_fb_helper_pan_display. Thanks, I'll take a look! With best wishes, Tobias > > Maxime > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 0/8] ARM: sun8i: a33: Mali improvements
Alexandre Belloni wrote: > On 17/02/2017 at 13:45:44 +0100, Tobias Jakobi wrote: >>> The device tree is a representation of the hardware itself. The state >>> of the driver support doesn't change the hardware you're running on, >>> just like your BIOS/UEFI on x86 won't change the device it reports to >>> Linux based on whether it has a driver for it. >> Like Emil already said, the new bindings and the DT entries are solely >> introduced to support a proprietary out-of-tree module. >> > > Because device tree describes the hardware, the added binding doesn't > support any particular module. The eventually upstreamed drvier will > share the same bindings. OK, can we then agree that we _only_ merge the bindings and the entries, once this driver is upstream? Driver upstreaming and DT work go hand-in-hand. It's usually after a lot of discussion that new bindings get finalised. And for that discussion to happen we need to know how the driver uses the information from the DT. Otherwise we have no way to evaluate if the description is in any way "appropriate". And no, I don't follow the "DT is a separate/independent thing" thought. It maybe is in an ideal world, but we've seen it now often enough that bindings turned out to be poorly designed, even though they looked fine at first. With best wishes, Tobias > >> The current workflow when introducing new DT entries is the following: >> - upstream a driver that uses the entries >> - THEN add the new entries >> > > Exactly not, if you do that, checkpatch will complain loudly. Because > you must not add a driver using bindings that are not documented first. > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2] drm/exynos/dsi: Remove error handling for bridge_node DT parsing
Hello Hoegeun, my last question (does this regress the case "node required, but absent") still stands. Hoegeun Kwon wrote: > Remove the error handling of bridge_node because the bridge_node is > required optionally. I don't think a construction like that exists. Either it's required, or it's optional. "required optionally" makes no sense to me (but I'm not a native speaker). - Tobias > For example, In case of Exynos SoC, a bridge device such as mDNIe and > MIC could be placed between Display Controller and MIPI DSI device but > the bridge device is required optionally. > > Signed-off-by: Hoegeun Kwon > --- > > Hi Inki and Tobias, > > Thanks for your review. > > Changes for V2: > - Modified the commit message in more detail than before. > > Best Regards, > Hoegeun > > drivers/gpu/drm/exynos/exynos_drm_dsi.c | 2 -- > 1 file changed, 2 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c > b/drivers/gpu/drm/exynos/exynos_drm_dsi.c > index a11b795..6ee0dac 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c > @@ -1651,8 +1651,6 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi) > return ret; > > dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0); > - if (!dsi->bridge_node) > - return -EINVAL; > > return 0; > } > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 2/2] drm/exynos: mixer: document YCbCr magic numbers
The output stage of the mixer uses YCbCr for the internal computations, which is the reason that some registers take YCbCr related data as input. In particular this applies to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. Document the formatting of the data which we write to these registers. While at it, unify wording of comments in the register header. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 35 +++ drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 41d0c36..3b0b07d 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -45,6 +45,20 @@ #define MIXER_WIN_NR 3 #define VP_DEFAULT_WIN 2 +/* + * Mixer color space conversion coefficient triplet. + * Used for CSC from RGB to YCbCr. + * Each coefficient is a 10-bit fixed point number with + * sign and no integer part, i.e. + * [0:8] = fractional part (representing a value y = x / 2^9) + * [9] = sign + * Negative values are encoded with two's complement. + */ +#define MXR_CSC_CT(a0, a1, a2) (((a0) << 20) | ((a1) << 10) | ((a2) << 0)) + +/* YCbCr value, used for mixer background color configuration. */ +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) + /* The pixelformats that are natively supported by the mixer. */ #define MXR_FORMAT_RGB565 4 #define MXR_FORMAT_ARGB15555 @@ -391,13 +405,18 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) case 1080: default: val = MXR_CFG_RGB709_16_235; + /* +* Configure the BT.709 CSC matrix M for full range RGB. +* | 0.1835 0.6132 0.0625| +* M = |-0.1015 -0.3378 0.4394| +* | 0.4394 -0.3984 -0.0390| +*/ mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); + MXR_CSC_CT(0x05E, 0x13A, 0x020) | MXR_CM_COEFF_RGB_FULL); mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); + MXR_CSC_CT(0x3CC, 0x353, 0x0E1)); mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); + MXR_CSC_CT(0x0E1, 0x334, 0x3EC)); break; } @@ -715,10 +734,10 @@ static void mixer_win_reset(struct mixer_context *ctx) /* reset default layer priority */ mixer_reg_write(res, MXR_LAYER_CFG, 0); - /* setting background color */ - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); + /* set all background colors to RGB (0,0,0) */ + mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { /* configuration of Video Processor Registers */ diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index 7f22df5..c311f57 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -140,11 +140,11 @@ #define MXR_INT_EN_VSYNC (1 << 11) #define MXR_INT_EN_ALL (0x0f << 8) -/* bit for MXR_INT_STATUS */ +/* bits for MXR_INT_STATUS */ #define MXR_INT_CLEAR_VSYNC(1 << 11) #define MXR_INT_STATUS_VSYNC (1 << 0) -/* bit for MXR_LAYER_CFG */ +/* bits for MXR_LAYER_CFG */ #define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) #define MXR_LAYER_CFG_GRP1_MASKMXR_LAYER_CFG_GRP1_VAL(~0) #define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) @@ -152,5 +152,8 @@ #define MXR_LAYER_CFG_VP_VAL(x)MXR_MASK_VAL(x, 3, 0) #define MXR_LAYER_CFG_VP_MASK MXR_LAYER_CFG_VP_VAL(~0) +/* bits for MXR_CM_COEFF_Y */ +#define MXR_CM_COEFF_RGB_FULL (1 << 30) + #endif /* SAMSUNG_REGS_MIXER_H */ -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt()
Convert if-statements to switch statement. Removes duplicated code. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 30 -- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 72143ac..41d0c36 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -382,29 +382,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) struct mixer_resources *res = &ctx->mixer_res; u32 val; - if (height == 480) { + switch (height) { + case 480: + case 576: val = MXR_CFG_RGB601_0_255; - } else if (height == 576) { - val = MXR_CFG_RGB601_0_255; - } else if (height == 720) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else if (height == 1080) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else { + break; + case 720: + case 1080: + default: val = MXR_CFG_RGB709_16_235; mixer_reg_write(res, MXR_CM_COEFF_Y, (1 << 30) | (94 << 20) | (314 << 10) | @@ -413,6 +398,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) (972 << 20) | (851 << 10) | (225 << 0)); mixer_reg_write(res, MXR_CM_COEFF_CR, (225 << 20) | (820 << 10) | (1004 << 0)); + break; } mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt()
Hello Andrzej, Andrzej Hajda wrote: > Hi Tobias, > > On 03.03.2017 14:40, Tobias Jakobi wrote: >> Convert if-statements to switch statement. Removes >> duplicated code. >> >> Signed-off-by: Tobias Jakobi >> --- >> drivers/gpu/drm/exynos/exynos_mixer.c | 30 -- >> 1 file changed, 8 insertions(+), 22 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >> b/drivers/gpu/drm/exynos/exynos_mixer.c >> index 72143ac..41d0c36 100644 >> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >> @@ -382,29 +382,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >> *ctx, unsigned int height) >> struct mixer_resources *res = &ctx->mixer_res; >> u32 val; >> >> -if (height == 480) { >> +switch (height) { >> +case 480: >> +case 576: >> val = MXR_CFG_RGB601_0_255; >> -} else if (height == 576) { >> -val = MXR_CFG_RGB601_0_255; >> -} else if (height == 720) { >> -val = MXR_CFG_RGB709_16_235; >> -mixer_reg_write(res, MXR_CM_COEFF_Y, >> -(1 << 30) | (94 << 20) | (314 << 10) | >> -(32 << 0)); >> -mixer_reg_write(res, MXR_CM_COEFF_CB, >> -(972 << 20) | (851 << 10) | (225 << 0)); >> -mixer_reg_write(res, MXR_CM_COEFF_CR, >> -(225 << 20) | (820 << 10) | (1004 << 0)); >> -} else if (height == 1080) { >> -val = MXR_CFG_RGB709_16_235; >> -mixer_reg_write(res, MXR_CM_COEFF_Y, >> -(1 << 30) | (94 << 20) | (314 << 10) | >> -(32 << 0)); >> -mixer_reg_write(res, MXR_CM_COEFF_CB, >> -(972 << 20) | (851 << 10) | (225 << 0)); >> -mixer_reg_write(res, MXR_CM_COEFF_CR, >> -(225 << 20) | (820 << 10) | (1004 << 0)); >> -} else { >> +break; >> +case 720: >> +case 1080: >> +default: >> val = MXR_CFG_RGB709_16_235; >> mixer_reg_write(res, MXR_CM_COEFF_Y, >> (1 << 30) | (94 << 20) | (314 << 10) | >> @@ -413,6 +398,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, >> unsigned int height) >> (972 << 20) | (851 << 10) | (225 << 0)); >> mixer_reg_write(res, MXR_CM_COEFF_CR, >> (225 << 20) | (820 << 10) | (1004 << 0)); >> +break; >> } > > Good change. > Reviewed-by: Andrzej Hajda Thanks for the review. > > One small nitpick. > As I see this conditional/switch is to decide about BT standard > depending on the height. The similar problem is addressed in exynos-gsc > patches [1]. > It would be good to have the same criteria to distinguish SD/HD mode. I > think ((height > 576) || (width > 720)) is more generic, in this case > even (height > 576) looks better, but as this changes logic of the code > it could be in separate patch. I'm not submitting functional changes anymore. You probably still remember how that ended up last time. It's just not worth my time, sorry. With best wishes, Tobias > [1]: https://lkml.org/lkml/2017/2/21/864 > > Regards > Andrzej > >> >> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); > > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH 2/2] drm/exynos: mixer: document YCbCr magic numbers
Hello Andrzej, Andrzej Hajda wrote: > On 03.03.2017 14:40, Tobias Jakobi wrote: >> The output stage of the mixer uses YCbCr for the internal >> computations, which is the reason that some registers take >> YCbCr related data as input. In particular this applies >> to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. >> >> Document the formatting of the data which we write to >> these registers. >> >> While at it, unify wording of comments in the register header. >> >> Signed-off-by: Tobias Jakobi >> --- >> drivers/gpu/drm/exynos/exynos_mixer.c | 35 >> +++ >> drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- >> 2 files changed, 32 insertions(+), 10 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >> b/drivers/gpu/drm/exynos/exynos_mixer.c >> index 41d0c36..3b0b07d 100644 >> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >> @@ -45,6 +45,20 @@ >> #define MIXER_WIN_NR3 >> #define VP_DEFAULT_WIN 2 >> >> +/* >> + * Mixer color space conversion coefficient triplet. >> + * Used for CSC from RGB to YCbCr. >> + * Each coefficient is a 10-bit fixed point number with >> + * sign and no integer part, i.e. > Maybe it would be more clear to say in exclusive range (-1,1) >> + * [0:8] = fractional part (representing a value y = x / 2^9) >> + * [9] = sign >> + * Negative values are encoded with two's complement. >> + */ >> +#define MXR_CSC_CT(a0, a1, a2) (((a0) << 20) | ((a1) << 10) | ((a2) << 0)) > > We can take advantage of the fact that floating point numbers are > allowed in compile time, aren't they? > > #define MXR_CSC_C(x) ((int)((x) * 512) & 0x3ff) > #define MXR_CSC_CT(a0, a1, a2) ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) > << 10) | (MXR_CSC_C(a2) << 0)) > > and stop using magic hexadecimals, now we will use real coefficients. > MXR_CSC_CT(0.1835, 0.6132, 0.0625) I'm not sure if this change of base can be done in a lossless fashion without typing out too many digits [see below]. I haven't done the math here. Like I said, no functional changes. >> + >> +/* YCbCr value, used for mixer background color configuration. */ >> +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) >> + >> /* The pixelformats that are natively supported by the mixer. */ >> #define MXR_FORMAT_RGB565 4 >> #define MXR_FORMAT_ARGB1555 5 >> @@ -391,13 +405,18 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >> *ctx, unsigned int height) >> case 1080: >> default: >> val = MXR_CFG_RGB709_16_235; >> +/* >> + * Configure the BT.709 CSC matrix M for full range RGB. >> + * | 0.1835 0.6132 0.0625| >> + * M = |-0.1015 -0.3378 0.4394| >> + * | 0.4394 -0.3984 -0.0390| > > Out of curiosity, where did you take those values from, datasheet for > Exynos5422 has little bit different matrix. I don't have access to any datasheets. This was done by reverse engineering. M is just the result of putting the current values in a calculator. M is not exact though, e.g. 94 / (2^9) = .18359375. Same for the other values. With best wishes, Tobias > > Regards > Andrzej > >> + */ >> mixer_reg_write(res, MXR_CM_COEFF_Y, >> -(1 << 30) | (94 << 20) | (314 << 10) | >> -(32 << 0)); >> +MXR_CSC_CT(0x05E, 0x13A, 0x020) | >> MXR_CM_COEFF_RGB_FULL); > >> mixer_reg_write(res, MXR_CM_COEFF_CB, >> -(972 << 20) | (851 << 10) | (225 << 0)); >> +MXR_CSC_CT(0x3CC, 0x353, 0x0E1)); >> mixer_reg_write(res, MXR_CM_COEFF_CR, >> -(225 << 20) | (820 << 10) | (1004 << 0)); >> +MXR_CSC_CT(0x0E1, 0x334, 0x3EC)); >> break; >> } >> >> @@ -715,10 +734,10 @@ static void mixer_win_reset(struct mixer_context *ctx) >> /* reset default layer priority */ >> mixer_reg_write(res, MXR_LAYER_CFG, 0); >> >> -/* setting background color */ >> -mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); >> -mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); >> -mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); >> +/* set all backgro
[PATCH v2 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt()
Convert if-statements to switch statement. Removes duplicated code. Reviewed-by: Andrzej Hajda Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 30 -- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 72143ac..41d0c36 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -382,29 +382,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) struct mixer_resources *res = &ctx->mixer_res; u32 val; - if (height == 480) { + switch (height) { + case 480: + case 576: val = MXR_CFG_RGB601_0_255; - } else if (height == 576) { - val = MXR_CFG_RGB601_0_255; - } else if (height == 720) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else if (height == 1080) { - val = MXR_CFG_RGB709_16_235; - mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); - mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); - } else { + break; + case 720: + case 1080: + default: val = MXR_CFG_RGB709_16_235; mixer_reg_write(res, MXR_CM_COEFF_Y, (1 << 30) | (94 << 20) | (314 << 10) | @@ -413,6 +398,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) (972 << 20) | (851 << 10) | (225 << 0)); mixer_reg_write(res, MXR_CM_COEFF_CR, (225 << 20) | (820 << 10) | (1004 << 0)); + break; } mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2 2/2] drm/exynos: mixer: document YCbCr magic numbers
The output stage of the mixer uses YCbCr for the internal computations, which is the reason that some registers take YCbCr related data as input. In particular this applies to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. Document the formatting of the data which we write to these registers. While at it, unify wording of comments in the register header. Signed-off-by: Tobias Jakobi --- Changes in v2: - use floating point values as input for the macros, as suggested by Andrzej - the floating point values have been tuned to exactly match the values that are currently used drivers/gpu/drm/exynos/exynos_mixer.c | 33 + drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 41d0c36..9648dd5 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -45,6 +45,22 @@ #define MIXER_WIN_NR 3 #define VP_DEFAULT_WIN 2 +/* + * Mixer color space conversion coefficient triplet. + * Used for CSC from RGB to YCbCr. + * Each coefficient is a 10-bit fixed point number with + * sign and no integer part, i.e. + * [0:8] = fractional part (representing a value y = x / 2^9) + * [9] = sign + * Negative values are encoded with two's complement. + */ +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) +#define MXR_CSC_CT(a0, a1, a2) \ + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) + +/* YCbCr value, used for mixer background color configuration. */ +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) + /* The pixelformats that are natively supported by the mixer. */ #define MXR_FORMAT_RGB565 4 #define MXR_FORMAT_ARGB15555 @@ -391,13 +407,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) case 1080: default: val = MXR_CFG_RGB709_16_235; + /* Configure the BT.709 CSC matrix for full range RGB. */ mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); + MXR_CSC_CT( 0.1836, 0.6133, 0.0625) | + MXR_CM_COEFF_RGB_FULL); mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); + MXR_CSC_CT(-0.1016, -0.3379, 0.4395)); mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); + MXR_CSC_CT( 0.4395, -0.3985, -0.0391)); break; } @@ -715,10 +732,10 @@ static void mixer_win_reset(struct mixer_context *ctx) /* reset default layer priority */ mixer_reg_write(res, MXR_LAYER_CFG, 0); - /* setting background color */ - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); + /* set all background colors to RGB (0,0,0) */ + mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { /* configuration of Video Processor Registers */ diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index 7f22df5..c311f57 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -140,11 +140,11 @@ #define MXR_INT_EN_VSYNC (1 << 11) #define MXR_INT_EN_ALL (0x0f << 8) -/* bit for MXR_INT_STATUS */ +/* bits for MXR_INT_STATUS */ #define MXR_INT_CLEAR_VSYNC(1 << 11) #define MXR_INT_STATUS_VSYNC (1 << 0) -/* bit for MXR_LAYER_CFG */ +/* bits for MXR_LAYER_CFG */ #define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) #define MXR_LAYER_CFG_GRP1_MASKMXR_LAYER_CFG_GRP1_VAL(~0) #define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) @@ -152,5 +152,8 @@ #define MXR_LAYER_CFG_VP_VAL(x)MXR_MASK_VAL(x, 3, 0) #define MXR_LAYER_CFG_VP_MASK MXR_LAYER_CFG_VP_VAL(~0) +/* bits for MXR_CM_COEFF_Y */ +#define MXR_CM_COEFF_RGB_FULL (1 << 30) + #endif /* SAMSUNG_REGS_MIXER_H */ -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v3] drm/exynos: mixer: document YCbCr magic numbers
The output stage of the mixer uses YCbCr for the internal computations, which is the reason that some registers take YCbCr related data as input. In particular this applies to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. Document the formatting of the data which we write to these registers. While at it, unify wording of comments in the register header. Reviewed-by: Andrzej Hajda Signed-off-by: Tobias Jakobi --- Changes in v2: - use floating point values as input for the macros, as suggested by Andrzej - the floating point values have been tuned to exactly match the values that are currently used Changes in v3: - use only three digit values (pointed out by Andrzej) drivers/gpu/drm/exynos/exynos_mixer.c | 33 + drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 41d0c36..9648dd5 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -45,6 +45,22 @@ #define MIXER_WIN_NR 3 #define VP_DEFAULT_WIN 2 +/* + * Mixer color space conversion coefficient triplet. + * Used for CSC from RGB to YCbCr. + * Each coefficient is a 10-bit fixed point number with + * sign and no integer part, i.e. + * [0:8] = fractional part (representing a value y = x / 2^9) + * [9] = sign + * Negative values are encoded with two's complement. + */ +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) +#define MXR_CSC_CT(a0, a1, a2) \ + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) + +/* YCbCr value, used for mixer background color configuration. */ +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) + /* The pixelformats that are natively supported by the mixer. */ #define MXR_FORMAT_RGB565 4 #define MXR_FORMAT_ARGB15555 @@ -391,13 +407,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) case 1080: default: val = MXR_CFG_RGB709_16_235; + /* Configure the BT.709 CSC matrix for full range RGB. */ mixer_reg_write(res, MXR_CM_COEFF_Y, - (1 << 30) | (94 << 20) | (314 << 10) | - (32 << 0)); + MXR_CSC_CT( 0.184, 0.614, 0.063) | + MXR_CM_COEFF_RGB_FULL); mixer_reg_write(res, MXR_CM_COEFF_CB, - (972 << 20) | (851 << 10) | (225 << 0)); + MXR_CSC_CT(-0.102, -0.338, 0.440)); mixer_reg_write(res, MXR_CM_COEFF_CR, - (225 << 20) | (820 << 10) | (1004 << 0)); + MXR_CSC_CT( 0.440, -0.399, -0.040)); break; } @@ -715,10 +732,10 @@ static void mixer_win_reset(struct mixer_context *ctx) /* reset default layer priority */ mixer_reg_write(res, MXR_LAYER_CFG, 0); - /* setting background color */ - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); + /* set all background colors to RGB (0,0,0) */ + mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { /* configuration of Video Processor Registers */ diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h index 7f22df5..c311f57 100644 --- a/drivers/gpu/drm/exynos/regs-mixer.h +++ b/drivers/gpu/drm/exynos/regs-mixer.h @@ -140,11 +140,11 @@ #define MXR_INT_EN_VSYNC (1 << 11) #define MXR_INT_EN_ALL (0x0f << 8) -/* bit for MXR_INT_STATUS */ +/* bits for MXR_INT_STATUS */ #define MXR_INT_CLEAR_VSYNC(1 << 11) #define MXR_INT_STATUS_VSYNC (1 << 0) -/* bit for MXR_LAYER_CFG */ +/* bits for MXR_LAYER_CFG */ #define MXR_LAYER_CFG_GRP1_VAL(x) MXR_MASK_VAL(x, 11, 8) #define MXR_LAYER_CFG_GRP1_MASKMXR_LAYER_CFG_GRP1_VAL(~0) #define MXR_LAYER_CFG_GRP0_VAL(x) MXR_MASK_VAL(x, 7, 4) @@ -152,5 +152,8 @@ #define MXR_LAYER_CFG_VP_VAL(x)MXR_MASK_VAL(x, 3, 0) #define MXR_LAYER_CFG_VP_MASK MXR_LAYER_CFG_VP_VAL(~0) +/* bits for MXR_CM_COEFF_Y */ +#define MXR_CM_COEFF_RGB_FULL (1 << 30) + #endif /* SAMSUNG_REGS_MIXER_H */ -- 2.7.3 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: Print kernel pointers in a restricted form
Hello Krzysztof, I was wondering about the benefit of this. From a quick look these are all messages that end up in the kernel log / dmesg. IIRC %pK does nothing there, since dmest_restrict is supposed to be used to deny an unpriviliged user the access to the kernel log. Or am I missing something here? - Tobias Krzysztof Kozlowski wrote: > Printing raw kernel pointers might reveal information which sometimes we > try to hide (e.g. with Kernel Address Space Layout Randomization). Use > the "%pK" format so these pointers will be hidden for unprivileged > users. > > Signed-off-by: Krzysztof Kozlowski > --- > drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 ++-- > drivers/gpu/drm/exynos/exynos_drm_fimc.c| 2 +- > drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 +- > drivers/gpu/drm/exynos/exynos_drm_gsc.c | 2 +- > drivers/gpu/drm/exynos/exynos_drm_ipp.c | 22 +++--- > drivers/gpu/drm/exynos/exynos_drm_rotator.c | 2 +- > 6 files changed, 17 insertions(+), 17 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c > b/drivers/gpu/drm/exynos/exynos_drm_dsi.c > index 812e2ec0761d..202526b20b64 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c > @@ -979,7 +979,7 @@ static void exynos_dsi_send_to_fifo(struct exynos_dsi > *dsi, > bool first = !xfer->tx_done; > u32 reg; > > - dev_dbg(dev, "< xfer %p: tx len %u, done %u, rx len %u, done %u\n", > + dev_dbg(dev, "< xfer %pK: tx len %u, done %u, rx len %u, done %u\n", > xfer, length, xfer->tx_done, xfer->rx_len, xfer->rx_done); > > if (length > DSI_TX_FIFO_SIZE) > @@ -1177,7 +1177,7 @@ static bool exynos_dsi_transfer_finish(struct > exynos_dsi *dsi) > spin_unlock_irqrestore(&dsi->transfer_lock, flags); > > dev_dbg(dsi->dev, > - "> xfer %p, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n", > + "> xfer %pK, tx_len %zu, tx_done %u, rx_len %u, rx_done %u\n", > xfer, xfer->packet.payload_length, xfer->tx_done, xfer->rx_len, > xfer->rx_done); > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c > b/drivers/gpu/drm/exynos/exynos_drm_fimc.c > index 95871577015d..5b18b5c5fdf2 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c > @@ -1695,7 +1695,7 @@ static int fimc_probe(struct platform_device *pdev) > goto err_put_clk; > } > > - DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv); > + DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv); > > spin_lock_init(&ctx->lock); > platform_set_drvdata(pdev, ctx); > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c > b/drivers/gpu/drm/exynos/exynos_drm_gem.c > index 4c28f7ffcc4d..55a1579d11b3 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c > @@ -218,7 +218,7 @@ static struct exynos_drm_gem *exynos_drm_gem_init(struct > drm_device *dev, > return ERR_PTR(ret); > } > > - DRM_DEBUG_KMS("created file object = %p\n", obj->filp); > + DRM_DEBUG_KMS("created file object = %pK\n", obj->filp); > > return exynos_gem; > } > diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c > b/drivers/gpu/drm/exynos/exynos_drm_gsc.c > index bef57987759d..0506b2b17ac1 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c > @@ -1723,7 +1723,7 @@ static int gsc_probe(struct platform_device *pdev) > return ret; > } > > - DRM_DEBUG_KMS("id[%d]ippdrv[%p]\n", ctx->id, ippdrv); > + DRM_DEBUG_KMS("id[%d]ippdrv[%pK]\n", ctx->id, ippdrv); > > mutex_init(&ctx->lock); > platform_set_drvdata(pdev, ctx); > diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c > b/drivers/gpu/drm/exynos/exynos_drm_ipp.c > index 9c84ee76f18a..3edda18cc2d2 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c > @@ -208,7 +208,7 @@ static struct exynos_drm_ippdrv > *ipp_find_drv_by_handle(u32 prop_id) >* e.g PAUSE state, queue buf, command control. >*/ > list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { > - DRM_DEBUG_KMS("count[%d]ippdrv[%p]\n", count++, ippdrv); > + DRM_DEBUG_KMS("count[%d]ippdrv[%pK]\n", count++, ippdrv); > > mutex_lock(&ippdrv->cmd_lock); > list_for_each_entry(c_node, &ippdrv->cmd_list, list) { > @@ -388,7 +388,7 @@ int exynos_drm_ipp_set_property(struct drm_device > *drm_dev, void *data, > } > property->prop_id = ret; > > - DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%p]\n", > + DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[%pK]\n", > property->prop_id, property->cmd, ippdrv); > > /* stored property information and ippdrv in private data */ > @@ -518,7 +518,7 @@ static int ipp
Re: [PATCH] drm/exynos: Print kernel pointers in a restricted form
Krzysztof Kozlowski wrote: > On Tue, Mar 14, 2017 at 08:01:41PM +0100, Tobias Jakobi wrote: >> Hello Krzysztof, >> >> I was wondering about the benefit of this. From a quick look these are >> all messages that end up in the kernel log / dmesg. >> >> IIRC %pK does nothing there, since dmest_restrict is supposed to be used >> to deny an unpriviliged user the access to the kernel log. >> >> Or am I missing something here? > > These are regular printks so depending on kernel options (e.g. dynamic > debug, drm.debug) these might be printed also in the console. Of course > we could argue then if access to one of the consoles is worth > securing. This here suggests otherwise. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/sysctl/kernel.txt#n388 I have not tested this, but IIRC %pK is not honored by the kernel logging infrastucture. That's why dmesg_restrict is there. Correct me if I'm wrong. - Tobias > Actually, I think that we should get rid of printing of these kernel > pointers entirely... > > > Best regards, > Krzysztof > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: Print kernel pointers in a restricted form
Krzysztof Kozlowski wrote: > On Tue, Mar 14, 2017 at 08:17:35PM +0100, Tobias Jakobi wrote: >> Krzysztof Kozlowski wrote: >>> On Tue, Mar 14, 2017 at 08:01:41PM +0100, Tobias Jakobi wrote: >>>> Hello Krzysztof, >>>> >>>> I was wondering about the benefit of this. From a quick look these are >>>> all messages that end up in the kernel log / dmesg. >>>> >>>> IIRC %pK does nothing there, since dmest_restrict is supposed to be used >>>> to deny an unpriviliged user the access to the kernel log. >>>> >>>> Or am I missing something here? >>> >>> These are regular printks so depending on kernel options (e.g. dynamic >>> debug, drm.debug) these might be printed also in the console. Of course >>> we could argue then if access to one of the consoles is worth >>> securing. >> This here suggests otherwise. >> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/sysctl/kernel.txt#n388 >> >> I have not tested this, but IIRC %pK is not honored by the kernel >> logging infrastucture. That's why dmesg_restrict is there. >> >> Correct me if I'm wrong. > > The %pK will not help for dmesg or /proc/kmsg but it will help for > console (/dev/ttySACN, ttySN etc) because effectively it uses the same > vsprintf()/pointer() functions. Thanks for the explanation, I didn't know that there was a difference there. In that case, looks good to me. > As I said, we could argue whether securing console is worth... usually > attacker having access to it has also physical access to the machine so > everything gets easier... Still, putting %pK there certainly doesn't hurt. - Tobias > > Best regards, > Krzysztof > > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majord...@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/exynos: Print kernel pointers in a restricted form
Hello Andrzej, note that i had already pointed Krzysztof to that documentation in my previous mail. - Tobias Andrzej Hajda wrote: > Hi Tobias, > > On 14.03.2017 21:41, Tobias Jakobi wrote: >> Krzysztof Kozlowski wrote: >>> On Tue, Mar 14, 2017 at 08:17:35PM +0100, Tobias Jakobi wrote: >>>> Krzysztof Kozlowski wrote: >>>>> On Tue, Mar 14, 2017 at 08:01:41PM +0100, Tobias Jakobi wrote: >>>>>> Hello Krzysztof, >>>>>> >>>>>> I was wondering about the benefit of this. From a quick look these are >>>>>> all messages that end up in the kernel log / dmesg. >>>>>> >>>>>> IIRC %pK does nothing there, since dmest_restrict is supposed to be used >>>>>> to deny an unpriviliged user the access to the kernel log. >>>>>> >>>>>> Or am I missing something here? >>>>> These are regular printks so depending on kernel options (e.g. dynamic >>>>> debug, drm.debug) these might be printed also in the console. Of course >>>>> we could argue then if access to one of the consoles is worth >>>>> securing. >>>> This here suggests otherwise. >>>> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/sysctl/kernel.txt#n388 >>>> >>>> I have not tested this, but IIRC %pK is not honored by the kernel >>>> logging infrastucture. That's why dmesg_restrict is there. >>>> >>>> Correct me if I'm wrong. >>> The %pK will not help for dmesg or /proc/kmsg but it will help for >>> console (/dev/ttySACN, ttySN etc) because effectively it uses the same >>> vsprintf()/pointer() functions. >> Thanks for the explanation, I didn't know that there was a difference >> there. In that case, looks good to me. >> >> > > Just to clarify %pK: > > Documentation/printk-formats.txt: > %pK 0x01234567 or 0x0123456789abcdef > > For printing kernel pointers which should be hidden from > unprivileged > users. The behaviour of %pK depends on the kptr_restrict sysctl > - see > Documentation/sysctl/kernel.txt for more details. > > Documentation/sysctl/kernel.txt: > > kptr_restrict: > > This toggle indicates whether restrictions are placed on > exposing kernel addresses via /proc and other interfaces. > > When kptr_restrict is set to (0), the default, there are no restrictions. > > When kptr_restrict is set to (1), kernel pointers printed using the %pK > format specifier will be replaced with 0's unless the user has CAP_SYSLOG > and effective user and group ids are equal to the real ids. This is > because %pK checks are done at read() time rather than open() time, so > if permissions are elevated between the open() and the read() (e.g via > a setuid binary) then %pK will not leak kernel pointers to unprivileged > users. Note, this is a temporary solution only. The correct long-term > solution is to do the permission checks at open() time. Consider removing > world read permissions from files that use %pK, and using dmesg_restrict > to protect against uses of %pK in dmesg(8) if leaking kernel pointer > values to unprivileged users is a concern. > > When kptr_restrict is set to (2), kernel pointers printed using > %pK will be replaced with 0's regardless of privileges. > --- > > Regards > Andrzej > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v2 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt()
Gentle ping. - Tobias Tobias Jakobi wrote: > Convert if-statements to switch statement. Removes > duplicated code. > > Reviewed-by: Andrzej Hajda > Signed-off-by: Tobias Jakobi > --- > drivers/gpu/drm/exynos/exynos_mixer.c | 30 -- > 1 file changed, 8 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c > b/drivers/gpu/drm/exynos/exynos_mixer.c > index 72143ac..41d0c36 100644 > --- a/drivers/gpu/drm/exynos/exynos_mixer.c > +++ b/drivers/gpu/drm/exynos/exynos_mixer.c > @@ -382,29 +382,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context > *ctx, unsigned int height) > struct mixer_resources *res = &ctx->mixer_res; > u32 val; > > - if (height == 480) { > + switch (height) { > + case 480: > + case 576: > val = MXR_CFG_RGB601_0_255; > - } else if (height == 576) { > - val = MXR_CFG_RGB601_0_255; > - } else if (height == 720) { > - val = MXR_CFG_RGB709_16_235; > - mixer_reg_write(res, MXR_CM_COEFF_Y, > - (1 << 30) | (94 << 20) | (314 << 10) | > - (32 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CB, > - (972 << 20) | (851 << 10) | (225 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CR, > - (225 << 20) | (820 << 10) | (1004 << 0)); > - } else if (height == 1080) { > - val = MXR_CFG_RGB709_16_235; > - mixer_reg_write(res, MXR_CM_COEFF_Y, > - (1 << 30) | (94 << 20) | (314 << 10) | > - (32 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CB, > - (972 << 20) | (851 << 10) | (225 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CR, > - (225 << 20) | (820 << 10) | (1004 << 0)); > - } else { > + break; > + case 720: > + case 1080: > + default: > val = MXR_CFG_RGB709_16_235; > mixer_reg_write(res, MXR_CM_COEFF_Y, > (1 << 30) | (94 << 20) | (314 << 10) | > @@ -413,6 +398,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, > unsigned int height) > (972 << 20) | (851 << 10) | (225 << 0)); > mixer_reg_write(res, MXR_CM_COEFF_CR, > (225 << 20) | (820 << 10) | (1004 << 0)); > + break; > } > > mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3] drm/exynos: mixer: document YCbCr magic numbers
Gentle ping. - Tobias Tobias Jakobi wrote: > The output stage of the mixer uses YCbCr for the internal > computations, which is the reason that some registers take > YCbCr related data as input. In particular this applies > to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. > > Document the formatting of the data which we write to > these registers. > > While at it, unify wording of comments in the register header. > > Reviewed-by: Andrzej Hajda > Signed-off-by: Tobias Jakobi > --- > Changes in v2: > - use floating point values as input for the macros, as > suggested by Andrzej > - the floating point values have been tuned to exactly match > the values that are currently used > > Changes in v3: > - use only three digit values (pointed out by Andrzej) > > drivers/gpu/drm/exynos/exynos_mixer.c | 33 + > drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- > 2 files changed, 30 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c > b/drivers/gpu/drm/exynos/exynos_mixer.c > index 41d0c36..9648dd5 100644 > --- a/drivers/gpu/drm/exynos/exynos_mixer.c > +++ b/drivers/gpu/drm/exynos/exynos_mixer.c > @@ -45,6 +45,22 @@ > #define MIXER_WIN_NR 3 > #define VP_DEFAULT_WIN 2 > > +/* > + * Mixer color space conversion coefficient triplet. > + * Used for CSC from RGB to YCbCr. > + * Each coefficient is a 10-bit fixed point number with > + * sign and no integer part, i.e. > + * [0:8] = fractional part (representing a value y = x / 2^9) > + * [9] = sign > + * Negative values are encoded with two's complement. > + */ > +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) > +#define MXR_CSC_CT(a0, a1, a2) \ > + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) > + > +/* YCbCr value, used for mixer background color configuration. */ > +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) > + > /* The pixelformats that are natively supported by the mixer. */ > #define MXR_FORMAT_RGB5654 > #define MXR_FORMAT_ARGB1555 5 > @@ -391,13 +407,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context > *ctx, unsigned int height) > case 1080: > default: > val = MXR_CFG_RGB709_16_235; > + /* Configure the BT.709 CSC matrix for full range RGB. */ > mixer_reg_write(res, MXR_CM_COEFF_Y, > - (1 << 30) | (94 << 20) | (314 << 10) | > - (32 << 0)); > + MXR_CSC_CT( 0.184, 0.614, 0.063) | > + MXR_CM_COEFF_RGB_FULL); > mixer_reg_write(res, MXR_CM_COEFF_CB, > - (972 << 20) | (851 << 10) | (225 << 0)); > + MXR_CSC_CT(-0.102, -0.338, 0.440)); > mixer_reg_write(res, MXR_CM_COEFF_CR, > - (225 << 20) | (820 << 10) | (1004 << 0)); > + MXR_CSC_CT( 0.440, -0.399, -0.040)); > break; > } > > @@ -715,10 +732,10 @@ static void mixer_win_reset(struct mixer_context *ctx) > /* reset default layer priority */ > mixer_reg_write(res, MXR_LAYER_CFG, 0); > > - /* setting background color */ > - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); > - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); > - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); > + /* set all background colors to RGB (0,0,0) */ > + mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); > + mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); > + mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); > > if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { > /* configuration of Video Processor Registers */ > diff --git a/drivers/gpu/drm/exynos/regs-mixer.h > b/drivers/gpu/drm/exynos/regs-mixer.h > index 7f22df5..c311f57 100644 > --- a/drivers/gpu/drm/exynos/regs-mixer.h > +++ b/drivers/gpu/drm/exynos/regs-mixer.h > @@ -140,11 +140,11 @@ > #define MXR_INT_EN_VSYNC (1 << 11) > #define MXR_INT_EN_ALL (0x0f << 8) > > -/* bit for MXR_INT_STATUS */ > +/* bits for MXR_INT_STATUS */ > #define MXR_INT_CLEAR_VSYNC (1 << 11) > #define MXR_INT_STATUS_VSYNC (1 << 0) > > -/* bit for MXR_LAYER_CFG */ > +/* bits for MXR_LAYER_CFG */ > #define MXR_LAYER_CFG_GRP1_VAL(x)MXR_MASK_VAL(x, 11, 8) > #define MXR_LAYER_CFG_GRP1_MASK MXR_LAYER_CFG_GRP1_VA
Re: [PATCH v2 1/2] drm/exynos: mixer: simplify mixer_cfg_rgb_fmt()
Hello Daniel, I'm not getting any response from the Exynos DRM maintainer concerning this patch. Since this is just a simple cleanup, and Andrzej has already review, could you perhaps merge it through drm-misc? With best wishes, Tobias Tobias Jakobi wrote: > Convert if-statements to switch statement. Removes > duplicated code. > > Reviewed-by: Andrzej Hajda > Signed-off-by: Tobias Jakobi > --- > drivers/gpu/drm/exynos/exynos_mixer.c | 30 -- > 1 file changed, 8 insertions(+), 22 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c > b/drivers/gpu/drm/exynos/exynos_mixer.c > index 72143ac..41d0c36 100644 > --- a/drivers/gpu/drm/exynos/exynos_mixer.c > +++ b/drivers/gpu/drm/exynos/exynos_mixer.c > @@ -382,29 +382,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context > *ctx, unsigned int height) > struct mixer_resources *res = &ctx->mixer_res; > u32 val; > > - if (height == 480) { > + switch (height) { > + case 480: > + case 576: > val = MXR_CFG_RGB601_0_255; > - } else if (height == 576) { > - val = MXR_CFG_RGB601_0_255; > - } else if (height == 720) { > - val = MXR_CFG_RGB709_16_235; > - mixer_reg_write(res, MXR_CM_COEFF_Y, > - (1 << 30) | (94 << 20) | (314 << 10) | > - (32 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CB, > - (972 << 20) | (851 << 10) | (225 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CR, > - (225 << 20) | (820 << 10) | (1004 << 0)); > - } else if (height == 1080) { > - val = MXR_CFG_RGB709_16_235; > - mixer_reg_write(res, MXR_CM_COEFF_Y, > - (1 << 30) | (94 << 20) | (314 << 10) | > - (32 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CB, > - (972 << 20) | (851 << 10) | (225 << 0)); > - mixer_reg_write(res, MXR_CM_COEFF_CR, > - (225 << 20) | (820 << 10) | (1004 << 0)); > - } else { > + break; > + case 720: > + case 1080: > + default: > val = MXR_CFG_RGB709_16_235; > mixer_reg_write(res, MXR_CM_COEFF_Y, > (1 << 30) | (94 << 20) | (314 << 10) | > @@ -413,6 +398,7 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, > unsigned int height) > (972 << 20) | (851 << 10) | (225 << 0)); > mixer_reg_write(res, MXR_CM_COEFF_CR, > (225 << 20) | (820 << 10) | (1004 << 0)); > + break; > } > > mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); > ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH v3] drm/exynos: mixer: document YCbCr magic numbers
Hello Daniel, same question here. Patch doesn't introduce any functional changes (just adds code documentation), so can you merge it through drm-misc? With best wishes, Tobias Tobias Jakobi wrote: > The output stage of the mixer uses YCbCr for the internal > computations, which is the reason that some registers take > YCbCr related data as input. In particular this applies > to MXR_BG_COLOR{0,1,2} and MXR_CM_COEFF_{Y,CB,CR}. > > Document the formatting of the data which we write to > these registers. > > While at it, unify wording of comments in the register header. > > Reviewed-by: Andrzej Hajda > Signed-off-by: Tobias Jakobi > --- > Changes in v2: > - use floating point values as input for the macros, as > suggested by Andrzej > - the floating point values have been tuned to exactly match > the values that are currently used > > Changes in v3: > - use only three digit values (pointed out by Andrzej) > > drivers/gpu/drm/exynos/exynos_mixer.c | 33 + > drivers/gpu/drm/exynos/regs-mixer.h | 7 +-- > 2 files changed, 30 insertions(+), 10 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c > b/drivers/gpu/drm/exynos/exynos_mixer.c > index 41d0c36..9648dd5 100644 > --- a/drivers/gpu/drm/exynos/exynos_mixer.c > +++ b/drivers/gpu/drm/exynos/exynos_mixer.c > @@ -45,6 +45,22 @@ > #define MIXER_WIN_NR 3 > #define VP_DEFAULT_WIN 2 > > +/* > + * Mixer color space conversion coefficient triplet. > + * Used for CSC from RGB to YCbCr. > + * Each coefficient is a 10-bit fixed point number with > + * sign and no integer part, i.e. > + * [0:8] = fractional part (representing a value y = x / 2^9) > + * [9] = sign > + * Negative values are encoded with two's complement. > + */ > +#define MXR_CSC_C(x) ((int)((x) * 512.0) & 0x3ff) > +#define MXR_CSC_CT(a0, a1, a2) \ > + ((MXR_CSC_C(a0) << 20) | (MXR_CSC_C(a1) << 10) | (MXR_CSC_C(a2) << 0)) > + > +/* YCbCr value, used for mixer background color configuration. */ > +#define MXR_YCBCR_VAL(y, cb, cr) (((y) << 16) | ((cb) << 8) | ((cr) << 0)) > + > /* The pixelformats that are natively supported by the mixer. */ > #define MXR_FORMAT_RGB5654 > #define MXR_FORMAT_ARGB1555 5 > @@ -391,13 +407,14 @@ static void mixer_cfg_rgb_fmt(struct mixer_context > *ctx, unsigned int height) > case 1080: > default: > val = MXR_CFG_RGB709_16_235; > + /* Configure the BT.709 CSC matrix for full range RGB. */ > mixer_reg_write(res, MXR_CM_COEFF_Y, > - (1 << 30) | (94 << 20) | (314 << 10) | > - (32 << 0)); > + MXR_CSC_CT( 0.184, 0.614, 0.063) | > + MXR_CM_COEFF_RGB_FULL); > mixer_reg_write(res, MXR_CM_COEFF_CB, > - (972 << 20) | (851 << 10) | (225 << 0)); > + MXR_CSC_CT(-0.102, -0.338, 0.440)); > mixer_reg_write(res, MXR_CM_COEFF_CR, > - (225 << 20) | (820 << 10) | (1004 << 0)); > + MXR_CSC_CT( 0.440, -0.399, -0.040)); > break; > } > > @@ -715,10 +732,10 @@ static void mixer_win_reset(struct mixer_context *ctx) > /* reset default layer priority */ > mixer_reg_write(res, MXR_LAYER_CFG, 0); > > - /* setting background color */ > - mixer_reg_write(res, MXR_BG_COLOR0, 0x008080); > - mixer_reg_write(res, MXR_BG_COLOR1, 0x008080); > - mixer_reg_write(res, MXR_BG_COLOR2, 0x008080); > + /* set all background colors to RGB (0,0,0) */ > + mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); > + mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); > + mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); > > if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { > /* configuration of Video Processor Registers */ > diff --git a/drivers/gpu/drm/exynos/regs-mixer.h > b/drivers/gpu/drm/exynos/regs-mixer.h > index 7f22df5..c311f57 100644 > --- a/drivers/gpu/drm/exynos/regs-mixer.h > +++ b/drivers/gpu/drm/exynos/regs-mixer.h > @@ -140,11 +140,11 @@ > #define MXR_INT_EN_VSYNC (1 << 11) > #define MXR_INT_EN_ALL (0x0f << 8) > > -/* bit for MXR_INT_STATUS */ > +/* bits for MXR_INT_STATUS */ > #define MXR_INT_CLEAR_VSYNC (1 << 11) > #define MXR_INT_STATUS_VSYNC (1 << 0) > > -/* bit for MXR_LAYER_CFG */ > +/* bits
[PATCH] exynos-drm: Fix display manager failing to start without IOMMU problem
Hello Shuah, Shuah Khan wrote: > On 10/19/2016 04:27 PM, Shuah Khan wrote: >> On 10/19/2016 08:16 AM, Inki Dae wrote: >>> Hi Shuah, >>> >>> 2016-10-13 8:11 GMT+09:00 Shuah Khan : Hi Inki, On 08/15/2016 10:40 PM, Inki Dae wrote: >> >> okay the very first commit that added IOMMU support >> introduced the code that rejects non-contig gem memory >> type without IOMMU. >> >> commit 0519f9a12d0113caab78980c48a7902d2bd40c2c >> Author: Inki Dae >> Date: Sat Oct 20 07:53:42 2012 -0700 >> >> drm/exynos: add iommu support for exynos drm framework >> I haven't given up on this yet. I am still seeing the following failure: Additional debug messages I added: [ 15.287403] exynos_drm_gem_create_ioctl() 1 [ 15.287419] exynos_drm_gem_create() flags 1 [ 15.311511] [drm:exynos_drm_framebuffer_init] *ERROR* Non-contiguous GEM memory is not supported. Additional debug message I added: [ 15.318981] [drm:exynos_user_fb_create] *ERROR* failed to initialize framebuffer This is what happens: 1. exynos_drm_gem_create_ioctl() gets called with EXYNOS_BO_NONCONTIG request 2. exynos_drm_gem_create(0 goes ahead and creates the GEM buffers 3. exynos_user_fb_create() tries to associate GEM to fb and fails during check_fb_gem_memory_type() At this point, there is no recovery and lightdm fails xf86-video-armsoc/src/drmmode_exynos/drmmode_exynos.c assumes contiguous allocations are not supported in some exynos drm versions: The following commit introduced this change: https://git.linaro.org/arm/xorg/driver/xf86-video-armsoc.git/commitdiff/3be1f6273441fe95dd442f44064387322e16b7e9 excerpts from the diff:- if (create_gem->buf_type == ARMSOC_BO_SCANOUT) - create_exynos.flags = EXYNOS_BO_CONTIG; - else - create_exynos.flags = EXYNOS_BO_NONCONTIG; + + /* Contiguous allocations are not supported in some exynos drm versions. +* When they are supported all allocations are effectively contiguous +* anyway, so for simplicity we always request non contiguous buffers. +*/ + create_exynos.flags = EXYNOS_BO_NONCONTIG; >>> >>> Above comment, "Contiguous allocations are not supported in some >>> exynos drm versions.", seems wrong assumption. >>> The root cause, contiguous allocation is not supported, would be that >>> they used Linux kernel which didn't have CMA region enough - as >>> default 16MB, or didn't declare CMA region enough for the DMA device. >>> So I think they should not force to flag EXYNOS_BO_NONCONTIG and they >>> should manage the error case if the allocation failed. >> >> This assumption doesn't sound correct and forcing NONCONTIG isn't right >> either. >> >>> There might have been logic on exynos_drm that forced Contig when it coudn't support NONCONTIG. At least, that is what this comment suggests. This assumption doesn't appear to be a good one and not sure if this change was made to fix a bug. After the IOMMU support, this assumption is no longer true. Hence, with IOMMU support, latest kernels have a mismatch with the installed xf86-video-armsoc This is what I am running into. This leads to the following question: 1. How do we ensure exynos_drm kernel changes don't break user-space specifically xf86-video-armsoc 2. This seems to have gone undetected for a while. I see a change in exynos_drm_gem_dumb_create() that is probably addressing this type of breakage. Commit 122beea84bb90236b1ae545f08267af58591c21b adds handling for IOMMU NONCONTIG case. >>> >>> Seems this patch has a problem. This patch forces to flag NONCONTIG if >>> iommu is enabled. The flag should be depend on the argument from >>> user-space. >>> I.e., if user-space requested a gem allocation with CONTIG flag, then >>> Exynos drm driver should allocate contiguous memory even though iommu >>> is enabled. >>> Anyway, I am interested in getting the exynos_drm kernel side code and xf86-video-armsoc in sync to resolve the issue. Could you recommend a going forward plan? >>> >>> My opinion are, >>> >>> 1. Do not force to flag EXYNOS_BO_NONCONTIG at xf86-video-armsoc > > Okay more on this. I fixed xf86-video-armso to ask for EXYNOS_BO_CONTIG > for ARMSOC_BO_SCANOUT and EXYNOS_BO_NONCONTIG in all other cases. > > Revert of the commit: 3be1f6273441fe95dd442f44064387322e16b7e9 > > With this change, now display manager starts just fine. However, it turns > out xf86-video-armsoc is obsoleted in favor of xf86-video-modesetting. The > last update to xf86-video-armsoc git was 3 years ago. IIRC xf86-video-armsoc was created to facilitate integration with the propri
[RFC PATCH] drm/exynos: fix pending update handling
Hello everyone, any update on this issue? I can see that the old/custom wait-for-vblank code is still in place. Andrzej mentioned that this patch is quick/dirty, but isn't using DRM core functionality actually the better approach? With best wishes, Tobias Andrzej Hajda wrote: > Exynos DRM devices update their registers at vblank time. Exynos-DRM uses > custom mechanism to wait for vblank. This mechanism is error prone - > variables are not updated atomically. As a result in certain circumstances > user space can try to free buffers which are still in use by hardware, > in such cases IOMMU can throw OOPS. > The patch instead of fixing the mechanism replaces it with drm core helper. > > Signed-off-by: Andrzej Hajda > --- > Hi Tobias, > > This is a quick/dirty patch just for checking if it solves your issue. > Successfully tested on decon5433/dsi/i80 path. > > Please verify if it helps in your case. > > The patch is based on exynos-drm-next and > "drm/exynos: fix cancel page flip code" [1]. > > [1]: http://permalink.gmane.org/gmane.linux.kernel.samsung-soc/53801 > > Regards > Andrzej > --- > drivers/gpu/drm/exynos/exynos_drm_crtc.c | 16 +--- > drivers/gpu/drm/exynos/exynos_drm_drv.c | 44 > +--- > drivers/gpu/drm/exynos/exynos_drm_drv.h | 2 -- > 3 files changed, 2 insertions(+), 60 deletions(-) > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c > b/drivers/gpu/drm/exynos/exynos_drm_crtc.c > index 785ffa6..5b6845b 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c > @@ -134,8 +134,6 @@ struct exynos_drm_crtc *exynos_drm_crtc_create(struct > drm_device *drm_dev, > exynos_crtc->ops = ops; > exynos_crtc->ctx = ctx; > > - init_waitqueue_head(&exynos_crtc->wait_update); > - > crtc = &exynos_crtc->base; > > private->crtc[pipe] = crtc; > @@ -175,13 +173,6 @@ void exynos_drm_crtc_disable_vblank(struct drm_device > *dev, unsigned int pipe) > exynos_crtc->ops->disable_vblank(exynos_crtc); > } > > -void exynos_drm_crtc_wait_pending_update(struct exynos_drm_crtc *exynos_crtc) > -{ > - wait_event_timeout(exynos_crtc->wait_update, > -(atomic_read(&exynos_crtc->pending_update) == 0), > -msecs_to_jiffies(50)); > -} > - > void exynos_drm_crtc_finish_update(struct exynos_drm_crtc *exynos_crtc, > struct exynos_drm_plane *exynos_plane) > { > @@ -190,9 +181,6 @@ void exynos_drm_crtc_finish_update(struct exynos_drm_crtc > *exynos_crtc, > > exynos_plane->pending_fb = NULL; > > - if (atomic_dec_and_test(&exynos_crtc->pending_update)) > - wake_up(&exynos_crtc->wait_update); > - > spin_lock_irqsave(&crtc->dev->event_lock, flags); > if (exynos_crtc->event) > drm_crtc_send_vblank_event(crtc, exynos_crtc->event); > @@ -235,10 +223,8 @@ void exynos_drm_crtc_cancel_page_flip(struct drm_crtc > *crtc, > spin_lock_irqsave(&crtc->dev->event_lock, flags); > > e = exynos_crtc->event; > - if (e && e->base.file_priv == file) { > + if (e && e->base.file_priv == file) > exynos_crtc->event = NULL; > - atomic_dec(&exynos_crtc->pending_update); > - } > > spin_unlock_irqrestore(&crtc->dev->event_lock, flags); > > diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c > b/drivers/gpu/drm/exynos/exynos_drm_drv.c > index 0281b30..cc96e85 100644 > --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c > +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c > @@ -45,37 +45,11 @@ struct exynos_atomic_commit { > u32 crtcs; > }; > > -static void exynos_atomic_wait_for_commit(struct drm_atomic_state *state) > -{ > - struct drm_crtc_state *crtc_state; > - struct drm_crtc *crtc; > - int i, ret; > - > - for_each_crtc_in_state(state, crtc, crtc_state, i) { > - struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); > - > - if (!crtc->state->enable) > - continue; > - > - ret = drm_crtc_vblank_get(crtc); > - if (ret) > - continue; > - > - exynos_drm_crtc_wait_pending_update(exynos_crtc); > - drm_crtc_vblank_put(crtc); > - } > -} > - > static void exynos_atomic_commit_complete(struct exynos_atomic_commit > *commit) > { > struct drm_device *dev = commit->dev; > struct exynos_drm_private *priv = dev->dev_private; > struct drm_atomic_state *state = commit->state; > - struct drm_plane *plane; > - struct drm_crtc *crtc; > - struct drm_plane_state *plane_state; > - struct drm_crtc_state *crtc_state; > - int i; > > drm_atomic_helper_commit_modeset_disables(dev, state); > > @@ -89,25 +63,9 @@ static void exynos_atomic_commit_complete(struct > exynos_atomic_commit *commit) >* have the relevant clocks enabled to pe
[RFC 0/2] drm/exynos: mixer: small optimisations
Hello, I had these two patches in my private tree for some time. Might as well ask if there is any interested in merging these. The first is just some unification on how booleans are used in the mixer code. The second one reduces register manipulation by moving stuff to the atomic flush call. I think one could even move more code there, like e.g. mixer_cfg_scan() and mixer_cfg_rgb_fmt(). Anyway, feedback is appreciated a lot! With best wishes, Tobias Tobias Jakobi (2): drm/exynos: mixer: convert booleans to flags in mixer context drm/exynos: mixer: configure layers once in mixer_atomic_flush() drivers/gpu/drm/exynos/exynos_mixer.c | 156 +- drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 97 insertions(+), 61 deletions(-) -- 2.7.3
[RFC 1/2] drm/exynos: mixer: convert booleans to flags in mixer context
The mixer context struct already has a 'flags' field, so we can use it to store the 'interlace', 'vp_enabled' and 'has_sclk' booleans. We use the non-atomic helper functions to access these bits. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 54 +++ 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 9a48aa1..1e78d57 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -73,6 +73,9 @@ enum mixer_version_id { enum mixer_flag_bits { MXR_BIT_POWERED, MXR_BIT_VSYNC, + MXR_BIT_INTERLACE, + MXR_BIT_VP_ENABLED, + MXR_BIT_HAS_SCLK, }; static const uint32_t mixer_formats[] = { @@ -98,9 +101,6 @@ struct mixer_context { struct exynos_drm_plane planes[MIXER_WIN_NR]; int pipe; unsigned long flags; - boolinterlace; - boolvp_enabled; - boolhas_sclk; struct mixer_resources mixer_res; enum mixer_version_id mxr_ver; @@ -346,7 +346,7 @@ static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) mixer_reg_writemask(res, MXR_STATUS, enable ? MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); - if (ctx->vp_enabled) + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) vp_reg_write(res, VP_SHADOW_UPDATE, enable ? VP_SHADOW_UPDATE_ENABLE : 0); } @@ -357,8 +357,8 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) u32 val; /* choosing between interlace and progressive mode */ - val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE : - MXR_CFG_SCAN_PROGRESSIVE); + val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? + MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE; if (ctx->mxr_ver != MXR_VER_128_0_0_184) { /* choosing between proper HD and SD mode */ @@ -436,9 +436,10 @@ static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, mixer_reg_writemask(res, MXR_LAYER_CFG, MXR_LAYER_CFG_GRP1_VAL(priority), MXR_LAYER_CFG_GRP1_MASK); + break; case VP_DEFAULT_WIN: - if (ctx->vp_enabled) { + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); @@ -501,7 +502,7 @@ static void vp_video_buffer(struct mixer_context *ctx, chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1); if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - ctx->interlace = true; + __set_bit(MXR_BIT_INTERLACE, &ctx->flags); if (tiled_mode) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; @@ -510,7 +511,7 @@ static void vp_video_buffer(struct mixer_context *ctx, chroma_addr[1] = chroma_addr[0] + fb->pitches[0]; } } else { - ctx->interlace = false; + __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); luma_addr[1] = 0; chroma_addr[1] = 0; } @@ -518,7 +519,7 @@ static void vp_video_buffer(struct mixer_context *ctx, spin_lock_irqsave(&res->reg_slock, flags); /* interlace or progressive scan mode */ - val = (ctx->interlace ? ~0 : 0); + val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); /* setup format */ @@ -541,7 +542,7 @@ static void vp_video_buffer(struct mixer_context *ctx, vp_reg_write(res, VP_DST_WIDTH, state->crtc.w); vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x); - if (ctx->interlace) { + if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2); vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2); } else { @@ -636,9 +637,9 @@ static void mixer_graph_buffer(struct mixer_context *ctx, src_y_offset = 0; if (mode->flags & DRM_MODE_FLAG_INTERLACE) - ctx->interlace = true; + __set_bit(MXR_BIT_INTERLACE, &ctx->flags); else - ctx->interlace = false; + __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); spin_lock_irqsave(&res->r
[RFC 2/2] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once in mixer_cfg_layer(). Trigger this via atomic flush. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 104 ++ drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 69 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1e78d57..d4efd9c 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -99,6 +99,7 @@ struct mixer_context { struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; + unsigned long state_cache; int pipe; unsigned long flags; @@ -418,37 +419,68 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); } -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, - unsigned int priority, bool enable) +static void mixer_cfg_layer(struct mixer_context *ctx) { struct mixer_resources *res = &ctx->mixer_res; - u32 val = enable ? ~0 : 0; - - switch (win) { - case 0: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP0_VAL(priority), - MXR_LAYER_CFG_GRP0_MASK); - break; - case 1: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP1_VAL(priority), - MXR_LAYER_CFG_GRP1_MASK); + unsigned int win; - break; - case VP_DEFAULT_WIN: - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, - MXR_CFG_VP_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_VP_VAL(priority), - MXR_LAYER_CFG_VP_MASK); + struct exynos_drm_plane_state *state; + struct drm_framebuffer *fb; + unsigned int priority; + u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; + bool enable; + + for (win = 0; win < MIXER_WIN_NR; ++win) { + state = to_exynos_plane_state(ctx->planes[win].base.state); + fb = state->fb; + + priority = state->base.normalized_zpos + 1; + enable = test_bit(win, &ctx->state_cache); + + if (!enable) + continue; + + switch (win) { + case 0: + mxr_cfg |= MXR_CFG_GRP0_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_GRP0_VAL(priority); + break; + + case 1: + mxr_cfg |= MXR_CFG_GRP1_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_GRP1_VAL(priority); + break; + + case VP_DEFAULT_WIN: + vp_enable = VP_ENABLE_ON; + mxr_cfg |= MXR_CFG_VP_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_VP_VAL(priority); + break; + } + + if (!fb) + continue; + + /* +* TODO: Don't enable alpha blending for the bottom window. +*/ + switch (win) { + case 0: + case 1: + mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format)); + break; + + case VP_DEFAULT_WIN: + mixer_cfg_vp_blend(ctx); + break; } - break; } + + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) + vp_reg_writemask(res, VP_ENABLE, vp_enable, VP_ENABLE_ON); + + mixer_reg_writemask(res, MXR_CFG, mxr_cfg, MXR_CFG_ENABLE_MASK); + mixer_reg_writemask(res, MXR_LAYER_CFG, mxr_layer_cfg, MXR_LAYER_CFG_MASK); } static void mixer_run(struct mixer_context *ctx) @@ -478,7 +510,6 @@ static void vp_video_buffer(struct mixer_context *ctx, struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->fb; - unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags;
[RFC 2/2] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello Andrzej, first of all, I've noticed an error myself. mixer_disable() calls mixer_disable_plane(), so it should also be modified. I'll send a v2 later. Now to your points... Andrzej Hajda wrote: > On 19.09.2016 16:16, Tobias Jakobi wrote: >> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >> in mixer_cfg_layer(). >> Trigger this via atomic flush. >> >> Signed-off-by: Tobias Jakobi >> --- >> drivers/gpu/drm/exynos/exynos_mixer.c | 104 >> ++ >> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >> 2 files changed, 69 insertions(+), 37 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >> b/drivers/gpu/drm/exynos/exynos_mixer.c >> index 1e78d57..d4efd9c 100644 >> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >> @@ -99,6 +99,7 @@ struct mixer_context { >> struct drm_device *drm_dev; >> struct exynos_drm_crtc *crtc; >> struct exynos_drm_plane planes[MIXER_WIN_NR]; >> +unsigned long state_cache; > > The name of the variable is cryptic. Yes, I'll try to come up with something better. It would probably be easier if struct mixer_context had a documentation for its fields. Anyway, any suggestions? > >> int pipe; >> unsigned long flags; >> >> @@ -418,37 +419,68 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >> *ctx, unsigned int height) >> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >> } >> >> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >> -unsigned int priority, bool enable) >> +static void mixer_cfg_layer(struct mixer_context *ctx) >> { >> struct mixer_resources *res = &ctx->mixer_res; >> -u32 val = enable ? ~0 : 0; >> - >> -switch (win) { >> -case 0: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP0_VAL(priority), >> -MXR_LAYER_CFG_GRP0_MASK); >> -break; >> -case 1: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP1_VAL(priority), >> -MXR_LAYER_CFG_GRP1_MASK); >> +unsigned int win; >> >> -break; >> -case VP_DEFAULT_WIN: >> -if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { >> -vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); >> -mixer_reg_writemask(res, MXR_CFG, val, >> -MXR_CFG_VP_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_VP_VAL(priority), >> -MXR_LAYER_CFG_VP_MASK); >> +struct exynos_drm_plane_state *state; >> +struct drm_framebuffer *fb; >> +unsigned int priority; >> +u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; >> +bool enable; >> + >> +for (win = 0; win < MIXER_WIN_NR; ++win) { >> +state = to_exynos_plane_state(ctx->planes[win].base.state); >> +fb = state->fb; >> + >> +priority = state->base.normalized_zpos + 1; >> +enable = test_bit(win, &ctx->state_cache); >> + >> +if (!enable) >> +continue; >> + >> +switch (win) { >> +case 0: >> +mxr_cfg |= MXR_CFG_GRP0_ENABLE; >> +mxr_layer_cfg |= MXR_LAYER_CFG_GRP0_VAL(priority); >> +break; >> + >> +case 1: >> +mxr_cfg |= MXR_CFG_GRP1_ENABLE; >> +mxr_layer_cfg |= MXR_LAYER_CFG_GRP1_VAL(priority); >> +break; >> + >> +case VP_DEFAULT_WIN: >> +vp_enable = VP_ENABLE_ON; >> +mxr_cfg |= MXR_CFG_VP_ENABLE; >> +mxr_layer_cfg |= MXR_LAYER_CFG_VP_VAL(priority); >> +break; >> +} >> + >> +if (!fb) >> +continue; >> + >> +/* >> +
drm/exynos: probe deferral for sub drivers
Hello, I'm currently facing the following problem. I want to use a devfreq device in one of the Exynos sub drivers, namely the G2D sub driver. My current approach is to use devfreq_get_devfreq_by_phandle() in g2d_probe(). But at the G2D probing time the devfreq subsystem isn't initialized yet, and I get EPROBE_DEFER back. Now I simply let g2d_probe() fail with EPROBE_DEFER in that case. Eventually devfreq is online and g2d_probe() runs successfully. So far, so good. However some debugging shows that g2d_subdrv_probe(), which does IOMMU setup and allocates the cmdlist, never happens in that case. I've looked at exynos_drm_load() which issues exynos_drm_device_subdrv_probe() at some point, which apparantly only probes those devices which are registered at that time. Hence, if the G2D probe hasn't happened until then, the Exynos DRM won't ever see it. That made me wonder how the driver makes sure that the sub drivers are all readily probed in that situation. I see that a component_bind_all() is issued prior to subdrv probing, but both the G2D and the IPP subdrv don't have bind/unbind calls. I guess subdrv != subdrv, eh? At present it appears that it's merely luck that the G2D is probed when sub drivers are probed? Anyway, probe deferral seems to work correctly with Exynos HDMI, so I was wondering if there is some way to also make it work with the G2D? Thanks in advance! With best wishes, Tobias
[RFC 2/2] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hi Andrzej, Andrzej Hajda wrote: > On 20.09.2016 14:34, Andrzej Hajda wrote: >> On 20.09.2016 13:23, Tobias Jakobi wrote: >>> Hello Andrzej, >>> >>> first of all, I've noticed an error myself. mixer_disable() calls >>> mixer_disable_plane(), so it should also be modified. I'll send a v2 later. >>> >>> Now to your points... >>> >>> >>> Andrzej Hajda wrote: >>>> On 19.09.2016 16:16, Tobias Jakobi wrote: >>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>> in mixer_cfg_layer(). >>>>> Trigger this via atomic flush. >>>>> >>>>> Signed-off-by: Tobias Jakobi >>>>> --- >>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 104 >>>>> ++ >>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>> 2 files changed, 69 insertions(+), 37 deletions(-) >>>>> >>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> index 1e78d57..d4efd9c 100644 >>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>> @@ -99,6 +99,7 @@ struct mixer_context { >>>>> struct drm_device *drm_dev; >>>>> struct exynos_drm_crtc *crtc; >>>>> struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>> + unsigned long state_cache; >>>> The name of the variable is cryptic. >>> Yes, I'll try to come up with something better. It would probably be >>> easier if struct mixer_context had a documentation for its fields. >>> >>> Anyway, any suggestions? >> (active|enabled)_(planes|windows), or sth similar? Thanks, I think I'll go with the 'window' terminology then. >>>>> int pipe; >>>>> unsigned long flags; >>>>> >>>>> @@ -418,37 +419,68 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >>>>> *ctx, unsigned int height) >>>>> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>>> } >>>>> >>>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >>>>> - unsigned int priority, bool enable) >>>>> +static void mixer_cfg_layer(struct mixer_context *ctx) >>>>> { >>>>> struct mixer_resources *res = &ctx->mixer_res; >>>>> - u32 val = enable ? ~0 : 0; >>>>> - >>>>> - switch (win) { >>>>> - case 0: >>>>> - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >>>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>>> - MXR_LAYER_CFG_GRP0_VAL(priority), >>>>> - MXR_LAYER_CFG_GRP0_MASK); >>>>> - break; >>>>> - case 1: >>>>> - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >>>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>>> - MXR_LAYER_CFG_GRP1_VAL(priority), >>>>> - MXR_LAYER_CFG_GRP1_MASK); >>>>> + unsigned int win; >>>>> >>>>> - break; >>>>> - case VP_DEFAULT_WIN: >>>>> - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { >>>>> - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); >>>>> - mixer_reg_writemask(res, MXR_CFG, val, >>>>> - MXR_CFG_VP_ENABLE); >>>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>>> - MXR_LAYER_CFG_VP_VAL(priority), >>>>> - MXR_LAYER_CFG_VP_MASK); >>>>> + struct exynos_drm_plane_state *state; >>>>> + struct drm_framebuffer *fb; >>>>> + unsigned int priority; >>>>> + u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; >>>>> + bool enable; >>>>> + >>>>> + for (win = 0; win < MIXER_WIN_NR; ++win) { >>>>> + state = to_exynos_plane_state(ctx->planes[win].base.state); >>>>> + fb = state->fb; >>>>> + &
drm/exynos: probe deferral for sub drivers
Hey Andrzej, Andrzej Hajda wrote: > On 21.09.2016 00:07, Tobias Jakobi wrote: >> Hello, >> >> I'm currently facing the following problem. >> >> I want to use a devfreq device in one of the Exynos sub drivers, namely >> the G2D sub driver. My current approach is to use >> devfreq_get_devfreq_by_phandle() in g2d_probe(). But at the G2D probing >> time the devfreq subsystem isn't initialized yet, and I get EPROBE_DEFER >> back. >> >> Now I simply let g2d_probe() fail with EPROBE_DEFER in that case. >> Eventually devfreq is online and g2d_probe() runs successfully. >> >> So far, so good. However some debugging shows that g2d_subdrv_probe(), >> which does IOMMU setup and allocates the cmdlist, never happens in that >> case. >> >> I've looked at exynos_drm_load() which issues >> exynos_drm_device_subdrv_probe() at some point, which apparantly only >> probes those devices which are registered at that time. Hence, if the >> G2D probe hasn't happened until then, the Exynos DRM won't ever see it. >> >> That made me wonder how the driver makes sure that the sub drivers are >> all readily probed in that situation. I see that a component_bind_all() >> is issued prior to subdrv probing, but both the G2D and the IPP subdrv >> don't have bind/unbind calls. I guess subdrv != subdrv, eh? >> >> At present it appears that it's merely luck that the G2D is probed when >> sub drivers are probed? >> >> Anyway, probe deferral seems to work correctly with Exynos HDMI, so I >> was wondering if there is some way to also make it work with the G2D? > > HDMI is componentized, G2D no, so it does not work with deferred probe. > The best solution at the moment is to componentize G2D, it should > not be difficult. I see! I try to look into this, but probably I'm going to ask for help again. If that's OK with you? ;-) With best wishes, Tobias > > Regards > Andrzej > >> >> Thanks in advance! >> >> With best wishes, >> Tobias >> ___ >> dri-devel mailing list >> dri-devel at lists.freedesktop.org >> https://lists.freedesktop.org/mailman/listinfo/dri-devel > >
[PATCH v2 0/4] drm/exynos: mixer: small optimisations
Hello, here's v2 of this patchset. I've added two other 'cosmetic' patches as well. Anyway, I have fixed up the second patch and integrated Andrzej's suggestions. First patch is unmodified except for the Reviewed-By tag. With best wishes, Tobias Tobias Jakobi (4): drm/exynos: mixer: convert booleans to flags in mixer context drm/exynos: mixer: configure layers once in mixer_atomic_flush() drm/exynos: mixer: simplify loop in vp_win_reset() drm/exynos: g2d: beautify probing message drivers/gpu/drm/exynos/exynos_drm_g2d.c | 2 +- drivers/gpu/drm/exynos/exynos_mixer.c | 187 drivers/gpu/drm/exynos/regs-mixer.h | 2 + 3 files changed, 120 insertions(+), 71 deletions(-) -- 2.7.3
[PATCH v2 1/4] drm/exynos: mixer: convert booleans to flags in mixer context
The mixer context struct already has a 'flags' field, so we can use it to store the 'interlace', 'vp_enabled' and 'has_sclk' booleans. We use the non-atomic helper functions to access these bits. Reviewed-by: Andrzej Hajda Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 54 +++ 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 9a48aa1..1e78d57 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -73,6 +73,9 @@ enum mixer_version_id { enum mixer_flag_bits { MXR_BIT_POWERED, MXR_BIT_VSYNC, + MXR_BIT_INTERLACE, + MXR_BIT_VP_ENABLED, + MXR_BIT_HAS_SCLK, }; static const uint32_t mixer_formats[] = { @@ -98,9 +101,6 @@ struct mixer_context { struct exynos_drm_plane planes[MIXER_WIN_NR]; int pipe; unsigned long flags; - boolinterlace; - boolvp_enabled; - boolhas_sclk; struct mixer_resources mixer_res; enum mixer_version_id mxr_ver; @@ -346,7 +346,7 @@ static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) mixer_reg_writemask(res, MXR_STATUS, enable ? MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); - if (ctx->vp_enabled) + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) vp_reg_write(res, VP_SHADOW_UPDATE, enable ? VP_SHADOW_UPDATE_ENABLE : 0); } @@ -357,8 +357,8 @@ static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) u32 val; /* choosing between interlace and progressive mode */ - val = (ctx->interlace ? MXR_CFG_SCAN_INTERLACE : - MXR_CFG_SCAN_PROGRESSIVE); + val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? + MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE; if (ctx->mxr_ver != MXR_VER_128_0_0_184) { /* choosing between proper HD and SD mode */ @@ -436,9 +436,10 @@ static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, mixer_reg_writemask(res, MXR_LAYER_CFG, MXR_LAYER_CFG_GRP1_VAL(priority), MXR_LAYER_CFG_GRP1_MASK); + break; case VP_DEFAULT_WIN: - if (ctx->vp_enabled) { + if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_VP_ENABLE); @@ -501,7 +502,7 @@ static void vp_video_buffer(struct mixer_context *ctx, chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1); if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - ctx->interlace = true; + __set_bit(MXR_BIT_INTERLACE, &ctx->flags); if (tiled_mode) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; @@ -510,7 +511,7 @@ static void vp_video_buffer(struct mixer_context *ctx, chroma_addr[1] = chroma_addr[0] + fb->pitches[0]; } } else { - ctx->interlace = false; + __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); luma_addr[1] = 0; chroma_addr[1] = 0; } @@ -518,7 +519,7 @@ static void vp_video_buffer(struct mixer_context *ctx, spin_lock_irqsave(&res->reg_slock, flags); /* interlace or progressive scan mode */ - val = (ctx->interlace ? ~0 : 0); + val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); /* setup format */ @@ -541,7 +542,7 @@ static void vp_video_buffer(struct mixer_context *ctx, vp_reg_write(res, VP_DST_WIDTH, state->crtc.w); vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x); - if (ctx->interlace) { + if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2); vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2); } else { @@ -636,9 +637,9 @@ static void mixer_graph_buffer(struct mixer_context *ctx, src_y_offset = 0; if (mode->flags & DRM_MODE_FLAG_INTERLACE) - ctx->interlace = true; + __set_bit(MXR_BIT_INTERLACE, &ctx->flags); else - ctx->interlace = false; + __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); sp
[PATCH v2 2/4] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once in mixer_cfg_layer(). Trigger this via atomic flush. Changes in v2: - issue mixer_cfg_layer() in mixer_disable() - rename fields as suggested by Andrzej - added docu to mixer context struct - simplify mixer_win_reset() as well Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 133 ++ drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 90 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1e78d57..c3dad66 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { DRM_FORMAT_NV21, }; +/* + * Mixer context structure. + * + * @crtc: The HDMI CRTC attached to the mixer. + * @planes: Array of plane objects for each of the mixer windows. + * @active_windows: Cache of the mixer's hardware state. + * Tracks which mixer windows are active/inactive. + * @pipe: The CRTC index. + * @flags: Bitfield build from the mixer_flag_bits enumerator. + * @mixer_resources: A struct containing registers, clocks, etc. + * @mxr_ver: The hardware revision/version of the mixer. + */ struct mixer_context { struct platform_device *pdev; struct device *dev; struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; + unsigned long active_windows; int pipe; unsigned long flags; @@ -418,37 +431,68 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); } -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, - unsigned int priority, bool enable) +static void mixer_cfg_layer(struct mixer_context *ctx) { struct mixer_resources *res = &ctx->mixer_res; - u32 val = enable ? ~0 : 0; - - switch (win) { - case 0: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP0_VAL(priority), - MXR_LAYER_CFG_GRP0_MASK); - break; - case 1: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP1_VAL(priority), - MXR_LAYER_CFG_GRP1_MASK); + unsigned int win; - break; - case VP_DEFAULT_WIN: - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, - MXR_CFG_VP_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_VP_VAL(priority), - MXR_LAYER_CFG_VP_MASK); + struct exynos_drm_plane_state *state; + struct drm_framebuffer *fb; + unsigned int priority; + u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; + bool enable; + + for (win = 0; win < MIXER_WIN_NR; ++win) { + state = to_exynos_plane_state(ctx->planes[win].base.state); + fb = state->fb; + + priority = state->base.normalized_zpos + 1; + enable = test_bit(win, &ctx->active_windows); + + if (!enable) + continue; + + switch (win) { + case 0: + mxr_cfg |= MXR_CFG_GRP0_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_GRP0_VAL(priority); + break; + + case 1: + mxr_cfg |= MXR_CFG_GRP1_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_GRP1_VAL(priority); + break; + + case VP_DEFAULT_WIN: + vp_enable = VP_ENABLE_ON; + mxr_cfg |= MXR_CFG_VP_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_VP_VAL(priority); + break; + } + + if (!fb) + continue; + + /* +* TODO: Don't enable alpha blending for the bottom window. +*/ + switch (win) { + case 0: + case 1: + mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format)); + break; + + case VP_DEFAULT_WIN: + mixer_cf
[PATCH v2 3/4] drm/exynos: mixer: simplify loop in vp_win_reset()
A simple while loop should do the same here. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index c3dad66..4f39d6b 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -736,10 +736,10 @@ static void mixer_graph_buffer(struct mixer_context *ctx, static void vp_win_reset(struct mixer_context *ctx) { struct mixer_resources *res = &ctx->mixer_res; - int tries = 100; + unsigned int tries = 100; vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING); - for (tries = 100; tries; --tries) { + while (tries--) { /* waiting until VP_SRESET_PROCESSING is 0 */ if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) break; -- 2.7.3
[PATCH v2 4/4] drm/exynos: g2d: beautify probing message
Apply some 'make-up' in g2d_probe(). Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 73cd83f..410d170 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -2423,7 +2423,7 @@ static int g2d_probe(struct platform_device *pdev) goto err_put_clk; } - dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n", + dev_info(dev, "The Exynos G2D (ver %d.%d) successfully probed.\n", G2D_HW_MAJOR_VER, G2D_HW_MINOR_VER); return 0; -- 2.7.3
[RFC] drm/exynos: g2d: runpm fixing attempt
Hello, I have already talked to Marek in private about this. The latest runpm patch (b05984e21a7e000bf5074ace00d7a574944b2c16) cripples G2D operation. I have tried to come up with a way to fix this and also to improve runpm behaviour while at it. Marek pointed out that the current issue, i.e. the reason for the aforementioned patch, is that sleep ops (suspend/resume) are now called during runpm suspend time. I think that my approach should handle this situation. In any case, feedback is much appreciated. With best wishes, Tobias Tobias Jakobi (1): drm/exynos: g2d: fix runtime PM drivers/gpu/drm/exynos/exynos_drm_g2d.c | 235 +--- 1 file changed, 186 insertions(+), 49 deletions(-) -- 2.7.3
[RFC] drm/exynos: g2d: fix runtime PM
The commit b05984e21a7e000bf5074ace00d7a574944b2c16 broke operation of the G2D. After this commit the following happens. - exynos_g2d_exec_ioctl() prepares a runqueue node and calls g2d_exec_runqueue() - g2d_exec_runqueue() calls g2d_dma_start() which gets runtime PM sync - runtime PM calls g2d_runtime_resume() - g2d_runtime_resume() calls g2d_exec_runqueue() Luckily for us this doesn't really loop, but creates a mutex lockup, which the kernel even predicts. Anyway, we fix this by reintroducing dedicated sleep operations again, and only letting runtime PM control the gate clock. This is not enough to fix the issue though. - We switch runtime PM to autosuspend. Currently clocks get disabled, and then re-enabled again in the runqueue worker when a node is completed and the next is started. With the upcoming introduction of IOMMU runtime PM this situations gets worse, since now also the IOMMU goes through a disable/enable cycle before the next node is started. - We consolidate all runtime PM management to the runqueue worker. - We introduce g2d_wait_finish() which waits until the currently processed runqueue node is finished. If this takes too long, the engine is forcibly reset. This is necessary to properly close the driver in case the engine should hang with read/write access to some area of memory. In this situation we can't properly unmap GEM/userptr objects, since this might create a pagefault. - Sleep suspend issues a suspend of the runqueue and then calls g2d_wait_finished(), which returns the engine in the idle state. The current runqueue node gets completed, all other queued nodes stay in the queue. There is no hardware state that needs to be retained. - Sleep resume just pokes the runqueue worker, which, should something be in queue, continues its work, or just exits. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 235 +--- 1 file changed, 186 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 6eca8bb..c4f7026 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -138,6 +138,18 @@ enum g2d_reg_type { MAX_REG_TYPE_NR }; +enum g2d_flag_bits { + /* +* If set, suspends the runqueue worker after the currently +* processed node is finished. +*/ + G2D_BIT_SUSPEND_RUNQUEUE, + /* +* If set, indicates that the engine is currently busy. +*/ + G2D_BIT_ENGINE_BUSY, +}; + /* cmdlist data structure */ struct g2d_cmdlist { u32 head; @@ -226,7 +238,7 @@ struct g2d_data { struct workqueue_struct *g2d_workq; struct work_struct runqueue_work; struct exynos_drm_subdrvsubdrv; - boolsuspended; + unsigned long flags; /* cmdlist */ struct g2d_cmdlist_node *cmdlist_node; @@ -246,6 +258,12 @@ struct g2d_data { unsigned long max_pool; }; +static inline void g2d_hw_reset(struct g2d_data *g2d) +{ + writel(G2D_R | G2D_SFRCLEAR, g2d->regs + G2D_SOFT_RESET); + clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); +} + static int g2d_init_cmdlist(struct g2d_data *g2d) { struct device *dev = g2d->dev; @@ -803,12 +821,8 @@ static void g2d_dma_start(struct g2d_data *g2d, struct g2d_cmdlist_node *node = list_first_entry(&runqueue_node->run_cmdlist, struct g2d_cmdlist_node, list); - int ret; - - ret = pm_runtime_get_sync(g2d->dev); - if (ret < 0) - return; + set_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); } @@ -831,9 +845,6 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, { struct g2d_cmdlist_node *node; - if (!runqueue_node) - return; - mutex_lock(&g2d->cmdlist_mutex); /* * commands in run_cmdlist have been completed so unmap all gem @@ -847,29 +858,63 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, kmem_cache_free(g2d->runqueue_slab, runqueue_node); } -static void g2d_exec_runqueue(struct g2d_data *g2d) +/** + * g2d_remove_runqueue_nodes - remove items from the list of runqueue nodes + * @g2d: G2D state object + * @file: if not zero, only remove items with this DRM file + * + * Has to be called under runqueue lock. + */ +static void g2d_remove_runqueue_nodes(struct g2d_data *g2d, struct drm_file* file) { - g2d->runqueue_node = g2d_get_runqueue_node(g2d); - if (g2d->runqueue_node) - g2d_dma_start(
[RFC] drm/exynos: g2d: fix runtime PM
Tobias Jakobi wrote: > The commit b05984e21a7e000bf5074ace00d7a574944b2c16 broke > operation of the G2D. After this commit the following > happens. > - exynos_g2d_exec_ioctl() prepares a runqueue node and > calls g2d_exec_runqueue() > - g2d_exec_runqueue() calls g2d_dma_start() which gets > runtime PM sync > - runtime PM calls g2d_runtime_resume() > - g2d_runtime_resume() calls g2d_exec_runqueue() > > Luckily for us this doesn't really loop, but creates a > mutex lockup, which the kernel even predicts. > > Anyway, we fix this by reintroducing dedicated sleep > operations again, and only letting runtime PM control > the gate clock. > > This is not enough to fix the issue though. > - We switch runtime PM to autosuspend. Currently clocks get > disabled, and then re-enabled again in the runqueue worker > when a node is completed and the next is started. > With the upcoming introduction of IOMMU runtime PM this > situations gets worse, since now also the IOMMU goes > through a disable/enable cycle before the next node is > started. > - We consolidate all runtime PM management to the runqueue > worker. > - We introduce g2d_wait_finish() which waits until the currently > processed runqueue node is finished. > If this takes too long, the engine is forcibly reset. This > is necessary to properly close the driver in case the engine > should hang with read/write access to some area of memory. > In this situation we can't properly unmap GEM/userptr > objects, since this might create a pagefault. > - Sleep suspend issues a suspend of the runqueue and then calls > g2d_wait_finished(), which returns the engine in the idle state. This should read 'g2d_wait_finish()'. > The current runqueue node gets completed, all other queued > nodes stay in the queue. There is no hardware state that > needs to be retained. > - Sleep resume just pokes the runqueue worker, which, should > something be in queue, continues its work, or just exits. > > Signed-off-by: Tobias Jakobi
[RFC v2] drm/exynos: g2d: fix runtime PM
The commit b05984e21a7e000bf5074ace00d7a574944b2c16 broke operation of the G2D. After this commit the following happens. - exynos_g2d_exec_ioctl() prepares a runqueue node and calls g2d_exec_runqueue() - g2d_exec_runqueue() calls g2d_dma_start() which gets runtime PM sync - runtime PM calls g2d_runtime_resume() - g2d_runtime_resume() calls g2d_exec_runqueue() Luckily for us this doesn't really loop, but creates a mutex lockup, which the kernel even predicts. Anyway, we fix this by reintroducing dedicated sleep operations again, and only letting runtime PM control the gate clock. This is not enough to fix the issue though. - We switch runtime PM to autosuspend. Currently clocks get disabled, and then re-enabled again in the runqueue worker when a node is completed and the next is started. With the upcoming introduction of IOMMU runtime PM this situations gets worse, since now also the IOMMU goes through a disable/enable cycle before the next node is started. - We consolidate all runtime PM management to the runqueue worker. - We introduce g2d_wait_finish() which waits until the currently processed runqueue node is finished. If this takes too long, the engine is forcibly reset. This is necessary to properly close the driver in case the engine should hang with read/write access to some area of memory. In this situation we can't properly unmap GEM/userptr objects, since this might create a pagefault. - Sleep suspend issues a suspend of the runqueue and then calls g2d_wait_finish(), which returns the engine in the idle state. The current runqueue node gets completed, all other queued nodes stay in the queue. There is no hardware state that needs to be retained. - Sleep resume just pokes the runqueue worker, which, should something be in queue, continues its work, or just exits. Changes in v2: - disable autosuspend mode again in g2d_remove() - only get sync in g2d_runqueue_worker() if there is node in the queue left Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 237 +--- 1 file changed, 188 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 6eca8bb..c3f839c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -138,6 +138,18 @@ enum g2d_reg_type { MAX_REG_TYPE_NR }; +enum g2d_flag_bits { + /* +* If set, suspends the runqueue worker after the currently +* processed node is finished. +*/ + G2D_BIT_SUSPEND_RUNQUEUE, + /* +* If set, indicates that the engine is currently busy. +*/ + G2D_BIT_ENGINE_BUSY, +}; + /* cmdlist data structure */ struct g2d_cmdlist { u32 head; @@ -226,7 +238,7 @@ struct g2d_data { struct workqueue_struct *g2d_workq; struct work_struct runqueue_work; struct exynos_drm_subdrvsubdrv; - boolsuspended; + unsigned long flags; /* cmdlist */ struct g2d_cmdlist_node *cmdlist_node; @@ -246,6 +258,12 @@ struct g2d_data { unsigned long max_pool; }; +static inline void g2d_hw_reset(struct g2d_data *g2d) +{ + writel(G2D_R | G2D_SFRCLEAR, g2d->regs + G2D_SOFT_RESET); + clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); +} + static int g2d_init_cmdlist(struct g2d_data *g2d) { struct device *dev = g2d->dev; @@ -803,12 +821,8 @@ static void g2d_dma_start(struct g2d_data *g2d, struct g2d_cmdlist_node *node = list_first_entry(&runqueue_node->run_cmdlist, struct g2d_cmdlist_node, list); - int ret; - - ret = pm_runtime_get_sync(g2d->dev); - if (ret < 0) - return; + set_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); } @@ -831,9 +845,6 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, { struct g2d_cmdlist_node *node; - if (!runqueue_node) - return; - mutex_lock(&g2d->cmdlist_mutex); /* * commands in run_cmdlist have been completed so unmap all gem @@ -847,29 +858,64 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, kmem_cache_free(g2d->runqueue_slab, runqueue_node); } -static void g2d_exec_runqueue(struct g2d_data *g2d) +/** + * g2d_remove_runqueue_nodes - remove items from the list of runqueue nodes + * @g2d: G2D state object + * @file: if not zero, only remove items with this DRM file + * + * Has to be called under runqueue lock. + */ +static void g2d_remove_runqueue_nodes(struct g2d_da
[RFC v3] drm/exynos: g2d: fix runtime PM
The commit b05984e21a7e000bf5074ace00d7a574944b2c16 broke operation of the G2D. After this commit the following happens. - exynos_g2d_exec_ioctl() prepares a runqueue node and calls g2d_exec_runqueue() - g2d_exec_runqueue() calls g2d_dma_start() which gets runtime PM sync - runtime PM calls g2d_runtime_resume() - g2d_runtime_resume() calls g2d_exec_runqueue() Luckily for us this doesn't really loop, but creates a mutex lockup, which the kernel even predicts. Anyway, we fix this by reintroducing dedicated sleep operations again, and only letting runtime PM control the gate clock. This is not enough to fix the issue though. - We switch runtime PM to autosuspend. Currently clocks get disabled, and then re-enabled again in the runqueue worker when a node is completed and the next is started. With the upcoming introduction of IOMMU runtime PM this situations gets worse, since now also the IOMMU goes through a disable/enable cycle before the next node is started. - We consolidate all runtime PM management to the runqueue worker. - We introduce g2d_wait_finish() which waits until the currently processed runqueue node is finished. If this takes too long, the engine is forcibly reset. This is necessary to properly close the driver in case the engine should hang with read/write access to some area of memory. In this situation we can't properly unmap GEM/userptr objects, since this might create a pagefault. - Sleep suspend issues a suspend of the runqueue and then calls g2d_wait_finish(), which returns the engine in the idle state. The current runqueue node gets completed, all other queued nodes stay in the queue. There is no hardware state that needs to be retained. - Sleep resume just pokes the runqueue worker, which, should something be in queue, continues its work, or just exits. Changes in v2: - disable autosuspend mode again in g2d_remove() - only get sync in g2d_runqueue_worker() if there is node in the queue left Changes in v3: - actually delete node in g2d_remove_runqueue_nodes() Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 238 +--- 1 file changed, 189 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 6eca8bb..ef546ec 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -138,6 +138,18 @@ enum g2d_reg_type { MAX_REG_TYPE_NR }; +enum g2d_flag_bits { + /* +* If set, suspends the runqueue worker after the currently +* processed node is finished. +*/ + G2D_BIT_SUSPEND_RUNQUEUE, + /* +* If set, indicates that the engine is currently busy. +*/ + G2D_BIT_ENGINE_BUSY, +}; + /* cmdlist data structure */ struct g2d_cmdlist { u32 head; @@ -226,7 +238,7 @@ struct g2d_data { struct workqueue_struct *g2d_workq; struct work_struct runqueue_work; struct exynos_drm_subdrvsubdrv; - boolsuspended; + unsigned long flags; /* cmdlist */ struct g2d_cmdlist_node *cmdlist_node; @@ -246,6 +258,12 @@ struct g2d_data { unsigned long max_pool; }; +static inline void g2d_hw_reset(struct g2d_data *g2d) +{ + writel(G2D_R | G2D_SFRCLEAR, g2d->regs + G2D_SOFT_RESET); + clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); +} + static int g2d_init_cmdlist(struct g2d_data *g2d) { struct device *dev = g2d->dev; @@ -803,12 +821,8 @@ static void g2d_dma_start(struct g2d_data *g2d, struct g2d_cmdlist_node *node = list_first_entry(&runqueue_node->run_cmdlist, struct g2d_cmdlist_node, list); - int ret; - - ret = pm_runtime_get_sync(g2d->dev); - if (ret < 0) - return; + set_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); } @@ -831,9 +845,6 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, { struct g2d_cmdlist_node *node; - if (!runqueue_node) - return; - mutex_lock(&g2d->cmdlist_mutex); /* * commands in run_cmdlist have been completed so unmap all gem @@ -847,29 +858,65 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, kmem_cache_free(g2d->runqueue_slab, runqueue_node); } -static void g2d_exec_runqueue(struct g2d_data *g2d) +/** + * g2d_remove_runqueue_nodes - remove items from the list of runqueue nodes + * @g2d: G2D state object + * @file: if not zero, only remove items with this DRM file + * + * Has to be called under runqueue lock. +
[PATCH v2 2/4] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Dear Inki, Inki Dae wrote: > > > 2016ë 09ì 22ì¼ 23:57ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >> in mixer_cfg_layer(). >> Trigger this via atomic flush. >> >> Changes in v2: >> - issue mixer_cfg_layer() in mixer_disable() >> - rename fields as suggested by Andrzej >> - added docu to mixer context struct >> - simplify mixer_win_reset() as well >> >> Signed-off-by: Tobias Jakobi >> --- >> drivers/gpu/drm/exynos/exynos_mixer.c | 133 >> ++ >> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >> 2 files changed, 90 insertions(+), 45 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >> b/drivers/gpu/drm/exynos/exynos_mixer.c >> index 1e78d57..c3dad66 100644 >> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >> DRM_FORMAT_NV21, >> }; >> >> +/* >> + * Mixer context structure. >> + * >> + * @crtc: The HDMI CRTC attached to the mixer. >> + * @planes: Array of plane objects for each of the mixer windows. >> + * @active_windows: Cache of the mixer's hardware state. >> + * Tracks which mixer windows are active/inactive. >> + * @pipe: The CRTC index. >> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >> + * @mixer_resources: A struct containing registers, clocks, etc. >> + * @mxr_ver: The hardware revision/version of the mixer. >> + */ > > Above changes are not related to this patch but trivial thing so no problem. The struct documentation was added after the discussion with Andrzej, which made me realise that we might at least need a few words to describe what 'active_windows' is used for. Eventually I decided to document all fields, except for the usual ones. I didn't seem reasonable to me to add this in a follow-up patch. >> struct mixer_context { >> struct platform_device *pdev; >> struct device *dev; >> struct drm_device *drm_dev; >> struct exynos_drm_crtc *crtc; >> struct exynos_drm_plane planes[MIXER_WIN_NR]; >> +unsigned long active_windows; >> int pipe; >> unsigned long flags; >> >> @@ -418,37 +431,68 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >> *ctx, unsigned int height) >> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >> } >> >> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >> -unsigned int priority, bool enable) >> +static void mixer_cfg_layer(struct mixer_context *ctx) >> { >> struct mixer_resources *res = &ctx->mixer_res; >> -u32 val = enable ? ~0 : 0; >> - >> -switch (win) { >> -case 0: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP0_VAL(priority), >> -MXR_LAYER_CFG_GRP0_MASK); >> -break; >> -case 1: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP1_VAL(priority), >> -MXR_LAYER_CFG_GRP1_MASK); >> +unsigned int win; >> >> -break; >> -case VP_DEFAULT_WIN: >> -if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { >> -vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); >> -mixer_reg_writemask(res, MXR_CFG, val, >> -MXR_CFG_VP_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_VP_VAL(priority), >> -MXR_LAYER_CFG_VP_MASK); >> +struct exynos_drm_plane_state *state; >> +struct drm_framebuffer *fb; >> +unsigned int priority; >> +u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; >> +bool enable; >> + >> +for (win = 0; win < MIXER_WIN_NR; ++win) { >> +state = to_exynos_plane_state(ctx->planes[win].base.state); >> +fb = state->fb; >> + >> +priority = state->base.normalized_zpos + 1; >> +
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once in mixer_cfg_layer(). Trigger this via atomic flush. Changes in v2: - issue mixer_cfg_layer() in mixer_disable() - rename fields as suggested by Andrzej - added docu to mixer context struct - simplify mixer_win_reset() as well Changes in v3: - simplify some conditions as suggested by Inki - add docu to mixer_cfg_layer() - fold switch statements into a single one Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 135 ++ drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1e78d57..4f06f4d 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { DRM_FORMAT_NV21, }; +/* + * Mixer context structure. + * + * @crtc: The HDMI CRTC attached to the mixer. + * @planes: Array of plane objects for each of the mixer windows. + * @active_windows: Cache of the mixer's hardware state. + * Tracks which mixer windows are active/inactive. + * @pipe: The CRTC index. + * @flags: Bitfield build from the mixer_flag_bits enumerator. + * @mixer_resources: A struct containing registers, clocks, etc. + * @mxr_ver: The hardware revision/version of the mixer. + */ struct mixer_context { struct platform_device *pdev; struct device *dev; struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; + unsigned long active_windows; int pipe; unsigned long flags; @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); } -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, - unsigned int priority, bool enable) +/** + * mixer_cfg_layer - apply layer configuration to hardware + * @ctx: mixer context + * + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers + * using the 'active_windows' field of the the mixer content, and + * the pixel format of the framebuffers associated with the enabled + * windows. + * + * Has to be called under mixer lock. + */ +static void mixer_cfg_layer(struct mixer_context *ctx) { struct mixer_resources *res = &ctx->mixer_res; - u32 val = enable ? ~0 : 0; - - switch (win) { - case 0: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP0_VAL(priority), - MXR_LAYER_CFG_GRP0_MASK); - break; - case 1: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP1_VAL(priority), - MXR_LAYER_CFG_GRP1_MASK); + unsigned int win; - break; - case VP_DEFAULT_WIN: - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, - MXR_CFG_VP_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_VP_VAL(priority), - MXR_LAYER_CFG_VP_MASK); + struct exynos_drm_plane_state *state; + struct drm_framebuffer *fb; + unsigned int priority; + u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; + bool enable; + + for (win = 0; win < MIXER_WIN_NR; ++win) { + state = to_exynos_plane_state(ctx->planes[win].base.state); + fb = state->fb; + + priority = state->base.normalized_zpos + 1; + enable = test_bit(win, &ctx->active_windows); + + if (!enable) + continue; + + BUG_ON(!fb); + + /* +* TODO: Don't enable alpha blending for the bottom window. +*/ + switch (win) { + case 0: + mxr_cfg |= MXR_CFG_GRP0_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_GRP0_VAL(priority); + mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->pixel_format)); + break; + + case 1: + mxr_cfg |= MXR_CFG_GRP1_ENABLE; + mxr_layer_cfg |= MXR_LAYER_CFG_GRP1_VAL(priority); +
[RFC v3] drm/exynos: g2d: fix runtime PM
Hello Marek, Marek Szyprowski wrote: > Dear Tobias, > > On 2016-09-24 20:58, Tobias Jakobi wrote: >> The commit b05984e21a7e000bf5074ace00d7a574944b2c16 broke >> operation of the G2D. After this commit the following >> happens. >> - exynos_g2d_exec_ioctl() prepares a runqueue node and >>calls g2d_exec_runqueue() >> - g2d_exec_runqueue() calls g2d_dma_start() which gets >>runtime PM sync >> - runtime PM calls g2d_runtime_resume() >> - g2d_runtime_resume() calls g2d_exec_runqueue() >> >> Luckily for us this doesn't really loop, but creates a >> mutex lockup, which the kernel even predicts. >> >> Anyway, we fix this by reintroducing dedicated sleep >> operations again, and only letting runtime PM control >> the gate clock. >> >> This is not enough to fix the issue though. >> - We switch runtime PM to autosuspend. Currently clocks get >>disabled, and then re-enabled again in the runqueue worker >>when a node is completed and the next is started. >>With the upcoming introduction of IOMMU runtime PM this >>situations gets worse, since now also the IOMMU goes >>through a disable/enable cycle before the next node is >>started. >> - We consolidate all runtime PM management to the runqueue >>worker. >> - We introduce g2d_wait_finish() which waits until the currently >>processed runqueue node is finished. >>If this takes too long, the engine is forcibly reset. This >>is necessary to properly close the driver in case the engine >>should hang with read/write access to some area of memory. >>In this situation we can't properly unmap GEM/userptr >>objects, since this might create a pagefault. >> - Sleep suspend issues a suspend of the runqueue and then calls >>g2d_wait_finish(), which returns the engine in the idle state. >>The current runqueue node gets completed, all other queued >>nodes stay in the queue. There is no hardware state that >>needs to be retained. >> - Sleep resume just pokes the runqueue worker, which, should >>something be in queue, continues its work, or just exits. > > IMHO there is too much done in one patch. It would be much easier to > understand it if the changes are split into 2 parts: restoring dedicated > speep callbacks and their integration with runqueue worker and addition > of autosuspend-based runtime pm. so you mean first revert your patch, and then put more changes on top of it in a separate patch? I'm not sure into which 'functional units' I should break this one down. I can of course create a separate patch for autosuspend, that that would only replace a put_sync() with mark_last_busy() + put_autosuspend(), wouldn't it? My current idea of functional units: 1) revert Marek's patch 2) move runpm management to g2d_runqueue_worker() 3) introduce g2d_wait_finish() and use it sleep call 4) also use it in g2d_close() and g2d_remove() 5) put autosuspend on top Would this make sense? With best wishes, Tobias >> Changes in v2: >> - disable autosuspend mode again in g2d_remove() >> - only get sync in g2d_runqueue_worker() if there is node >>in the queue left >> >> Changes in v3: >> - actually delete node in g2d_remove_runqueue_nodes() >> >> Signed-off-by: Tobias Jakobi > > [...] > > Best regards
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Inki Dae wrote: > > > 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >> in mixer_cfg_layer(). >> Trigger this via atomic flush. >> >> Changes in v2: >> - issue mixer_cfg_layer() in mixer_disable() >> - rename fields as suggested by Andrzej >> - added docu to mixer context struct >> - simplify mixer_win_reset() as well >> >> Changes in v3: >> - simplify some conditions as suggested by Inki >> - add docu to mixer_cfg_layer() >> - fold switch statements into a single one >> >> Signed-off-by: Tobias Jakobi >> --- >> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >> ++ >> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >> 2 files changed, 92 insertions(+), 45 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >> b/drivers/gpu/drm/exynos/exynos_mixer.c >> index 1e78d57..4f06f4d 100644 >> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >> DRM_FORMAT_NV21, >> }; >> >> +/* >> + * Mixer context structure. >> + * >> + * @crtc: The HDMI CRTC attached to the mixer. >> + * @planes: Array of plane objects for each of the mixer windows. >> + * @active_windows: Cache of the mixer's hardware state. >> + * Tracks which mixer windows are active/inactive. >> + * @pipe: The CRTC index. >> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >> + * @mixer_resources: A struct containing registers, clocks, etc. >> + * @mxr_ver: The hardware revision/version of the mixer. >> + */ >> struct mixer_context { >> struct platform_device *pdev; >> struct device *dev; >> struct drm_device *drm_dev; >> struct exynos_drm_crtc *crtc; >> struct exynos_drm_plane planes[MIXER_WIN_NR]; >> +unsigned long active_windows; >> int pipe; >> unsigned long flags; >> >> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >> *ctx, unsigned int height) >> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >> } >> >> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >> -unsigned int priority, bool enable) >> +/** >> + * mixer_cfg_layer - apply layer configuration to hardware >> + * @ctx: mixer context >> + * >> + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers >> + * using the 'active_windows' field of the the mixer content, and >> + * the pixel format of the framebuffers associated with the enabled >> + * windows. >> + * >> + * Has to be called under mixer lock. >> + */ >> +static void mixer_cfg_layer(struct mixer_context *ctx) >> { >> struct mixer_resources *res = &ctx->mixer_res; >> -u32 val = enable ? ~0 : 0; >> - >> -switch (win) { >> -case 0: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP0_VAL(priority), >> -MXR_LAYER_CFG_GRP0_MASK); >> -break; >> -case 1: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP1_VAL(priority), >> -MXR_LAYER_CFG_GRP1_MASK); >> +unsigned int win; >> >> -break; >> -case VP_DEFAULT_WIN: >> -if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { >> -vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); >> -mixer_reg_writemask(res, MXR_CFG, val, >> -MXR_CFG_VP_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_VP_VAL(priority), >> -MXR_LAYER_CFG_VP_MASK); >> +struct exynos_drm_plane_state *state; >> +struct drm_framebuffer *fb; >> +unsigned int priority; >> +u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; >> +bool enable; >> + >> +for (win = 0; win < MIXER_WIN_NR; ++win) { >> +state = to_exynos_plane_state(ctx->planes[win].base.state); >> +fb = state->fb; >> + >> +priority = state->base.normalized_zpos + 1; >> +enable = test_bit(win, &ctx->active_windows); >> + >> +if (!enable) >> +continue; >> + >> +BUG_ON(!fb); > > Not good. Even through some problem happens at mixer driver, other KMS > drivers should work. That would be a issue at core level. And in this case, BUG_ON() should be triggered. - Tobias >
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello Inki, Inki Dae wrote: > 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >> in mixer_cfg_layer(). >> Trigger this via atomic flush. >> >> Changes in v2: >> - issue mixer_cfg_layer() in mixer_disable() >> - rename fields as suggested by Andrzej >> - added docu to mixer context struct >> - simplify mixer_win_reset() as well >> >> Changes in v3: >> - simplify some conditions as suggested by Inki >> - add docu to mixer_cfg_layer() >> - fold switch statements into a single one >> >> Signed-off-by: Tobias Jakobi >> --- >> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >> ++ >> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >> 2 files changed, 92 insertions(+), 45 deletions(-) >> >> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >> b/drivers/gpu/drm/exynos/exynos_mixer.c >> index 1e78d57..4f06f4d 100644 >> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >> DRM_FORMAT_NV21, >> }; >> >> +/* >> + * Mixer context structure. >> + * >> + * @crtc: The HDMI CRTC attached to the mixer. >> + * @planes: Array of plane objects for each of the mixer windows. >> + * @active_windows: Cache of the mixer's hardware state. >> + * Tracks which mixer windows are active/inactive. >> + * @pipe: The CRTC index. >> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >> + * @mixer_resources: A struct containing registers, clocks, etc. >> + * @mxr_ver: The hardware revision/version of the mixer. >> + */ >> struct mixer_context { >> struct platform_device *pdev; >> struct device *dev; >> struct drm_device *drm_dev; >> struct exynos_drm_crtc *crtc; >> struct exynos_drm_plane planes[MIXER_WIN_NR]; >> +unsigned long active_windows; >> int pipe; >> unsigned long flags; >> >> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >> *ctx, unsigned int height) >> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >> } >> >> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >> -unsigned int priority, bool enable) >> +/** >> + * mixer_cfg_layer - apply layer configuration to hardware >> + * @ctx: mixer context >> + * >> + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers >> + * using the 'active_windows' field of the the mixer content, and >> + * the pixel format of the framebuffers associated with the enabled >> + * windows. >> + * >> + * Has to be called under mixer lock. >> + */ >> +static void mixer_cfg_layer(struct mixer_context *ctx) >> { >> struct mixer_resources *res = &ctx->mixer_res; >> -u32 val = enable ? ~0 : 0; >> - >> -switch (win) { >> -case 0: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP0_VAL(priority), >> -MXR_LAYER_CFG_GRP0_MASK); >> -break; >> -case 1: >> -mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_GRP1_VAL(priority), >> -MXR_LAYER_CFG_GRP1_MASK); >> +unsigned int win; >> >> -break; >> -case VP_DEFAULT_WIN: >> -if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { >> -vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); >> -mixer_reg_writemask(res, MXR_CFG, val, >> -MXR_CFG_VP_ENABLE); >> -mixer_reg_writemask(res, MXR_LAYER_CFG, >> -MXR_LAYER_CFG_VP_VAL(priority), >> -MXR_LAYER_CFG_VP_MASK); >> +struct exynos_drm_plane_state *state; >> +struct drm_framebuffer *fb; >> +unsigned int priority; >> +u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; >> +bool enable; >> + >> +for (win = 0; win < MIXER_WIN_NR; ++win) { >> +sta
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hey Inki, Inki Dae wrote: > 2016ë 09ì 27ì¼ 14:40ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Inki Dae wrote: >>> >>> >>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>> in mixer_cfg_layer(). >>>> Trigger this via atomic flush. >>>> >>>> Changes in v2: >>>> - issue mixer_cfg_layer() in mixer_disable() >>>> - rename fields as suggested by Andrzej >>>> - added docu to mixer context struct >>>> - simplify mixer_win_reset() as well >>>> >>>> Changes in v3: >>>> - simplify some conditions as suggested by Inki >>>> - add docu to mixer_cfg_layer() >>>> - fold switch statements into a single one >>>> >>>> Signed-off-by: Tobias Jakobi >>>> --- >>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>> ++ >>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>> index 1e78d57..4f06f4d 100644 >>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>DRM_FORMAT_NV21, >>>> }; >>>> >>>> +/* >>>> + * Mixer context structure. >>>> + * >>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>> + * @planes: Array of plane objects for each of the mixer windows. >>>> + * @active_windows: Cache of the mixer's hardware state. >>>> + * Tracks which mixer windows are active/inactive. >>>> + * @pipe: The CRTC index. >>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>> + */ >>>> struct mixer_context { >>>>struct platform_device *pdev; >>>>struct device *dev; >>>>struct drm_device *drm_dev; >>>>struct exynos_drm_crtc *crtc; >>>>struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>> + unsigned long active_windows; >>>>int pipe; >>>>unsigned long flags; >>>> >>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >>>> *ctx, unsigned int height) >>>>mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>> } >>>> >>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >>>> - unsigned int priority, bool enable) >>>> +/** >>>> + * mixer_cfg_layer - apply layer configuration to hardware >>>> + * @ctx: mixer context >>>> + * >>>> + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers >>>> + * using the 'active_windows' field of the the mixer content, and >>>> + * the pixel format of the framebuffers associated with the enabled >>>> + * windows. >>>> + * >>>> + * Has to be called under mixer lock. >>>> + */ >>>> +static void mixer_cfg_layer(struct mixer_context *ctx) >>>> { >>>>struct mixer_resources *res = &ctx->mixer_res; >>>> - u32 val = enable ? ~0 : 0; >>>> - >>>> - switch (win) { >>>> - case 0: >>>> - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>> - MXR_LAYER_CFG_GRP0_VAL(priority), >>>> - MXR_LAYER_CFG_GRP0_MASK); >>>> - break; >>>> - case 1: >>>> - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>> - MXR_LAYER_CFG_GRP1_VAL(priority), >>>> - MXR_LAYER_CFG_GRP1_MASK); >>>> + unsigned int win; >>>> >>>> - break; >>>> - case VP_DEFAULT_WIN: >>>> - i
[RFC v3] drm/exynos: g2d: fix runtime PM
Hello Marek, Marek Szyprowski wrote: > Hi Tobias, > > On 2016-09-26 16:15, Tobias Jakobi wrote: >> Marek Szyprowski wrote: >>> On 2016-09-24 20:58, Tobias Jakobi wrote: >>>> The commit b05984e21a7e000bf5074ace00d7a574944b2c16 broke >>>> operation of the G2D. After this commit the following >>>> happens. >>>> - exynos_g2d_exec_ioctl() prepares a runqueue node and >>>> calls g2d_exec_runqueue() >>>> - g2d_exec_runqueue() calls g2d_dma_start() which gets >>>> runtime PM sync >>>> - runtime PM calls g2d_runtime_resume() >>>> - g2d_runtime_resume() calls g2d_exec_runqueue() >>>> >>>> Luckily for us this doesn't really loop, but creates a >>>> mutex lockup, which the kernel even predicts. >>>> >>>> Anyway, we fix this by reintroducing dedicated sleep >>>> operations again, and only letting runtime PM control >>>> the gate clock. >>>> >>>> This is not enough to fix the issue though. >>>> - We switch runtime PM to autosuspend. Currently clocks get >>>> disabled, and then re-enabled again in the runqueue worker >>>> when a node is completed and the next is started. >>>> With the upcoming introduction of IOMMU runtime PM this >>>> situations gets worse, since now also the IOMMU goes >>>> through a disable/enable cycle before the next node is >>>> started. >>>> - We consolidate all runtime PM management to the runqueue >>>> worker. >>>> - We introduce g2d_wait_finish() which waits until the currently >>>> processed runqueue node is finished. >>>> If this takes too long, the engine is forcibly reset. This >>>> is necessary to properly close the driver in case the engine >>>> should hang with read/write access to some area of memory. >>>> In this situation we can't properly unmap GEM/userptr >>>> objects, since this might create a pagefault. >>>> - Sleep suspend issues a suspend of the runqueue and then calls >>>> g2d_wait_finish(), which returns the engine in the idle state. >>>> The current runqueue node gets completed, all other queued >>>> nodes stay in the queue. There is no hardware state that >>>> needs to be retained. >>>> - Sleep resume just pokes the runqueue worker, which, should >>>> something be in queue, continues its work, or just exits. >>> IMHO there is too much done in one patch. It would be much easier to >>> understand it if the changes are split into 2 parts: restoring dedicated >>> speep callbacks and their integration with runqueue worker and addition >>> of autosuspend-based runtime pm. >> so you mean first revert your patch, and then put more changes on top of >> it in a separate patch? I'm not sure into which 'functional units' I >> should break this one down. >> >> I can of course create a separate patch for autosuspend, that that would >> only replace a put_sync() with mark_last_busy() + put_autosuspend(), >> wouldn't it? >> >> >> My current idea of functional units: >> 1) revert Marek's patch >> 2) move runpm management to g2d_runqueue_worker() >> 3) introduce g2d_wait_finish() and use it sleep call >> 4) also use it in g2d_close() and g2d_remove() >> 5) put autosuspend on top >> >> Would this make sense? > > Yes, definitely this approach makes much more sense in my opinion. I'm > sorry > for my broken initial patch and the additional work you had to do. No problem! Thanks for looking over this! With best wishes, Tobias > > Best regards
[PATCH 0/6] drm/exynos: g2d: rework sleep and runtime PM
Hello everyone, as discussed with Marek I have broken down my initial patch into smaller piecer. Anyway, this series fixes a regression introduced by commit b05984e21a7e000bf5074ace00d7a574944b2c16. With best wishes, Tobias Tobias Jakobi (6): Revert "drm/exynos: g2d: fix system and runtime pm integration" drm/exynos: g2d: move PM management to runqueue worker drm/exynos: g2d: remove runqueue nodes in g2d_{close,remove}() drm/exynos: g2d: wait for engine to finish drm/exynos: g2d: use autosuspend mode for PM runtime drm/exynos: g2d: simplify g2d_free_runqueue_node() drivers/gpu/drm/exynos/exynos_drm_g2d.c | 237 +--- 1 file changed, 188 insertions(+), 49 deletions(-) -- 2.7.3
[PATCH 1/6] Revert "drm/exynos: g2d: fix system and runtime pm integration"
This reverts commit b05984e21a7e000bf5074ace00d7a574944b2c16. The change, i.e. merging the sleep and runpm operations, produces a deadlock situation: (1) exynos_g2d_exec_ioctl() prepares a runqueue node and calls g2d_exec_runqueue() (2) g2d_exec_runqueue() calls g2d_dma_start() which gets runtime PM sync (3) runtime PM core calls g2d_runtime_resume() (4) g2d_runtime_resume() calls g2d_exec_runqueue(), which loops back to (2) Due to mutexes that are in place, a deadlock situation is created. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 29 ++--- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 6eca8bb..4bf00f5 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -1475,8 +1475,8 @@ static int g2d_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int g2d_runtime_suspend(struct device *dev) +#ifdef CONFIG_PM_SLEEP +static int g2d_suspend(struct device *dev) { struct g2d_data *g2d = dev_get_drvdata(dev); @@ -1490,6 +1490,25 @@ static int g2d_runtime_suspend(struct device *dev) flush_work(&g2d->runqueue_work); + return 0; +} + +static int g2d_resume(struct device *dev) +{ + struct g2d_data *g2d = dev_get_drvdata(dev); + + g2d->suspended = false; + g2d_exec_runqueue(g2d); + + return 0; +} +#endif + +#ifdef CONFIG_PM +static int g2d_runtime_suspend(struct device *dev) +{ + struct g2d_data *g2d = dev_get_drvdata(dev); + clk_disable_unprepare(g2d->gate_clk); return 0; @@ -1504,16 +1523,12 @@ static int g2d_runtime_resume(struct device *dev) if (ret < 0) dev_warn(dev, "failed to enable clock.\n"); - g2d->suspended = false; - g2d_exec_runqueue(g2d); - return ret; } #endif static const struct dev_pm_ops g2d_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, - pm_runtime_force_resume) + SET_SYSTEM_SLEEP_PM_OPS(g2d_suspend, g2d_resume) SET_RUNTIME_PM_OPS(g2d_runtime_suspend, g2d_runtime_resume, NULL) }; -- 2.7.3
[PATCH 2/6] drm/exynos: g2d: move PM management to runqueue worker
Do all pm_runtime_{get,put}() calls in the runqueue worker. Also keep track of the engine's idle/busy state. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 78 +++-- 1 file changed, 56 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 4bf00f5..eda385a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -138,6 +138,18 @@ enum g2d_reg_type { MAX_REG_TYPE_NR }; +enum g2d_flag_bits { + /* +* If set, suspends the runqueue worker after the currently +* processed node is finished. +*/ + G2D_BIT_SUSPEND_RUNQUEUE, + /* +* If set, indicates that the engine is currently busy. +*/ + G2D_BIT_ENGINE_BUSY, +}; + /* cmdlist data structure */ struct g2d_cmdlist { u32 head; @@ -226,7 +238,7 @@ struct g2d_data { struct workqueue_struct *g2d_workq; struct work_struct runqueue_work; struct exynos_drm_subdrvsubdrv; - boolsuspended; + unsigned long flags; /* cmdlist */ struct g2d_cmdlist_node *cmdlist_node; @@ -803,12 +815,8 @@ static void g2d_dma_start(struct g2d_data *g2d, struct g2d_cmdlist_node *node = list_first_entry(&runqueue_node->run_cmdlist, struct g2d_cmdlist_node, list); - int ret; - - ret = pm_runtime_get_sync(g2d->dev); - if (ret < 0) - return; + set_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); } @@ -858,18 +866,37 @@ static void g2d_runqueue_worker(struct work_struct *work) { struct g2d_data *g2d = container_of(work, struct g2d_data, runqueue_work); + struct g2d_runqueue_node *runqueue_node; + + /* +* The engine is busy and the completion of the current node is going +* to poke the runqueue worker, so nothing to do here. +*/ + if (test_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags)) + return; mutex_lock(&g2d->runqueue_mutex); - pm_runtime_put_sync(g2d->dev); - complete(&g2d->runqueue_node->complete); - if (g2d->runqueue_node->async) - g2d_free_runqueue_node(g2d, g2d->runqueue_node); + runqueue_node = g2d->runqueue_node; + g2d->runqueue_node = NULL; + + if (runqueue_node) { + pm_runtime_put(g2d->dev); + + complete(&runqueue_node->complete); + if (runqueue_node->async) + g2d_free_runqueue_node(g2d, runqueue_node); + } + + if (!test_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags)) { + g2d->runqueue_node = g2d_get_runqueue_node(g2d); + + if (g2d->runqueue_node) { + pm_runtime_get_sync(g2d->dev); + g2d_dma_start(g2d, g2d->runqueue_node); + } + } - if (g2d->suspended) - g2d->runqueue_node = NULL; - else - g2d_exec_runqueue(g2d); mutex_unlock(&g2d->runqueue_mutex); } @@ -918,8 +945,10 @@ static irqreturn_t g2d_irq_handler(int irq, void *dev_id) } } - if (pending & G2D_INTP_ACMD_FIN) + if (pending & G2D_INTP_ACMD_FIN) { + clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); queue_work(g2d->g2d_workq, &g2d->runqueue_work); + } return IRQ_HANDLED; } @@ -1259,10 +1288,11 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data, runqueue_node->pid = current->pid; runqueue_node->filp = file; list_add_tail(&runqueue_node->list, &g2d->runqueue); - if (!g2d->runqueue_node) - g2d_exec_runqueue(g2d); mutex_unlock(&g2d->runqueue_mutex); + /* Let the runqueue know that there is work to do. */ + queue_work(g2d->g2d_workq, &g2d->runqueue_work); + if (runqueue_node->async) goto out; @@ -1400,6 +1430,8 @@ static int g2d_probe(struct platform_device *pdev) } pm_runtime_enable(dev); + clear_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); + clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1458,6 +1490,9 @@ static int g2d_remove(struct platform_device *pdev) { struct g2d_data *g2d = platform_get_drvdata(pdev); + /* S
[PATCH 3/6] drm/exynos: g2d: remove runqueue nodes in g2d_{close, remove}()
The driver might be closed (and/or removed) while there are still nodes queued for processing. Make sure to remove these nodes, which means all of them in the case of g2d_remove() and only those belonging to the corresponding process in g2d_close(). Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 48 ++--- 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index eda385a..3599489 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -855,11 +855,27 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, kmem_cache_free(g2d->runqueue_slab, runqueue_node); } -static void g2d_exec_runqueue(struct g2d_data *g2d) +/** + * g2d_remove_runqueue_nodes - remove items from the list of runqueue nodes + * @g2d: G2D state object + * @file: if not zero, only remove items with this DRM file + * + * Has to be called under runqueue lock. + */ +static void g2d_remove_runqueue_nodes(struct g2d_data *g2d, struct drm_file* file) { - g2d->runqueue_node = g2d_get_runqueue_node(g2d); - if (g2d->runqueue_node) - g2d_dma_start(g2d, g2d->runqueue_node); + struct g2d_runqueue_node *node, *n; + + if (list_empty(&g2d->runqueue)) + return; + + list_for_each_entry_safe(node, n, &g2d->runqueue, list) { + if (file && node->filp != file) + continue; + + list_del_init(&node->list); + g2d_free_runqueue_node(g2d, node); + } } static void g2d_runqueue_worker(struct work_struct *work) @@ -1369,15 +1385,19 @@ static void g2d_close(struct drm_device *drm_dev, struct device *dev, if (!g2d) return; + /* Remove the runqueue nodes that belong to us. */ + mutex_lock(&g2d->runqueue_mutex); + g2d_remove_runqueue_nodes(g2d, file); + mutex_unlock(&g2d->runqueue_mutex); + + /* +* Even after the engine is idle, there might still be stale cmdlists +* (i.e. cmdlisst which we submitted but never executed) around, with +* their corresponding GEM/userptr buffers. +* Properly unmap these buffers here. +*/ mutex_lock(&g2d->cmdlist_mutex); list_for_each_entry_safe(node, n, &g2d_priv->inuse_cmdlist, list) { - /* -* unmap all gem objects not completed. -* -* P.S. if current process was terminated forcely then -* there may be some commands in inuse_cmdlist so unmap -* them. -*/ g2d_unmap_cmdlist_gem(g2d, node, file); list_move_tail(&node->list, &g2d->free_cmdlist); } @@ -1496,10 +1516,8 @@ static int g2d_remove(struct platform_device *pdev) cancel_work_sync(&g2d->runqueue_work); exynos_drm_subdrv_unregister(&g2d->subdrv); - while (g2d->runqueue_node) { - g2d_free_runqueue_node(g2d, g2d->runqueue_node); - g2d->runqueue_node = g2d_get_runqueue_node(g2d); - } + /* There should be no locking needed here. */ + g2d_remove_runqueue_nodes(g2d, NULL); pm_runtime_disable(&pdev->dev); -- 2.7.3
[PATCH 4/6] drm/exynos: g2d: wait for engine to finish
While the engine works on a runqueue node it does memory access to the buffers associated with that node. Make sure that the engine is idle when g2d_close() and/or g2d_remove() are called, i.e. buffer associated with the process (for g2d_close()), or all buffers (for g2d_remove()) can be safely be unmapped. We have to take into account that the engine might be in an undefined state, i.e. it hangs and doesn't become idle. In this case, we issue a hardware reset to return the hardware and the driver context into a proper state. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 84 ++--- 1 file changed, 77 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 3599489..5de5ea4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -258,6 +258,12 @@ struct g2d_data { unsigned long max_pool; }; +static inline void g2d_hw_reset(struct g2d_data *g2d) +{ + writel(G2D_R | G2D_SFRCLEAR, g2d->regs + G2D_SOFT_RESET); + clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); +} + static int g2d_init_cmdlist(struct g2d_data *g2d) { struct device *dev = g2d->dev; @@ -969,6 +975,63 @@ static irqreturn_t g2d_irq_handler(int irq, void *dev_id) return IRQ_HANDLED; } +/** + * g2d_wait_finish - wait for the G2D engine to finish the current runqueue node + * @g2d: G2D state object + * @file: if not zero, only wait if the current runqueue node belongs + *to the DRM file + * + * Should the engine not become idle after a 100ms timeout, a hardware + * reset is issued. + */ +static void g2d_wait_finish(struct g2d_data *g2d, struct drm_file *file) +{ + struct device *dev = g2d->dev; + + struct g2d_runqueue_node *runqueue_node = NULL; + unsigned int tries = 10; + + mutex_lock(&g2d->runqueue_mutex); + + /* If no node is currently processed, we have nothing to do. */ + if (!g2d->runqueue_node) + goto out; + + runqueue_node = g2d->runqueue_node; + + /* Check if the currently processed item belongs to us. */ + if (file && runqueue_node->filp != file) + goto out; + + mutex_unlock(&g2d->runqueue_mutex); + + /* Wait for the G2D engine to finish. */ + while (tries-- && (g2d->runqueue_node == runqueue_node)) + mdelay(10); + + mutex_lock(&g2d->runqueue_mutex); + + if (g2d->runqueue_node != runqueue_node) + goto out; + + dev_err(dev, "wait timed out, resetting engine...\n"); + g2d_hw_reset(g2d); + + /* +* After the hardware reset of the engine we are going to loose +* the IRQ which triggers the PM runtime put(). +* So do this manually here. +*/ + pm_runtime_put(dev); + + complete(&runqueue_node->complete); + if (runqueue_node->async) + g2d_free_runqueue_node(g2d, runqueue_node); + +out: + mutex_unlock(&g2d->runqueue_mutex); +} + static int g2d_check_reg_offset(struct device *dev, struct g2d_cmdlist_node *node, int nr, bool for_addr) @@ -1391,6 +1454,13 @@ static void g2d_close(struct drm_device *drm_dev, struct device *dev, mutex_unlock(&g2d->runqueue_mutex); /* +* Wait for the runqueue worker to finish its current node. +* After this the engine should no longer be accessing any +* memory belonging to us. +*/ + g2d_wait_finish(g2d, file); + + /* * Even after the engine is idle, there might still be stale cmdlists * (i.e. cmdlisst which we submitted but never executed) around, with * their corresponding GEM/userptr buffers. @@ -1510,8 +1580,9 @@ static int g2d_remove(struct platform_device *pdev) { struct g2d_data *g2d = platform_get_drvdata(pdev); - /* Suspend runqueue operation. */ + /* Suspend operation and wait for engine idle. */ set_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); + g2d_wait_finish(g2d, NULL); cancel_work_sync(&g2d->runqueue_work); exynos_drm_subdrv_unregister(&g2d->subdrv); @@ -1533,13 +1604,12 @@ static int g2d_suspend(struct device *dev) { struct g2d_data *g2d = dev_get_drvdata(dev); - /* Suspend runqueue operation. */ + /* +* Suspend the runqueue worker operation and wait until the G2D +* engine is idle. +*/ set_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); - - while (g2d->runqueue_node) - /* FIXME: good range? */ - usleep_range(500, 1000); - + g2d_wait_finish(g2d, NULL); flush_work(&g2d->runqueue_work); return 0; -- 2.7.3
[PATCH 5/6] drm/exynos: g2d: use autosuspend mode for PM runtime
The runqueue worker currently issues a get() when a new node is processed, and a put() once a node is completed. The corresponding suspend and resume calls currently only do clock gating, but with the upcoming introduction of IOMMU runpm also the corresponding IOMMU domain gets enabled (for get()) and disabled (for put()). This introduces performance regressions with we mitigate here. Switch PM runtime to autosuspend, such that clock gating and IOMMU control only happens when the engine is idle for a 'long' time. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 9 +++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 5de5ea4..1a000c1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -903,7 +903,8 @@ static void g2d_runqueue_worker(struct work_struct *work) g2d->runqueue_node = NULL; if (runqueue_node) { - pm_runtime_put(g2d->dev); + pm_runtime_mark_last_busy(g2d->dev); + pm_runtime_put_autosuspend(g2d->dev); complete(&runqueue_node->complete); if (runqueue_node->async) @@ -1022,7 +1023,8 @@ static void g2d_wait_finish(struct g2d_data *g2d, struct drm_file *file) * the IRQ which triggers the PM runtime put(). * So do this manually here. */ - pm_runtime_put(dev); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); complete(&runqueue_node->complete); if (runqueue_node->async) @@ -1519,6 +1521,8 @@ static int g2d_probe(struct platform_device *pdev) goto err_destroy_workqueue; } + pm_runtime_use_autosuspend(dev); + pm_runtime_set_autosuspend_delay(dev, 2000); pm_runtime_enable(dev); clear_bit(G2D_BIT_SUSPEND_RUNQUEUE, &g2d->flags); clear_bit(G2D_BIT_ENGINE_BUSY, &g2d->flags); @@ -1590,6 +1594,7 @@ static int g2d_remove(struct platform_device *pdev) /* There should be no locking needed here. */ g2d_remove_runqueue_nodes(g2d, NULL); + pm_runtime_dont_use_autosuspend(&pdev->dev); pm_runtime_disable(&pdev->dev); g2d_fini_cmdlist(g2d); -- 2.7.3
[PATCH 6/6] drm/exynos: g2d: simplify g2d_free_runqueue_node()
The function is never called with zero 'runqueue_node'. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_drm_g2d.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 1a000c1..fa25c7f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c @@ -845,9 +845,6 @@ static void g2d_free_runqueue_node(struct g2d_data *g2d, { struct g2d_cmdlist_node *node; - if (!runqueue_node) - return; - mutex_lock(&g2d->cmdlist_mutex); /* * commands in run_cmdlist have been completed so unmap all gem -- 2.7.3
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello Andrzej, Andrzej Hajda wrote: > On 27.09.2016 13:22, Tobias Jakobi wrote: >> Hello Inki, >> >> >> Inki Dae wrote: >>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>> in mixer_cfg_layer(). >>>> Trigger this via atomic flush. >>>> >>>> Changes in v2: >>>> - issue mixer_cfg_layer() in mixer_disable() >>>> - rename fields as suggested by Andrzej >>>> - added docu to mixer context struct >>>> - simplify mixer_win_reset() as well >>>> >>>> Changes in v3: >>>> - simplify some conditions as suggested by Inki >>>> - add docu to mixer_cfg_layer() >>>> - fold switch statements into a single one >>>> >>>> Signed-off-by: Tobias Jakobi >>>> --- >>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>> ++ >>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>> >>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>> index 1e78d57..4f06f4d 100644 >>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>DRM_FORMAT_NV21, >>>> }; >>>> >>>> +/* >>>> + * Mixer context structure. >>>> + * >>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>> + * @planes: Array of plane objects for each of the mixer windows. >>>> + * @active_windows: Cache of the mixer's hardware state. >>>> + * Tracks which mixer windows are active/inactive. >>>> + * @pipe: The CRTC index. >>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>> + */ >>>> struct mixer_context { >>>>struct platform_device *pdev; >>>>struct device *dev; >>>>struct drm_device *drm_dev; >>>>struct exynos_drm_crtc *crtc; >>>>struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>> + unsigned long active_windows; >>>>int pipe; >>>>unsigned long flags; >>>> >>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >>>> *ctx, unsigned int height) >>>>mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>> } >>>> >>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >>>> - unsigned int priority, bool enable) >>>> +/** >>>> + * mixer_cfg_layer - apply layer configuration to hardware >>>> + * @ctx: mixer context >>>> + * >>>> + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers >>>> + * using the 'active_windows' field of the the mixer content, and >>>> + * the pixel format of the framebuffers associated with the enabled >>>> + * windows. >>>> + * >>>> + * Has to be called under mixer lock. >>>> + */ >>>> +static void mixer_cfg_layer(struct mixer_context *ctx) >>>> { >>>>struct mixer_resources *res = &ctx->mixer_res; >>>> - u32 val = enable ? ~0 : 0; >>>> - >>>> - switch (win) { >>>> - case 0: >>>> - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); >>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>> - MXR_LAYER_CFG_GRP0_VAL(priority), >>>> - MXR_LAYER_CFG_GRP0_MASK); >>>> - break; >>>> - case 1: >>>> - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); >>>> - mixer_reg_writemask(res, MXR_LAYER_CFG, >>>> - MXR_LAYER_CFG_GRP1_VAL(priority), >>>> - MXR_LAYER_CFG_GRP1_MASK); >>>> + unsigned int win; >>>> >>>> - break; >>>> - case VP_DEFAULT_WI
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hey Inki, Inki Dae wrote: > > > 2016ë 09ì 28ì¼ 01:52ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Hello Andrzej, >> >> >> Andrzej Hajda wrote: >>> On 27.09.2016 13:22, Tobias Jakobi wrote: >>>> Hello Inki, >>>> >>>> >>>> Inki Dae wrote: >>>>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>>> in mixer_cfg_layer(). >>>>>> Trigger this via atomic flush. >>>>>> >>>>>> Changes in v2: >>>>>> - issue mixer_cfg_layer() in mixer_disable() >>>>>> - rename fields as suggested by Andrzej >>>>>> - added docu to mixer context struct >>>>>> - simplify mixer_win_reset() as well >>>>>> >>>>>> Changes in v3: >>>>>> - simplify some conditions as suggested by Inki >>>>>> - add docu to mixer_cfg_layer() >>>>>> - fold switch statements into a single one >>>>>> >>>>>> Signed-off-by: Tobias Jakobi >>>>>> --- >>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>>>> ++ >>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>>>> >>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>> index 1e78d57..4f06f4d 100644 >>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>>> DRM_FORMAT_NV21, >>>>>> }; >>>>>> >>>>>> +/* >>>>>> + * Mixer context structure. >>>>>> + * >>>>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>>>> + * @planes: Array of plane objects for each of the mixer windows. >>>>>> + * @active_windows: Cache of the mixer's hardware state. >>>>>> + * Tracks which mixer windows are active/inactive. >>>>>> + * @pipe: The CRTC index. >>>>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>>>> + */ >>>>>> struct mixer_context { >>>>>> struct platform_device *pdev; >>>>>> struct device *dev; >>>>>> struct drm_device *drm_dev; >>>>>> struct exynos_drm_crtc *crtc; >>>>>> struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>>> +unsigned long active_windows; >>>>>> int pipe; >>>>>> unsigned long flags; >>>>>> >>>>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context >>>>>> *ctx, unsigned int height) >>>>>> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>>>> } >>>>>> >>>>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, >>>>>> -unsigned int priority, bool enable) >>>>>> +/** >>>>>> + * mixer_cfg_layer - apply layer configuration to hardware >>>>>> + * @ctx: mixer context >>>>>> + * >>>>>> + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers >>>>>> + * using the 'active_windows' field of the the mixer content, and >>>>>> + * the pixel format of the framebuffers associated with the enabled >>>>>> + * windows. >>>>>> + * >>>>>> + * Has to be called under mixer lock. >>>>>> + */ >>>>>> +static void mixer_cfg_layer(struct mixer_context *ctx) >>>>>> { >>>>>> struct mixer_resources *res = &ctx->mixer_res; >>>>>> -u32 val = enable ? ~0 : 0; >>>>>> - >>>>>> -swi
[PATCH 0/6] drm/exynos: g2d: rework sleep and runtime PM
Hello, Inki Dae wrote: > We would need to review this patch series for -next in a hurry. > I have to request git-pull soon. I just want to point out that I have yet to test the split series. Currently it's only compile-tested. But I have done a stress test with both sync and async execution mode with the first version of the patch (the big one, before the split), and there everything seemed to work. So this should apply for this series as well... hopefully :) With best wishes, Tobias > 2016ë 09ì 28ì¼ 00:50ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Hello everyone, >> >> as discussed with Marek I have broken down my initial patch into smaller >> piecer. >> >> Anyway, this series fixes a regression introduced by commit >> b05984e21a7e000bf5074ace00d7a574944b2c16. >> >> With best wishes, >> Tobias >> >> Tobias Jakobi (6): >> Revert "drm/exynos: g2d: fix system and runtime pm integration" >> drm/exynos: g2d: move PM management to runqueue worker >> drm/exynos: g2d: remove runqueue nodes in g2d_{close,remove}() >> drm/exynos: g2d: wait for engine to finish >> drm/exynos: g2d: use autosuspend mode for PM runtime >> drm/exynos: g2d: simplify g2d_free_runqueue_node() >> >> drivers/gpu/drm/exynos/exynos_drm_g2d.c | 237 >> +--- >> 1 file changed, 188 insertions(+), 49 deletions(-) >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" > in > the body of a message to majordomo at vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html >
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello Inki, Inki Dae wrote: > > > 2016ë 09ì 28ì¼ 08:31ì Inki Dae ì´(ê°) ì´ ê¸: >> >> >> 2016ë 09ì 28ì¼ 01:52ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>> Hello Andrzej, >>> >>> >>> Andrzej Hajda wrote: >>>> On 27.09.2016 13:22, Tobias Jakobi wrote: >>>>> Hello Inki, >>>>> >>>>> >>>>> Inki Dae wrote: >>>>>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>>>> in mixer_cfg_layer(). >>>>>>> Trigger this via atomic flush. >>>>>>> >>>>>>> Changes in v2: >>>>>>> - issue mixer_cfg_layer() in mixer_disable() >>>>>>> - rename fields as suggested by Andrzej >>>>>>> - added docu to mixer context struct >>>>>>> - simplify mixer_win_reset() as well >>>>>>> >>>>>>> Changes in v3: >>>>>>> - simplify some conditions as suggested by Inki >>>>>>> - add docu to mixer_cfg_layer() >>>>>>> - fold switch statements into a single one >>>>>>> >>>>>>> Signed-off-by: Tobias Jakobi >>>>>>> --- >>>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>>>>> ++ >>>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>>>>> >>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> index 1e78d57..4f06f4d 100644 >>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>>>> DRM_FORMAT_NV21, >>>>>>> }; >>>>>>> >>>>>>> +/* >>>>>>> + * Mixer context structure. >>>>>>> + * >>>>>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>>>>> + * @planes: Array of plane objects for each of the mixer windows. >>>>>>> + * @active_windows: Cache of the mixer's hardware state. >>>>>>> + * Tracks which mixer windows are active/inactive. >>>>>>> + * @pipe: The CRTC index. >>>>>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>>>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>>>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>>>>> + */ >>>>>>> struct mixer_context { >>>>>>> struct platform_device *pdev; >>>>>>> struct device *dev; >>>>>>> struct drm_device *drm_dev; >>>>>>> struct exynos_drm_crtc *crtc; >>>>>>> struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>>>> + unsigned long active_windows; >>>>>>> int pipe; >>>>>>> unsigned long flags; >>>>>>> >>>>>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct >>>>>>> mixer_context *ctx, unsigned int height) >>>>>>> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>>>>> } >>>>>>> >>>>>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int >>>>>>> win, >>>>>>> - unsigned int priority, bool enable) >>>>>>> +/** >>>>>>> + * mixer_cfg_layer - apply layer configuration to hardware >>>>>>> + * @ctx: mixer context >>>>>>> + * >>>>>>> + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers >>>>>>> + * using the 'active_windows' field of the the mixer content, and >>>>>>> + * the pixel format of the framebuffers associated with the enabled >>>>>>> + * windows. >>>>
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Inki Dae wrote: > > > 2016ë 09ì 28ì¼ 09:03ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Hey Inki, >> >> >> Inki Dae wrote: >>> >>> >>> 2016ë 09ì 28ì¼ 01:52ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>> Hello Andrzej, >>>> >>>> >>>> Andrzej Hajda wrote: >>>>> On 27.09.2016 13:22, Tobias Jakobi wrote: >>>>>> Hello Inki, >>>>>> >>>>>> >>>>>> Inki Dae wrote: >>>>>>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>>>>> in mixer_cfg_layer(). >>>>>>>> Trigger this via atomic flush. >>>>>>>> >>>>>>>> Changes in v2: >>>>>>>> - issue mixer_cfg_layer() in mixer_disable() >>>>>>>> - rename fields as suggested by Andrzej >>>>>>>> - added docu to mixer context struct >>>>>>>> - simplify mixer_win_reset() as well >>>>>>>> >>>>>>>> Changes in v3: >>>>>>>> - simplify some conditions as suggested by Inki >>>>>>>> - add docu to mixer_cfg_layer() >>>>>>>> - fold switch statements into a single one >>>>>>>> >>>>>>>> Signed-off-by: Tobias Jakobi >>>>>>>> --- >>>>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>>>>>> ++ >>>>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>>>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>>>>>> >>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> index 1e78d57..4f06f4d 100644 >>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>>>>>DRM_FORMAT_NV21, >>>>>>>> }; >>>>>>>> >>>>>>>> +/* >>>>>>>> + * Mixer context structure. >>>>>>>> + * >>>>>>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>>>>>> + * @planes: Array of plane objects for each of the mixer windows. >>>>>>>> + * @active_windows: Cache of the mixer's hardware state. >>>>>>>> + * Tracks which mixer windows are active/inactive. >>>>>>>> + * @pipe: The CRTC index. >>>>>>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>>>>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>>>>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>>>>>> + */ >>>>>>>> struct mixer_context { >>>>>>>>struct platform_device *pdev; >>>>>>>>struct device *dev; >>>>>>>>struct drm_device *drm_dev; >>>>>>>>struct exynos_drm_crtc *crtc; >>>>>>>>struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>>>>> + unsigned long active_windows; >>>>>>>>int pipe; >>>>>>>>unsigned long flags; >>>>>>>> >>>>>>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct >>>>>>>> mixer_context *ctx, unsigned int height) >>>>>>>>mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>>>>>> } >>>>>>>> >>>>>>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int >>>>>>>> win, >>>>>>>> - unsigned int priority, bool enable) >>>>>>>> +/** >>>>>>>> + * mixer_cfg_layer - apply layer configuration to hardware >>>>>>>> + * @ctx:
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello Inki, Inki Dae wrote: > > > 2016ë 09ì 28ì¼ 09:03ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Hey Inki, >> >> >> Inki Dae wrote: >>> >>> >>> 2016ë 09ì 28ì¼ 01:52ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>> Hello Andrzej, >>>> >>>> >>>> Andrzej Hajda wrote: >>>>> On 27.09.2016 13:22, Tobias Jakobi wrote: >>>>>> Hello Inki, >>>>>> >>>>>> >>>>>> Inki Dae wrote: >>>>>>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>>>>> in mixer_cfg_layer(). >>>>>>>> Trigger this via atomic flush. >>>>>>>> >>>>>>>> Changes in v2: >>>>>>>> - issue mixer_cfg_layer() in mixer_disable() >>>>>>>> - rename fields as suggested by Andrzej >>>>>>>> - added docu to mixer context struct >>>>>>>> - simplify mixer_win_reset() as well >>>>>>>> >>>>>>>> Changes in v3: >>>>>>>> - simplify some conditions as suggested by Inki >>>>>>>> - add docu to mixer_cfg_layer() >>>>>>>> - fold switch statements into a single one >>>>>>>> >>>>>>>> Signed-off-by: Tobias Jakobi >>>>>>>> --- >>>>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>>>>>> ++ >>>>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>>>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>>>>>> >>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> index 1e78d57..4f06f4d 100644 >>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>>>>>DRM_FORMAT_NV21, >>>>>>>> }; >>>>>>>> >>>>>>>> +/* >>>>>>>> + * Mixer context structure. >>>>>>>> + * >>>>>>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>>>>>> + * @planes: Array of plane objects for each of the mixer windows. >>>>>>>> + * @active_windows: Cache of the mixer's hardware state. >>>>>>>> + * Tracks which mixer windows are active/inactive. >>>>>>>> + * @pipe: The CRTC index. >>>>>>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>>>>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>>>>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>>>>>> + */ >>>>>>>> struct mixer_context { >>>>>>>>struct platform_device *pdev; >>>>>>>>struct device *dev; >>>>>>>>struct drm_device *drm_dev; >>>>>>>>struct exynos_drm_crtc *crtc; >>>>>>>>struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>>>>> + unsigned long active_windows; >>>>>>>>int pipe; >>>>>>>>unsigned long flags; >>>>>>>> >>>>>>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct >>>>>>>> mixer_context *ctx, unsigned int height) >>>>>>>>mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>>>>>> } >>>>>>>> >>>>>>>> -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int >>>>>>>> win, >>>>>>>> - unsigned int priority, bool enable) >>>>>>>> +/** >>>>>>>> + * mixer_cfg_layer - apply layer configuration to hardware >>>>>>>> + * @ctx:
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello Inki, Inki Dae wrote: > > > 2016ë 09ì 28ì¼ 09:12ì Tobias Jakobi ì´(ê°) ì´ ê¸: >> Hello Inki, >> >> >> Inki Dae wrote: >>> >>> >>> 2016ë 09ì 28ì¼ 08:31ì Inki Dae ì´(ê°) ì´ ê¸: >>>> >>>> >>>> 2016ë 09ì 28ì¼ 01:52ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>> Hello Andrzej, >>>>> >>>>> >>>>> Andrzej Hajda wrote: >>>>>> On 27.09.2016 13:22, Tobias Jakobi wrote: >>>>>>> Hello Inki, >>>>>>> >>>>>>> >>>>>>> Inki Dae wrote: >>>>>>>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>>>>>> in mixer_cfg_layer(). >>>>>>>>> Trigger this via atomic flush. >>>>>>>>> >>>>>>>>> Changes in v2: >>>>>>>>> - issue mixer_cfg_layer() in mixer_disable() >>>>>>>>> - rename fields as suggested by Andrzej >>>>>>>>> - added docu to mixer context struct >>>>>>>>> - simplify mixer_win_reset() as well >>>>>>>>> >>>>>>>>> Changes in v3: >>>>>>>>> - simplify some conditions as suggested by Inki >>>>>>>>> - add docu to mixer_cfg_layer() >>>>>>>>> - fold switch statements into a single one >>>>>>>>> >>>>>>>>> Signed-off-by: Tobias Jakobi >>>>>>>>> --- >>>>>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>>>>>>> ++ >>>>>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>>>>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>>>>>>> >>>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>> index 1e78d57..4f06f4d 100644 >>>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>>>>>> DRM_FORMAT_NV21, >>>>>>>>> }; >>>>>>>>> >>>>>>>>> +/* >>>>>>>>> + * Mixer context structure. >>>>>>>>> + * >>>>>>>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>>>>>>> + * @planes: Array of plane objects for each of the mixer windows. >>>>>>>>> + * @active_windows: Cache of the mixer's hardware state. >>>>>>>>> + * Tracks which mixer windows are active/inactive. >>>>>>>>> + * @pipe: The CRTC index. >>>>>>>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>>>>>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>>>>>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>>>>>>> + */ >>>>>>>>> struct mixer_context { >>>>>>>>> struct platform_device *pdev; >>>>>>>>> struct device *dev; >>>>>>>>> struct drm_device *drm_dev; >>>>>>>>> struct exynos_drm_crtc *crtc; >>>>>>>>> struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>>>>>> + unsigned long active_windows; >>>>>>>>> int pipe; >>>>>>>>> unsigned long flags; >>>>>>>>> >>>>>>>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct >>>>>>>>> mixer_context *ctx, unsigned int height) >>>>>>>>> mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); >>>>>>>>> } >>>>>>>>> >>>>>>>>> -static void mixer_cf
[PATCH v3] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Inki Dae wrote: > 2016-09-28 18:06 GMT+09:00 Tobias Jakobi : >> Hello Inki, >> >> >> Inki Dae wrote: >>> >>> >>> 2016ë 09ì 28ì¼ 09:03ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>> Hey Inki, >>>> >>>> >>>> Inki Dae wrote: >>>>> >>>>> >>>>> 2016ë 09ì 28ì¼ 01:52ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>> Hello Andrzej, >>>>>> >>>>>> >>>>>> Andrzej Hajda wrote: >>>>>>> On 27.09.2016 13:22, Tobias Jakobi wrote: >>>>>>>> Hello Inki, >>>>>>>> >>>>>>>> >>>>>>>> Inki Dae wrote: >>>>>>>>> 2016ë 09ì 26ì¼ 20:36ì Tobias Jakobi ì´(ê°) ì´ ê¸: >>>>>>>>>> Only manipulate the MXR_CFG and MXR_LAYER_CFG registers once >>>>>>>>>> in mixer_cfg_layer(). >>>>>>>>>> Trigger this via atomic flush. >>>>>>>>>> >>>>>>>>>> Changes in v2: >>>>>>>>>> - issue mixer_cfg_layer() in mixer_disable() >>>>>>>>>> - rename fields as suggested by Andrzej >>>>>>>>>> - added docu to mixer context struct >>>>>>>>>> - simplify mixer_win_reset() as well >>>>>>>>>> >>>>>>>>>> Changes in v3: >>>>>>>>>> - simplify some conditions as suggested by Inki >>>>>>>>>> - add docu to mixer_cfg_layer() >>>>>>>>>> - fold switch statements into a single one >>>>>>>>>> >>>>>>>>>> Signed-off-by: Tobias Jakobi >>>>>>>>>> --- >>>>>>>>>> drivers/gpu/drm/exynos/exynos_mixer.c | 135 >>>>>>>>>> ++ >>>>>>>>>> drivers/gpu/drm/exynos/regs-mixer.h | 2 + >>>>>>>>>> 2 files changed, 92 insertions(+), 45 deletions(-) >>>>>>>>>> >>>>>>>>>> diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>>> b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>>> index 1e78d57..4f06f4d 100644 >>>>>>>>>> --- a/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>>> +++ b/drivers/gpu/drm/exynos/exynos_mixer.c >>>>>>>>>> @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { >>>>>>>>>>DRM_FORMAT_NV21, >>>>>>>>>> }; >>>>>>>>>> >>>>>>>>>> +/* >>>>>>>>>> + * Mixer context structure. >>>>>>>>>> + * >>>>>>>>>> + * @crtc: The HDMI CRTC attached to the mixer. >>>>>>>>>> + * @planes: Array of plane objects for each of the mixer windows. >>>>>>>>>> + * @active_windows: Cache of the mixer's hardware state. >>>>>>>>>> + * Tracks which mixer windows are active/inactive. >>>>>>>>>> + * @pipe: The CRTC index. >>>>>>>>>> + * @flags: Bitfield build from the mixer_flag_bits enumerator. >>>>>>>>>> + * @mixer_resources: A struct containing registers, clocks, etc. >>>>>>>>>> + * @mxr_ver: The hardware revision/version of the mixer. >>>>>>>>>> + */ >>>>>>>>>> struct mixer_context { >>>>>>>>>>struct platform_device *pdev; >>>>>>>>>>struct device *dev; >>>>>>>>>>struct drm_device *drm_dev; >>>>>>>>>>struct exynos_drm_crtc *crtc; >>>>>>>>>>struct exynos_drm_plane planes[MIXER_WIN_NR]; >>>>>>>>>> + unsigned long active_windows; >>>>>>>>>>int pipe; >>>>>>>>>>unsigned long flags; >>>>>>>>>> >>>>>>>>>> @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct >>>>>>
[PATCH 0/6] drm/exynos: g2d: rework sleep and runtime PM
Hello Marek, Marek Szyprowski wrote: > Dear Tobias, > > > On 2016-09-27 17:50, Tobias Jakobi wrote: >> Hello everyone, >> >> as discussed with Marek I have broken down my initial patch into >> smaller piecer. >> >> Anyway, this series fixes a regression introduced by commit >> b05984e21a7e000bf5074ace00d7a574944b2c16. >> >> With best wishes, >> Tobias > > Patches looks really nice! However I didn't have time to test them on > the real > hardware. thanks for having a look! I have just tested the split version of the patch on top of 4.8-rc8, and can confirm that all the tests in upstream libdrm are working. With best wishes, Tobias > You can add my: > Acked-by: Marek Szyprowski > >> Tobias Jakobi (6): >>Revert "drm/exynos: g2d: fix system and runtime pm integration" >>drm/exynos: g2d: move PM management to runqueue worker >>drm/exynos: g2d: remove runqueue nodes in g2d_{close,remove}() >>drm/exynos: g2d: wait for engine to finish >>drm/exynos: g2d: use autosuspend mode for PM runtime >>drm/exynos: g2d: simplify g2d_free_runqueue_node() >> >> drivers/gpu/drm/exynos/exynos_drm_g2d.c | 237 >> +--- >> 1 file changed, 188 insertions(+), 49 deletions(-) >> > > Best regards
[PATCH v4] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Hello everyone, the recent discussion about this patch has made me realise that the purpose of the patch, and in particular what it does, and what does not, was too unclear. Hence I'm resending the patch with a (hopefully) improved and expanded commit description. With best wishes, Tobias Tobias Jakobi (1): drm/exynos: mixer: configure layers once in mixer_atomic_flush() drivers/gpu/drm/exynos/exynos_mixer.c | 135 ++ drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 92 insertions(+), 45 deletions(-) -- 2.7.3
[PATCH v4] drm/exynos: mixer: configure layers once in mixer_atomic_flush()
Consider the following scenario: - mixer hardware block is present including video processor - userspace uses atomic DRM API - userspace uses all available planes The following call sequence (simplified) now happens when userspace issues an atomic commit. (1) mixer_atomic_begin() (2) mixer_update_plane() [for 1st mixer plane] (3) mixer_update_plane() [for 2nd mixer plane] (4) mixer_update_plane() [for video plane] (5) mixer_atomic_flush() For the 1st and 2nd mixer plane mixer_update_plane() internally calls mixer_graph_buffer(), for the video plane vp_video_buffer() is called. Both mixer_graph_buffer() and vp_video_buffer() setup registers and issue these calls near the end. - mixer_cfg_layer() & mixer_cfg_gfx_blend() [mixer] - mixer_cfg_layer() & mixer_cfg_vp_blend() [VP] mixer_cfg_layer() manipulates the MXR_CFG and MXR_LAYER_CFG register. So for each atomic commit we have 6x mixer_reg_writemask(). By rewriting mixer_cfg_layer() and moving it to the atomic flush step, we reduce this to 2x mixer_reg_writemask(). This is the initial step to consolidate manipulation of MXR_CFG and MXR_LAYER_CFG to mixer_atomic_flush(). A follow-up patch is going to move mixer_cfg_scan() and mixer_cfg_rgb_fmt() as well. To point out: - this is not fixing any bugs - this is not going to improve performance (at least not noticeable) This is merely some micro-optimisation and the aforementioned consolidation of register manipulation. Signed-off-by: Tobias Jakobi --- drivers/gpu/drm/exynos/exynos_mixer.c | 135 ++ drivers/gpu/drm/exynos/regs-mixer.h | 2 + 2 files changed, 92 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 1e78d57..4f06f4d 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -93,12 +93,25 @@ static const uint32_t vp_formats[] = { DRM_FORMAT_NV21, }; +/* + * Mixer context structure. + * + * @crtc: The HDMI CRTC attached to the mixer. + * @planes: Array of plane objects for each of the mixer windows. + * @active_windows: Cache of the mixer's hardware state. + * Tracks which mixer windows are active/inactive. + * @pipe: The CRTC index. + * @flags: Bitfield build from the mixer_flag_bits enumerator. + * @mixer_resources: A struct containing registers, clocks, etc. + * @mxr_ver: The hardware revision/version of the mixer. + */ struct mixer_context { struct platform_device *pdev; struct device *dev; struct drm_device *drm_dev; struct exynos_drm_crtc *crtc; struct exynos_drm_plane planes[MIXER_WIN_NR]; + unsigned long active_windows; int pipe; unsigned long flags; @@ -418,37 +431,70 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); } -static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, - unsigned int priority, bool enable) +/** + * mixer_cfg_layer - apply layer configuration to hardware + * @ctx: mixer context + * + * This configures the MXR_CFG and MXR_LAYER_CFG hardware registers + * using the 'active_windows' field of the the mixer content, and + * the pixel format of the framebuffers associated with the enabled + * windows. + * + * Has to be called under mixer lock. + */ +static void mixer_cfg_layer(struct mixer_context *ctx) { struct mixer_resources *res = &ctx->mixer_res; - u32 val = enable ? ~0 : 0; - - switch (win) { - case 0: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP0_VAL(priority), - MXR_LAYER_CFG_GRP0_MASK); - break; - case 1: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_GRP1_VAL(priority), - MXR_LAYER_CFG_GRP1_MASK); + unsigned int win; - break; - case VP_DEFAULT_WIN: - if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, - MXR_CFG_VP_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, - MXR_LAYER_CFG_VP_VAL(priority), - MXR_LAYER_CFG_VP_MASK); + struct exynos_drm_plane_state *state; + struct drm_framebuffer *fb; + unsigned int priority; + u32 mxr_cfg = 0, mxr_layer_cfg = 0, vp_enable = 0; +