Message ID | 20180820132405.28855-1-alexandru-cosmin.gheorghe@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm/malidp: Fix writeback in NV12 | expand |
Hi Alex, On Mon, Aug 20, 2018 at 02:24:05PM +0100, Alexandru Gheorghe wrote: >When we want to writeback to memory in NV12 format we need to program >the RGB2YUV coefficients. >Currently, we don't program the coefficients and the NV12 doesn't work >at all. > >This patchset fixes that by programming a sane default(bt709, limited >range) as rgb2yuv coefficients. > >In the long run, probably we need to think of a way for userspace to >be able to program that, but for now I think this is better than not >working at all or not advertising NV12 as a supported format for >memwrite. > >Reviewed-by: Liviu Dudau <liviu.dudau@arm.com> >Signed-off-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com> >--- > drivers/gpu/drm/arm/malidp_hw.c | 25 +++++++++++++++++++++++-- > drivers/gpu/drm/arm/malidp_hw.h | 6 ++++-- > drivers/gpu/drm/arm/malidp_mw.c | 12 +++++++++++- > drivers/gpu/drm/arm/malidp_regs.h | 2 ++ > 4 files changed, 40 insertions(+), 5 deletions(-) > >diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c >index c94a4422e0e9..2781e462c1ed 100644 >--- a/drivers/gpu/drm/arm/malidp_hw.c >+++ b/drivers/gpu/drm/arm/malidp_hw.c >@@ -384,7 +384,8 @@ static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev, > > static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, > dma_addr_t *addrs, s32 *pitches, >- int num_planes, u16 w, u16 h, u32 fmt_id) >+ int num_planes, u16 w, u16 h, u32 fmt_id, >+ const s16 *rgb2yuv_coeffs) > { > u32 base = MALIDP500_SE_MEMWRITE_BASE; > u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); >@@ -416,6 +417,16 @@ static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, > > malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), > MALIDP500_SE_MEMWRITE_OUT_SIZE); >+ >+ if (rgb2yuv_coeffs) { >+ int i; >+ >+ for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { >+ malidp_hw_write(hwdev, rgb2yuv_coeffs[i], >+ MALIDP500_SE_RGB_YUV_COEFFS + i * 4); >+ } >+ } >+ > malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); > > return 0; >@@ -658,7 +669,8 @@ static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev, > > static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, > dma_addr_t *addrs, s32 *pitches, >- int num_planes, u16 w, u16 h, u32 fmt_id) >+ int num_planes, u16 w, u16 h, u32 fmt_id, >+ const s16 *rgb2yuv_coeffs) > { > u32 base = MALIDP550_SE_MEMWRITE_BASE; > u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); >@@ -689,6 +701,15 @@ static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, > malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, > MALIDP550_SE_CONTROL); > >+ if (rgb2yuv_coeffs) { >+ int i; >+ >+ for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { >+ malidp_hw_write(hwdev, rgb2yuv_coeffs[i], >+ MALIDP550_SE_RGB_YUV_COEFFS + i * 4); >+ } >+ } >+ > return 0; > } > >diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h >index ad2e96915d44..d2ceb70305ca 100644 >--- a/drivers/gpu/drm/arm/malidp_hw.h >+++ b/drivers/gpu/drm/arm/malidp_hw.h >@@ -190,8 +190,10 @@ struct malidp_hw { > * @param h - height of the output frame > * @param fmt_id - internal format ID of output buffer > */ >- int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs, >- s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id); >+ int (*enable_memwrite)(struct malidp_hw_device *hwdev, >+ dma_addr_t *addrs, s32 *pitches, int num_planes, >+ u16 w, u16 h, u32 fmt_id, >+ const s16 *rgb2yuv_coeffs); > > /* > * Disable the writing to memory of the next frame's content. >diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c >index cfd718e7e97c..0523ba5d27dd 100644 >--- a/drivers/gpu/drm/arm/malidp_mw.c >+++ b/drivers/gpu/drm/arm/malidp_mw.c >@@ -213,6 +213,13 @@ int malidp_mw_connector_init(struct drm_device *drm) > return 0; > } > >+static const s16 rgb2yuv_coeffs_bt709_limited[MALIDP_COLORADJ_NUM_COEFFS] = { >+ 47, 157, 16, >+ -26, -87, 112, >+ 112, -102, -10, >+ 16, 128, 128 >+}; >+ > void malidp_mw_atomic_commit(struct drm_device *drm, > struct drm_atomic_state *old_state) > { >@@ -242,7 +249,10 @@ void malidp_mw_atomic_commit(struct drm_device *drm, > > hwdev->hw->enable_memwrite(hwdev, mw_state->addrs, > mw_state->pitches, mw_state->n_planes, >- fb->width, fb->height, mw_state->format); >+ fb->width, fb->height, >+ mw_state->format, >+ fb->format->is_yuv ? >+ rgb2yuv_coeffs_bt709_limited : NULL); Given we only have one set of coefficients, it would be nice to either program once at power-up, or to at least track in the connector state whether the coeffs are already programmed instead of programming every frame. Cheers, -Brian > } else { > DRM_DEV_DEBUG_DRIVER(drm->dev, "Disable memwrite\n"); > hwdev->hw->disable_memwrite(hwdev); >diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h >index 3579d36b2a71..6ffe849774f2 100644 >--- a/drivers/gpu/drm/arm/malidp_regs.h >+++ b/drivers/gpu/drm/arm/malidp_regs.h >@@ -205,6 +205,7 @@ > #define MALIDP500_SE_BASE 0x00c00 > #define MALIDP500_SE_CONTROL 0x00c0c > #define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c >+#define MALIDP500_SE_RGB_YUV_COEFFS 0x00C74 > #define MALIDP500_SE_MEMWRITE_BASE 0x00e00 > #define MALIDP500_DC_IRQ_BASE 0x00f00 > #define MALIDP500_CONFIG_VALID 0x00f00 >@@ -238,6 +239,7 @@ > #define MALIDP550_SE_CONTROL 0x08010 > #define MALIDP550_SE_MEMWRITE_ONESHOT (1 << 7) > #define MALIDP550_SE_MEMWRITE_OUT_SIZE 0x08030 >+#define MALIDP550_SE_RGB_YUV_COEFFS 0x08078 > #define MALIDP550_SE_MEMWRITE_BASE 0x08100 > #define MALIDP550_DC_BASE 0x0c000 > #define MALIDP550_DC_CONTROL 0x0c010 >-- >2.18.0 >
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index c94a4422e0e9..2781e462c1ed 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -384,7 +384,8 @@ static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev, static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, dma_addr_t *addrs, s32 *pitches, - int num_planes, u16 w, u16 h, u32 fmt_id) + int num_planes, u16 w, u16 h, u32 fmt_id, + const s16 *rgb2yuv_coeffs) { u32 base = MALIDP500_SE_MEMWRITE_BASE; u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); @@ -416,6 +417,16 @@ static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), MALIDP500_SE_MEMWRITE_OUT_SIZE); + + if (rgb2yuv_coeffs) { + int i; + + for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { + malidp_hw_write(hwdev, rgb2yuv_coeffs[i], + MALIDP500_SE_RGB_YUV_COEFFS + i * 4); + } + } + malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); return 0; @@ -658,7 +669,8 @@ static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev, static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, dma_addr_t *addrs, s32 *pitches, - int num_planes, u16 w, u16 h, u32 fmt_id) + int num_planes, u16 w, u16 h, u32 fmt_id, + const s16 *rgb2yuv_coeffs) { u32 base = MALIDP550_SE_MEMWRITE_BASE; u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); @@ -689,6 +701,15 @@ static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN, MALIDP550_SE_CONTROL); + if (rgb2yuv_coeffs) { + int i; + + for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) { + malidp_hw_write(hwdev, rgb2yuv_coeffs[i], + MALIDP550_SE_RGB_YUV_COEFFS + i * 4); + } + } + return 0; } diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h index ad2e96915d44..d2ceb70305ca 100644 --- a/drivers/gpu/drm/arm/malidp_hw.h +++ b/drivers/gpu/drm/arm/malidp_hw.h @@ -190,8 +190,10 @@ struct malidp_hw { * @param h - height of the output frame * @param fmt_id - internal format ID of output buffer */ - int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs, - s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id); + int (*enable_memwrite)(struct malidp_hw_device *hwdev, + dma_addr_t *addrs, s32 *pitches, int num_planes, + u16 w, u16 h, u32 fmt_id, + const s16 *rgb2yuv_coeffs); /* * Disable the writing to memory of the next frame's content. diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c index cfd718e7e97c..0523ba5d27dd 100644 --- a/drivers/gpu/drm/arm/malidp_mw.c +++ b/drivers/gpu/drm/arm/malidp_mw.c @@ -213,6 +213,13 @@ int malidp_mw_connector_init(struct drm_device *drm) return 0; } +static const s16 rgb2yuv_coeffs_bt709_limited[MALIDP_COLORADJ_NUM_COEFFS] = { + 47, 157, 16, + -26, -87, 112, + 112, -102, -10, + 16, 128, 128 +}; + void malidp_mw_atomic_commit(struct drm_device *drm, struct drm_atomic_state *old_state) { @@ -242,7 +249,10 @@ void malidp_mw_atomic_commit(struct drm_device *drm, hwdev->hw->enable_memwrite(hwdev, mw_state->addrs, mw_state->pitches, mw_state->n_planes, - fb->width, fb->height, mw_state->format); + fb->width, fb->height, + mw_state->format, + fb->format->is_yuv ? + rgb2yuv_coeffs_bt709_limited : NULL); } else { DRM_DEV_DEBUG_DRIVER(drm->dev, "Disable memwrite\n"); hwdev->hw->disable_memwrite(hwdev); diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h index 3579d36b2a71..6ffe849774f2 100644 --- a/drivers/gpu/drm/arm/malidp_regs.h +++ b/drivers/gpu/drm/arm/malidp_regs.h @@ -205,6 +205,7 @@ #define MALIDP500_SE_BASE 0x00c00 #define MALIDP500_SE_CONTROL 0x00c0c #define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c +#define MALIDP500_SE_RGB_YUV_COEFFS 0x00C74 #define MALIDP500_SE_MEMWRITE_BASE 0x00e00 #define MALIDP500_DC_IRQ_BASE 0x00f00 #define MALIDP500_CONFIG_VALID 0x00f00 @@ -238,6 +239,7 @@ #define MALIDP550_SE_CONTROL 0x08010 #define MALIDP550_SE_MEMWRITE_ONESHOT (1 << 7) #define MALIDP550_SE_MEMWRITE_OUT_SIZE 0x08030 +#define MALIDP550_SE_RGB_YUV_COEFFS 0x08078 #define MALIDP550_SE_MEMWRITE_BASE 0x08100 #define MALIDP550_DC_BASE 0x0c000 #define MALIDP550_DC_CONTROL 0x0c010