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 15 static 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 */ 25 static const u32 yuv2rgb[] = { 26 0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A, 27 0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4, 28 0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A, 29 }; 30 31 static const u32 yvu2rgb[] = { 32 0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A, 33 0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4, 34 0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A, 35 }; 36 37 static 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 64 static 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 76 void 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 86 void 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