Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add sun4i_drm CTM (Color Transformation Matrix) Support #6

Open
rsglobal opened this issue Jan 29, 2025 · 2 comments
Open

Add sun4i_drm CTM (Color Transformation Matrix) Support #6

rsglobal opened this issue Jan 29, 2025 · 2 comments

Comments

@rsglobal
Copy link
Member

TCON hardware block can be used for this purpose:

Cut from the official documentation:


7.2.7.12. TCON CEU Coefficient Mul Register (Default Value: 0x00000000)

Offset: 0x0110 + N*0x04 (N=0,1,2,4,5,6,8,9,10)

Bit R/W Default/Hex Description
31:13 / / Reserved
12:0 R/W 0 CEU_Coef_Mul_Value: Signed 13-bit value (range: -16 to 16).
N Mapping:
N=0: Rr, N=1: Rg, N=2: Rb,
N=4: Gr, N=5: Gg, N=6: Gb,
N=8: Br, N=9: Bg, N=10: Bb

7.2.7.13. TCON CEU Coefficient Add Register (Default Value: 0x00000000)

Offset: 0x011C + N*0x10 (N=0,1,2)
Register Name: TCON_CEU_COEF_ADD_REG

Bit R/W Default/Hex Description
31:19 / / Reserved
18:0 R/W 0 CEU_Coef_Add_Value: Signed 19-bit value (range: -16384 to 16384).
N Mapping:
N=0: Rc, N=1: Gc, N=2: Bc

7.2.7.14. TCON CEU Coefficient Rang Register (Default Value: 0x00000000)

Offset: 0x0140 + N*0x04 (N=0,1,2)
Register Name: TCON_CEU_COEF_RANG_REG

Bit R/W Default/Hex Description
31:24 / / Reserved
23:16 R/W 0 CEU_Coef_Range_Min: Unsigned 8-bit value (range: 0 to 255)
15:8 / / Reserved
7:0 R/W 0 CEU_Coef_Range_Max: Unsigned 8-bit value (range: 0 to 255)
@rsglobal
Copy link
Member Author

Here's the python script that can help to check if that works:

def generate_devmem_commands(mul_coefficients, add_coefficients, range_parameters):
    """
    Generates devmem commands to set the TCON CEU color matrix coefficients and ranges.

    Parameters:
    - mul_coefficients: List of 9 signed integers (range -16 to 16) in the order:
      [Rr, Rg, Rb, Gr, Gg, Gb, Br, Bg, Bb]
    - add_coefficients: List of 3 signed integers (range -16384 to 16384) in the order:
      [Rc, Gc, Bc]
    - range_parameters: List of 3 tuples (min, max) with each value 0-255 in the order:
      [(R_min, R_max), (G_min, G_max), (B_min, B_max)]

    Returns:
    - List of devmem command strings
    """
    commands = []
    tcon_base = 0x01C0C000  # Base address of TCON0

    # Process Mul Coefficients (TCON_CEU_COEF_MUL_REG)
    n_mul = [0, 1, 2, 4, 5, 6, 8, 9, 10]  # N values for each mul_coefficient
    for idx, coeff in enumerate(mul_coefficients):
        n = n_mul[idx]
        offset = 0x0110 + n * 0x04
        addr = tcon_base + offset
        # Scale coefficient to 13-bit fixed-point (8 fractional bits)
        scaled = int(round(coeff * 256))  # Multiply by 2^8 for 8 fractional bits
        # Clamp to valid range (-4096 to 4095) for 13-bit signed
        scaled = max(-4096, min(scaled, 4095))
        # Convert to 13-bit two's complement (mask 0x1FFF handles sign automatically)
        value = scaled & 0x1FFF  # Ensure it fits in 13 bits

        commands.append(f"devmem 0x{addr:08X} 32 0x{value:08X}")

    # Process Add Coefficients (TCON_CEU_COEF_ADD_REG)
    for n in range(3):
        coeff = add_coefficients[n]
        offset = 0x011C + n * 0x10
        addr = tcon_base + offset
        # Clamp to 19-bit signed range (-262144 to 262143)
        clamped = max(-262144, min(coeff, 262143))
        # Convert to two's complement (mask 0x7FFFF handles sign)
        value = clamped & 0x7FFFF  # 19 bits
        commands.append(f"devmem 0x{addr:08X} 32 0x{value:08X}")

    # Process Range Parameters (TCON_CEU_COEF_RANG_REG)
    for n in range(3):
        min_val, max_val = range_parameters[n]
        offset = 0x0140 + n * 0x04
        addr = tcon_base + offset
        # Pack min (bits 23:16) and max (bits 7:0)
        value = ((min_val & 0xFF) << 16) | (max_val & 0xFF)
        commands.append(f"devmem 0x{addr:08X} 32 0x{value:08X}")

    return commands


# Example coefficients
mul_coeffs = [
    0, 0, 1,   # Rr, Rg, Rb
    0, 1, 0,   # Gr, Gg, Gb
    1, 0, 0    # Br, Bg, Bb
]
add_coeffs = [0, 0, 0]  # Rc, Gc, Bc
range_params = [(0, 255), (0, 255), (0, 255)]  # Clamp to 0-255 for R, G, B

commands = generate_devmem_commands(mul_coeffs, add_coeffs, range_params)
for cmd in commands:
    print(cmd)

@rsglobal
Copy link
Member Author

rsglobal commented Jan 29, 2025

Here's the output:

devmem 0x01C0C110 32 0x00000000
devmem 0x01C0C114 32 0x00000000
devmem 0x01C0C118 32 0x00000100
devmem 0x01C0C120 32 0x00000000
devmem 0x01C0C124 32 0x00000100
devmem 0x01C0C128 32 0x00000000
devmem 0x01C0C130 32 0x00000100
devmem 0x01C0C134 32 0x00000000
devmem 0x01C0C138 32 0x00000000
devmem 0x01C0C11C 32 0x00000000
devmem 0x01C0C12C 32 0x00000000
devmem 0x01C0C13C 32 0x00000000
devmem 0x01C0C140 32 0x000000FF
devmem 0x01C0C144 32 0x000000FF
devmem 0x01C0C148 32 0x000000FF

And don't forget to turn on the CEU unit:

devmem 0x01C0C110 32 0x00000100

After running commands, we can see R and B colors swapped by the TCON hardware.

So, now we need to embed it into the kernel DRM driver.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant