In this doc will show how to adjust display brightness/contrast/saturation by using i.MX8 Display Controller (DC) Subsystem.
HW: i.MX8QXP MEK board
SW: Linux 4.14.98_2.0.0 BSP release.
See i.MX 8DualXPlus/8QuadXPlus Applications Processor Reference Manual, Rev. D:
This kind Matrix total number is 5 , that is 0/1/4/5/9.
In this doc using Matrix0 to adjust whole display brightness/contrast/saturation.
Matrix0 unit position is located between FramGen unit and Tcon unit, that means using Matrix0 will impact on the whole display contents.
Note, this Matrix is applied on RGB color space.
The Matrix is consist of two parts:
You can program any value into register of A11 to A44 and C1 to C4, Matrix will applied on input RGB data, then output RGB data will changed as you want. In this way, we can change the display brightness/contrast/saturation.
The Matrix entry from A11 to A44, their register format is same as below:
Each register entry of A11 to A44 , total 13 bit, bit 12 is symbol bit , bit 11 and bit 10 is integer bit, bit 9 to bit 0 is floating point bit.
The Matrix entry from C1 to C4, their format is same as below:
Each register entry of C1 to C4, total 13 bit, bit 12 is symbol bit, others are integer bit.
Now let us choose the matrix that will be used for adjust brightness/contrast/saturation.
See this link https://docs.rainmeter.net/tips/colormatrix-guide/
So we can set matrix as below to change brightness/contrast/saturation
A11=c(sr+s) A12=c(sg) A13=c(sb)
A21=c(sb) A22=c(sg+s) A23=c(sb)
A31=c(sr) A32=c(sg) A33=c(sb+s)
b as brightness , range[-1.0, 1.0], zero means no change , >0 will increases brightness, <0 will reduce brightness.
c as contrast, range [0,2.0) , default is 1.0 , >1.0 is increase , <1.0 is reduce.
s is saturation, range [0,1.0], default is 1.0.
Other matrix entry is related to alpha, in this doc not change it, just keep them as zero.
Note here sr,sb,sg value will depend on lumR/ lumG/ lumB constant value you choose, this value may depend on different color standard.
Due to each matrix value is floating point number, and in this doc , i.MX8X run Linux OS.
So you can choose do floating point operation in user space program, then pass related register value into kernel space , let driver write them into register. But in this doc, to make Linux kernel driver more simple, I will convert floating point operation into integer operation , then user space app just pass brightness/contrast/saturation value into kernel space, then kernel driver to do left operation in kernel space.
So 1024*c and 1024*s is integer number that user space app will passed into kernel space.
And in kernel space could be do left integer number operation, then write register value.
The kernel patch 8qxp_4.14.98_brightness_contrast_saturation.diff could be used on 4.14.98_2.0.0 BSP release.
Test usage, need used one patch that for proptest which from libdrm test case, see 8qxp_prop_test.diff, recompile the proptest case.
root@imx8qxpmek:~# ./proptest //list current drm property
values: 0 131071
values: 0 2048
values: 0 1024
values: 0 1
I add four drm property , brightness, contrast, saturation, update. The “update property” should be set as 1 at last, otherwise kernel space will not update related property. Reference API usage ( in 8qxp_prop_test.diff)
+ drmModeObjectSetProperty(fd_rend, obj_id, obj_type, 42, b_int);
+ drmModeObjectSetProperty(fd_rend, obj_id, obj_type, 43, c_int);
+ drmModeObjectSetProperty(fd_rend, obj_id, obj_type, 44, s_int);
+ drmModeObjectSetProperty(fd_rend, obj_id, obj_type, 45, 1);
//run cmd as below , will ask you input related brightness/contrast/saturation value , then will get result in display
root@imx8qxpmek:~# ./proptest 32 crtc 45 1
input brightness [-1,1]
input contrast, >1.0 or <1.0
input saturation, [0,1]
brightness 0.300000 0x133 from [-1,1] percent
contrast 1.200000 0x4cc >1.0 or <1.0
saturation 0.300000 0x133 from 0.0 to 1.0
For demo this feature , I need run proptest and weston at same time. Due to the set property drm ioctl default allowed by DRM master and DRM control client. But 4.14. kernel, removed the DRM control device node, so I changed to open drm render node fd, and allow DRM render client to using set property drm ioctl. This is just a workaround, you may not use it.