linux/drivers/gpu/drm/sun4i/sun8i_csc.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net>
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License as
   6 * published by the Free Software Foundation; either version 2 of
   7 * the License, or (at your option) any later version.
   8 */
   9
  10#include <drm/drmP.h>
  11
  12#include "sun8i_csc.h"
  13#include "sun8i_mixer.h"
  14
  15static const u32 ccsc_base[2][2] = {
  16        {CCSC00_OFFSET, CCSC01_OFFSET},
  17        {CCSC10_OFFSET, CCSC11_OFFSET},
  18};
  19
  20/*
  21 * Factors are in two's complement format, 10 bits for fractinal part.
  22 * First tree values in each line are multiplication factor and last
  23 * value is constant, which is added at the end.
  24 */
  25static const u32 yuv2rgb[] = {
  26        0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A,
  27        0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4,
  28        0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A,
  29};
  30
  31static const u32 yvu2rgb[] = {
  32        0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A,
  33        0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4,
  34        0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A,
  35};
  36
  37static void sun8i_csc_set_coefficients(struct regmap *map, u32 base,
  38                                       enum sun8i_csc_mode mode)
  39{
  40        const u32 *table;
  41        int i, data;
  42
  43        switch (mode) {
  44        case SUN8I_CSC_MODE_YUV2RGB:
  45                table = yuv2rgb;
  46                break;
  47        case SUN8I_CSC_MODE_YVU2RGB:
  48                table = yvu2rgb;
  49                break;
  50        default:
  51                DRM_WARN("Wrong CSC mode specified.\n");
  52                return;
  53        }
  54
  55        for (i = 0; i < 12; i++) {
  56                data = table[i];
  57                /* For some reason, 0x200 must be added to constant parts */
  58                if (((i + 1) & 3) == 0)
  59                        data += 0x200;
  60                regmap_write(map, SUN8I_CSC_COEFF(base, i), data);
  61        }
  62}
  63
  64static void sun8i_csc_enable(struct regmap *map, u32 base, bool enable)
  65{
  66        u32 val;
  67
  68        if (enable)
  69                val = SUN8I_CSC_CTRL_EN;
  70        else
  71                val = 0;
  72
  73        regmap_update_bits(map, SUN8I_CSC_CTRL(base), SUN8I_CSC_CTRL_EN, val);
  74}
  75
  76void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer,
  77                                     enum sun8i_csc_mode mode)
  78{
  79        u32 base;
  80
  81        base = ccsc_base[mixer->cfg->ccsc][layer];
  82
  83        sun8i_csc_set_coefficients(mixer->engine.regs, base, mode);
  84}
  85
  86void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable)
  87{
  88        u32 base;
  89
  90        base = ccsc_base[mixer->cfg->ccsc][layer];
  91
  92        sun8i_csc_enable(mixer->engine.regs, base, enable);
  93}
  94