IMX8MP LVDS LCD contrast and colour saturation control

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

IMX8MP LVDS LCD contrast and colour saturation control

2,540 Views
TerryBarnaby1
Contributor V

We have a custom board using the IMX8MP SOC which has an LVDS LCD display and a HDMI display connected.

We wish to be able to control the contrast and colour saturation on the LCD display. Is this possible somehow, ideally through Wayland/Weston or Linux drivers but if not using direct hardware registers ?

We note the LCDIF driver has colour space conversion matrix registers but it looks like these cannot be used for RGB -> RGB changes which I presume would be needed in a default IMX8MP Linux with Wayland/Weston setup.

0 Kudos
Reply
13 Replies

1,575 Views
tsmt
Contributor II

May somewhat interesting for others. The Color Space Conversion can be somewhat missused to do RGB -> RGB. I barely spent any time on it, but the following coefficients

CSC0_CTRL = 0

A1=0x100, A2=0, A3=0, B1=0, B2=0x100, B3=0, C1=0, C2=0, C3=0x100, D1=0, D2=0x100, D3=0x100

seem to lead to the same output as

CSC0_CTRL = 1 (the bypass mode)

Unfortunately NXP does not fully document what the conversion are doing. But with adjusting this coefficients, I at least I was able to do a slight color correction for a display we use. Is this an ugly hack, yes absolutely, did it solve my problem, yes.

 

#!/usr/bin/env python3

import mmap
import struct

def write_word(address, value):
    with open('/dev/mem', 'r+b') as f:
        mem = mmap.mmap(f.fileno(), mmap.PAGESIZE, mmap.MAP_SHARED, mmap.PROT_READ | mmap.PROT_WRITE, offset=address & ~(mmap.PAGESIZE - 1))
        struct.pack_into('I', mem, address & (mmap.PAGESIZE - 1), value)
        mem.close()

def write_coeffs(a1, a2, a3, b1, b2, b3, c1, c2, c3, d1, d2, d3):
# LCDIF2 = 0x32E90000
 # A1-C3 11-bits, D1-D3 10 bits
   
def w(x, y):
        return ((x & 0x3FF) << 16) | ((y & 0x3FF) << 0)
    write_word(0x32E9021C, 0)  # CSC0_CTRL
    write_word(0x32E90220, w(a2, a1))  # CSC0_COEF0 - A2 A1
    write_word(0x32E90224, w(b1, a3))  # CSC0_COEF1 - B1 A3
    write_word(0x32E90228, w(b3, b2))  # CSC0_COEF2 - B3 B2
    write_word(0x32E9022C, w(c2, c1))  # CSC0_COEF3 - C2 C1
    write_word(0x32E90230, w(d1, c3))  # CSC0_COEF4 - D1 C3
    write_word(0x32E90234, w(d3, d2))  # CSC0_COEF5 - D3 D2

write_coeffs(0x100, 0, 0, 0, 0x100, 0, 0, 0, 0x100, 0x000, 0x100, 0x100)  # "somewhat" close to identity
write_coeffs(0x0B0, 0, 0, 0, 0x100, 0, 0, 0, 0x100, 0x000, 0x100, 0x100)  # less red

1,541 Views
malik_cisse
Senior Contributor I

This might be a stupid question.
Your python script is referring to CSC0_CTRL register 0x32E9021C whereas in the imx8mp reference manual, the address is 0x32FC621C as can be seen in picture below . An idea where the difference comes from

write_word(0x32E9021C, 0)  # CSC0_CTRL

malik_cisse_0-1715702880733.png

 

 

0 Kudos
Reply

1,520 Views
tsmt
Contributor II

The baseaddress for LCDIF2 is 0x32E90000, the base address for LCDIF3 is 0x32FC600. Could have done this better in the script to allow it for all 3 LCDIF. The display I have tough, is connected via LCDIF2.

0 Kudos
Reply

1,503 Views
malik_cisse
Senior Contributor I

you are the man @tsmt 
This was rather stupid question from me.
I can now reproduce your result on my display too which sits on LCDIF1.
The colors are not yet quite the same as original, but I will play with the coefficient and try to achieve 1-to-1 RGB2RGB conversion.

1,568 Views
TerryBarnaby1
Contributor V

Ah, that looks interesting and looking at the datasheet might do what I need with:

A1, B2, C3 = RGB gains (0x100 being 1x) so change these equally for contrast.

D1, D2, D3 = RGB offsets so change these equally for brightness.

This assumes the calculated YUV values clip to 255 and 0.

Any reason why you set D2=0x100, D3=0x100 that looks like -256 whatever that would do ?

If I get time I will try that out.

0 Kudos
Reply

1,565 Views
tsmt
Contributor II

A1 through C3 seemed somewhat obvious, just creating an identity matrix. Why D2 and D3 are these numbers I don't understand (yet), but I just found out testing it with a white image and adjusting the coefficients until I saw a nice blue, red, green and finally white again.

I assume that this conversion modes quite likely do some additional underlining calculation. Else the control registers would need IMHO 1 bit less. But this is all a wild guess. I also read a little bit through the Linux kernel code, and the comments also lead to the conclusion that not everything is fully understood.

And yes the values seem to be clipped (I think I read this somewhere, but it may also have been on an iMX6 post).

By the way, for a quick hack, it's easiest to just write this values through /dev/mem

0 Kudos
Reply

1,555 Views
malik_cisse
Senior Contributor I

@tsmt 
>>By the way, for a quick hack, it's easiest to just write this values through /dev/mem
would you share your config script?
I would like to quickly reproduce the RGB2RGB just to check.
otherwise I will read the register addresses from the manual but I am too lazy
Thx

0 Kudos
Reply

1,562 Views
TerryBarnaby1
Contributor V

Have you tried setting CSC_MODE to 0x04 so CSC_MODE 2,RGB2YUV or even CSC_MODE to 0x06 so CSC_MODE 3, RGB2YCbCr ?

The RGB2YUV "seems" most useful.

0 Kudos
Reply

2,402 Views
malik_cisse
Senior Contributor I

Hi Terry,

Could you solve this problem?
I have exact same issue.

GPU cannot solve this because AFAIK Color gain cannot be set using e.g G2D API.
Thank you,

0 Kudos
Reply

2,382 Views
TerryBarnaby1
Contributor V

Unfortunately no, its a shame NXP did not provide this ability with the colour conversion matrix as used for YUV -> RGB could not be used for RGB -> RGB.

In my case we had a TP2856 analogue TV to CSI chip that had this ability. Although this only affect the video, this was good enough for our usage.

2,523 Views
TerryBarnaby1
Contributor V

Thanks for the info.

When you say "lcdif only has normal colour space conversion matrix" is this matrix programmable or are you saying there really is no matrix (ie: 1:1 RGB to RGB with no changes ?)

If so its a shame the colour conversion matrix as used for YUV -> RGB could not be used for RGB -> RGB.

0 Kudos
Reply

2,513 Views
joanxie
NXP TechSupport
NXP TechSupport

I mean only support YUV to RGB or RGB to YUV color space convertion

0 Kudos
Reply

2,528 Views
joanxie
NXP TechSupport
NXP TechSupport

yes, lcdif only has normal colour space conversion matrix, maybe customer needs to use GPU to do this job, but we don't have such demo on imx8mp, imx8x display controller has this feature

0 Kudos
Reply