1068 lines
40 KiB
C
Executable File
1068 lines
40 KiB
C
Executable File
/*
|
|
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
|
* http://www.samsung.com
|
|
*
|
|
* Register interface file for Exynos Scaler driver
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include "scaler.h"
|
|
#include "scaler-regs.h"
|
|
|
|
#define COEF(val_l, val_h) ((((val_h) & 0x7FF) << 16) | ((val_l) & 0x7FF))
|
|
extern int sc_set_blur;
|
|
|
|
/* Scaling coefficient value for 10bit supporting */
|
|
static const __u32 sc_coef_8t_org[7][16][4] = {
|
|
{ /* 8:8 or Zoom-in */
|
|
{COEF( 0, 0), COEF( 0, 0), COEF(512, 0), COEF( 0, 0)},
|
|
{COEF(-1, 2), COEF( -9, 30), COEF(509, -25), COEF( 8, -2)},
|
|
{COEF(-1, 5), COEF(-19, 64), COEF(499, -46), COEF( 14, -4)},
|
|
{COEF(-2, 8), COEF(-30, 101), COEF(482, -62), COEF( 20, -5)},
|
|
{COEF(-3, 12), COEF(-41, 142), COEF(458, -73), COEF( 23, -6)},
|
|
{COEF(-3, 15), COEF(-53, 185), COEF(429, -80), COEF( 25, -6)},
|
|
{COEF(-4, 19), COEF(-63, 228), COEF(395, -83), COEF( 26, -6)},
|
|
{COEF(-5, 21), COEF(-71, 273), COEF(357, -82), COEF( 25, -6)},
|
|
{COEF(-5, 23), COEF(-78, 316), COEF(316, -78), COEF( 23, -5)},
|
|
}, { /* 8:7 Zoom-out */
|
|
{COEF( 0, 12), COEF(-32, 52), COEF(444, 56), COEF(-32, 12)},
|
|
{COEF(-3, 13), COEF(-39, 82), COEF(445, 29), COEF(-24, 9)},
|
|
{COEF(-3, 14), COEF(-46, 112), COEF(438, 6), COEF(-16, 7)},
|
|
{COEF(-3, 15), COEF(-52, 144), COEF(426, -14), COEF( -9, 5)},
|
|
{COEF(-3, 16), COEF(-58, 177), COEF(410, -30), COEF( -3, 3)},
|
|
{COEF(-3, 16), COEF(-63, 211), COEF(390, -43), COEF( 2, 2)},
|
|
{COEF(-2, 16), COEF(-66, 244), COEF(365, -53), COEF( 7, 1)},
|
|
{COEF(-2, 15), COEF(-66, 277), COEF(338, -60), COEF( 10, 0)},
|
|
{COEF(-1, 13), COEF(-65, 309), COEF(309, -65), COEF( 13, -1)},
|
|
}, { /* 8:6 or Zoom-in */
|
|
{COEF( 0, 8), COEF(-44, 100), COEF(384, 100), COEF(-44, 8)},
|
|
{COEF( 0, 8), COEF(-47, 123), COEF(382, 77), COEF(-40, 9)},
|
|
{COEF( 1, 7), COEF(-49, 147), COEF(377, 57), COEF(-36, 8)},
|
|
{COEF( 2, 5), COEF(-49, 171), COEF(369, 38), COEF(-32, 8)},
|
|
{COEF( 2, 3), COEF(-48, 196), COEF(358, 20), COEF(-27, 8)},
|
|
{COEF( 3, 1), COEF(-47, 221), COEF(344, 5), COEF(-22, 7)},
|
|
{COEF( 3, -2), COEF(-43, 245), COEF(329, -9), COEF(-18, 7)},
|
|
{COEF( 4, -5), COEF(-37, 268), COEF(310, -20), COEF(-13, 5)},
|
|
{COEF( 5, -9), COEF(-30, 290), COEF(290, -30), COEF( -9, 5)},
|
|
}, { /* 8:5 Zoom-out */
|
|
{COEF( 0, -3), COEF(-31, 130), COEF(320, 130), COEF(-31, -3)},
|
|
{COEF( 3, -6), COEF(-29, 147), COEF(319, 113), COEF(-32, -3)},
|
|
{COEF( 3, -8), COEF(-26, 165), COEF(315, 97), COEF(-33, -1)},
|
|
{COEF( 3, -11), COEF(-22, 182), COEF(311, 81), COEF(-32, 0)},
|
|
{COEF( 3, -13), COEF(-17, 199), COEF(304, 66), COEF(-31, 1)},
|
|
{COEF( 3, -16), COEF(-11, 216), COEF(296, 52), COEF(-30, 2)},
|
|
{COEF( 3, -18), COEF( -3, 232), COEF(286, 38), COEF(-28, 2)},
|
|
{COEF( 3, -21), COEF( 5, 247), COEF(274, 26), COEF(-25, 3)},
|
|
{COEF( 3, -23), COEF( 15, 261), COEF(261, 15), COEF(-23, 3)},
|
|
}, { /* 8:4 Zoom-out */
|
|
{COEF( 0, -12), COEF( 0, 140), COEF(255, 140), COEF( 0, -11)},
|
|
{COEF( 0, -13), COEF( 5, 151), COEF(254, 129), COEF( -4, -10)},
|
|
{COEF(-1, -14), COEF( 10, 163), COEF(253, 117), COEF( -7, -9)},
|
|
{COEF(-1, -15), COEF( 16, 174), COEF(250, 106), COEF(-10, -8)},
|
|
{COEF(-1, -16), COEF( 22, 185), COEF(246, 95), COEF(-12, -7)},
|
|
{COEF(-2, -16), COEF( 29, 195), COEF(241, 85), COEF(-14, -6)},
|
|
{COEF(-2, -17), COEF( 37, 204), COEF(236, 74), COEF(-15, -5)},
|
|
{COEF(-3, -17), COEF( 46, 214), COEF(229, 64), COEF(-16, -5)},
|
|
{COEF(-4, -17), COEF( 55, 222), COEF(222, 55), COEF(-17, -4)},
|
|
}, { /* 8:3 or Zoom-in */
|
|
{COEF( 0, -6), COEF( 31, 133), COEF(195, 133), COEF( 31, -5)},
|
|
{COEF(-3, -4), COEF( 37, 139), COEF(195, 126), COEF( 27, -5)},
|
|
{COEF(-3, -3), COEF( 41, 146), COEF(194, 119), COEF( 23, -5)},
|
|
{COEF(-4, -2), COEF( 47, 152), COEF(193, 112), COEF( 19, -5)},
|
|
{COEF(-4, -2), COEF( 53, 158), COEF(191, 105), COEF( 16, -5)},
|
|
{COEF(-4, 0), COEF( 59, 163), COEF(189, 98), COEF( 12, -5)},
|
|
{COEF(-4, 1), COEF( 65, 169), COEF(185, 91), COEF( 10, -5)},
|
|
{COEF(-4, 3), COEF( 71, 174), COEF(182, 84), COEF( 7, -5)},
|
|
{COEF(-5, 5), COEF( 78, 178), COEF(178, 78), COEF( 5, -5)},
|
|
}, { /* 8:2 Zoom-out */
|
|
{COEF( 0, 10), COEF( 52, 118), COEF(152, 118), COEF( 52, 10)},
|
|
{COEF( 0, 11), COEF( 56, 122), COEF(152, 114), COEF( 48, 9)},
|
|
{COEF( 1, 13), COEF( 60, 125), COEF(151, 110), COEF( 45, 7)},
|
|
{COEF( 1, 15), COEF( 64, 129), COEF(150, 106), COEF( 41, 6)},
|
|
{COEF( 1, 17), COEF( 68, 132), COEF(149, 102), COEF( 38, 5)},
|
|
{COEF( 1, 19), COEF( 72, 135), COEF(148, 98), COEF( 35, 4)},
|
|
{COEF( 1, 21), COEF( 77, 138), COEF(146, 94), COEF( 31, 4)},
|
|
{COEF( 2, 23), COEF( 81, 140), COEF(145, 89), COEF( 29, 3)},
|
|
{COEF( 2, 26), COEF( 85, 143), COEF(143, 85), COEF( 26, 2)},
|
|
}
|
|
};
|
|
|
|
static const __u32 sc_coef_4t_org[7][16][2] = {
|
|
{ /* 8:8 or Zoom-in */
|
|
{COEF( 0, 0), COEF(512, 0)},
|
|
{COEF( -1, 20), COEF(508, -15)},
|
|
{COEF( -3, 45), COEF(495, -25)},
|
|
{COEF( -5, 75), COEF(473, -31)},
|
|
{COEF( -8, 110), COEF(443, -33)},
|
|
{COEF(-11, 148), COEF(408, -33)},
|
|
{COEF(-14, 190), COEF(367, -31)},
|
|
{COEF(-19, 234), COEF(324, -27)},
|
|
{COEF(-23, 279), COEF(279, -23)},
|
|
}, { /* 8:7 Zoom-out */
|
|
{COEF( 0, 32), COEF(448, 32)},
|
|
{COEF( -6, 55), COEF(446, 17)},
|
|
{COEF( -7, 79), COEF(437, 3)},
|
|
{COEF( -9, 107), COEF(421, -7)},
|
|
{COEF(-11, 138), COEF(399, -14)},
|
|
{COEF(-13, 170), COEF(373, -18)},
|
|
{COEF(-15, 204), COEF(343, -20)},
|
|
{COEF(-18, 240), COEF(310, -20)},
|
|
{COEF(-19, 275), COEF(275, -19)},
|
|
}, { /* 8:6 Zoom-out */
|
|
{COEF( 0, 61), COEF(390, 61)},
|
|
{COEF( -7, 83), COEF(390, 46)},
|
|
{COEF( -8, 106), COEF(383, 31)},
|
|
{COEF( -8, 130), COEF(371, 19)},
|
|
{COEF( -9, 156), COEF(356, 9)},
|
|
{COEF(-10, 183), COEF(337, 2)},
|
|
{COEF(-10, 210), COEF(315, -3)},
|
|
{COEF(-10, 238), COEF(291, -7)},
|
|
{COEF( -9, 265), COEF(265, -9)},
|
|
}, { /* 8:5 Zoom-out */
|
|
{COEF( 0, 86), COEF(341, 85)},
|
|
{COEF( -5, 105), COEF(341, 71)},
|
|
{COEF( -4, 124), COEF(336, 56)},
|
|
{COEF( -4, 145), COEF(328, 43)},
|
|
{COEF( -3, 166), COEF(317, 32)},
|
|
{COEF( -2, 187), COEF(304, 23)},
|
|
{COEF( -1, 209), COEF(288, 16)},
|
|
{COEF( 1, 231), COEF(271, 9)},
|
|
{COEF( 5, 251), COEF(251, 5)},
|
|
}, { /* 8:4 Zoom-out */
|
|
{COEF( 0, 104), COEF(304, 104)},
|
|
{COEF( 1, 120), COEF(302, 89)},
|
|
{COEF( 2, 136), COEF(298, 76)},
|
|
{COEF( 3, 153), COEF(293, 63)},
|
|
{COEF( 5, 170), COEF(285, 52)},
|
|
{COEF( 7, 188), COEF(275, 42)},
|
|
{COEF( 10, 205), COEF(264, 33)},
|
|
{COEF( 14, 221), COEF(251, 26)},
|
|
{COEF( 20, 236), COEF(236, 20)},
|
|
}, { /* 8:3 Zoom-out */
|
|
{COEF( 0, 118), COEF(276, 118)},
|
|
{COEF( 7, 129), COEF(273, 103)},
|
|
{COEF( 9, 143), COEF(270, 90)},
|
|
{COEF( 11, 157), COEF(266, 78)},
|
|
{COEF( 14, 171), COEF(260, 67)},
|
|
{COEF( 17, 185), COEF(253, 57)},
|
|
{COEF( 21, 199), COEF(244, 48)},
|
|
{COEF( 27, 211), COEF(234, 40)},
|
|
{COEF( 33, 223), COEF(223, 33)},
|
|
}, { /* 8:2 Zoom-out */
|
|
{COEF( 0, 127), COEF(258, 127)},
|
|
{COEF( 14, 135), COEF(252, 111)},
|
|
{COEF( 15, 147), COEF(250, 100)},
|
|
{COEF( 18, 159), COEF(247, 88)},
|
|
{COEF( 21, 171), COEF(242, 78)},
|
|
{COEF( 25, 182), COEF(237, 68)},
|
|
{COEF( 30, 193), COEF(230, 59)},
|
|
{COEF( 36, 204), COEF(222, 50)},
|
|
{COEF( 43, 213), COEF(213, 43)},
|
|
},
|
|
};
|
|
|
|
static const __u32 sc_coef_8t_blur1[7][16][4] = {
|
|
{ /* 8:8 or zoom-in */
|
|
{COEF( 0, -12), COEF( 0, 140), COEF(256, 140), COEF( 0,-12)},
|
|
{COEF( 0, -12), COEF( 4, 152), COEF(256, 124), COEF( -4, -8)},
|
|
{COEF( 0, -12), COEF( 8, 164), COEF(252, 116), COEF( -8, -8)},
|
|
{COEF( 0, -16), COEF( 16, 176), COEF(248, 104), COEF( -8, -8)},
|
|
{COEF( 0, -16), COEF( 32, 184), COEF(248, 92), COEF(-12, -8)},
|
|
{COEF( 0, -16), COEF( 28, 196), COEF(240, 80), COEF(-12, -4)},
|
|
{COEF(-4, -16), COEF( 36, 208), COEF(236, 72), COEF(-16, -4)},
|
|
{COEF(-4, -16), COEF( 48, 212), COEF(228, 64), COEF(-16, -4)},
|
|
{COEF(-4, -16), COEF( 56, 224), COEF(220, 52), COEF(-16, -4)},
|
|
{COEF(-4, -16), COEF( 48, 212), COEF(228, 64), COEF(-16, -4)},
|
|
{COEF(-4, -16), COEF( 36, 208), COEF(236, 72), COEF(-16, -4)},
|
|
{COEF( 0, -16), COEF( 28, 196), COEF(240, 80), COEF(-12, -4)},
|
|
{COEF( 0, -16), COEF( 24, 184), COEF(248, 92), COEF(-12, -8)},
|
|
{COEF( 0, -16), COEF( 16, 176), COEF(248, 104), COEF( -8, -8)},
|
|
{COEF( 0, -12), COEF( 8, 164), COEF(252, 116), COEF( -8, -8)},
|
|
{COEF( 0, -12), COEF( 4, 152), COEF(256, 124), COEF( -4, -8)}
|
|
}, { /* 8:7 Zoom-out */
|
|
{COEF(-4, -8), COEF( 16, 140), COEF(224, 136), COEF( 16, -8)},
|
|
{COEF(-4, -12), COEF( 24, 148), COEF(224, 128), COEF( 12, -8)},
|
|
{COEF(-4, -12), COEF( 28, 156), COEF(224, 120), COEF( 8, -8)},
|
|
{COEF(-4, -12), COEF( 32, 164), COEF(220, 112), COEF( 4, -8)},
|
|
{COEF(-4, -12), COEF( 40, 172), COEF(216, 104), COEF( 0, -8)},
|
|
{COEF(-4, -8), COEF( 48, 176), COEF(212, 92), COEF( 0, -8)},
|
|
{COEF(-4, -8), COEF( 56, 188), COEF(208, 84), COEF( -4, -8)},
|
|
{COEF(-4, -8), COEF( 60, 192), COEF(204, 76), COEF( -4, -4)},
|
|
{COEF(-4, -8), COEF( 68, 200), COEF(200, 68), COEF( -8, -4)},
|
|
{COEF(-4, -8), COEF( 60, 192), COEF(204, 76), COEF( -4, -4)},
|
|
{COEF(-4, -8), COEF( 56, 188), COEF(208, 84), COEF( -4, -8)},
|
|
{COEF(-4, -8), COEF( 48, 180), COEF(212, 92), COEF( 0, -8)},
|
|
{COEF(-4, -12), COEF( 40, 176), COEF(216, 104), COEF( 0, -8)},
|
|
{COEF(-4, -12), COEF( 32, 168), COEF(220, 112), COEF( 4, -8)},
|
|
{COEF(-4, -12), COEF( 28, 156), COEF(224, 120), COEF( 8, -8)},
|
|
{COEF(-4, -12), COEF( 24, 148), COEF(224, 128), COEF( 12, -8)}
|
|
}, { /* 8:6 Zoom-out */
|
|
{COEF( 0, -4), COEF( 32, 132), COEF(196, 128), COEF( 32, -4)},
|
|
{COEF(-4, -4), COEF( 36, 140), COEF(196, 124), COEF( 28, -4)},
|
|
{COEF(-4, -4), COEF( 44, 144), COEF(196, 116), COEF( 24, -4)},
|
|
{COEF(-4, -4), COEF( 48, 152), COEF(192, 112), COEF( 20, -4)},
|
|
{COEF(-4, 0), COEF( 48, 160), COEF(192, 104), COEF( 16, -4)},
|
|
{COEF(-4, 0), COEF( 60, 164), COEF(188, 96), COEF( 12, -4)},
|
|
{COEF(-4, 0), COEF( 68, 168), COEF(184, 88), COEF( 12, -4)},
|
|
{COEF(-4, 4), COEF( 72, 172), COEF(180, 84), COEF( 8, -4)},
|
|
{COEF(-4, 4), COEF( 80, 180), COEF(176, 76), COEF( 4, -4)},
|
|
{COEF(-4, 4), COEF( 72, 172), COEF(180, 84), COEF( 8, -4)},
|
|
{COEF(-4, 0), COEF( 68, 168), COEF(184, 88), COEF( 12, -4)},
|
|
{COEF(-4, 0), COEF( 60, 164), COEF(188, 96), COEF( 12, -4)},
|
|
{COEF(-4, 0), COEF( 48, 160), COEF(192, 104), COEF( 16, -4)},
|
|
{COEF(-4, -4), COEF( 48, 152), COEF(192, 112), COEF( 20, -4)},
|
|
{COEF(-4, -4), COEF( 44, 144), COEF(196, 116), COEF( 24, -4)},
|
|
{COEF(-4, -4), COEF( 36, 140), COEF(196, 124), COEF( 28, -4)}
|
|
}, { /* 8:5 Zoom-out */
|
|
{COEF( 0, 4), COEF( 44, 128), COEF(168, 120), COEF( 44, 4)},
|
|
{COEF(-4, 4), COEF( 48, 132), COEF(172, 120), COEF( 40, 0)},
|
|
{COEF(-4, 4), COEF( 52, 136), COEF(172, 116), COEF( 36, 0)},
|
|
{COEF(-4, 8), COEF( 56, 140), COEF(172, 108), COEF( 32, 0)},
|
|
{COEF(-4, 8), COEF( 64, 144), COEF(168, 104), COEF( 28, 0)},
|
|
{COEF(-4, 8), COEF( 68, 148), COEF(168, 100), COEF( 24, 0)},
|
|
{COEF( 0, 12), COEF( 72, 152), COEF(164, 92), COEF( 20, 0)},
|
|
{COEF( 0, 12), COEF( 80, 156), COEF(160, 88), COEF( 16, 0)},
|
|
{COEF( 0, 16), COEF( 84, 156), COEF(160, 80), COEF( 16, 0)},
|
|
{COEF( 0, 12), COEF( 80, 156), COEF(160, 88), COEF( 16, 0)},
|
|
{COEF( 0, 12), COEF( 72, 152), COEF(164, 92), COEF( 20, 0)},
|
|
{COEF(-4, 8), COEF( 68, 148), COEF(168, 100), COEF( 24, 0)},
|
|
{COEF(-4, 8), COEF( 64, 144), COEF(168, 104), COEF( 28, 0)},
|
|
{COEF(-4, 8), COEF( 56, 140), COEF(172, 108), COEF( 32, 0)},
|
|
{COEF(-4, 4), COEF( 52, 136), COEF(172, 116), COEF( 36, 0)},
|
|
{COEF(-4, 4), COEF( 48, 132), COEF(172, 120), COEF( 40, 0)}
|
|
}, { /* 8:4 Zoom-out */
|
|
{COEF( 0, 8), COEF( 52, 120), COEF(156, 116), COEF( 52, 8)},
|
|
{COEF( 0, 12), COEF( 56, 124), COEF(152, 112), COEF( 48, 8)},
|
|
{COEF( 0, 12), COEF( 60, 128), COEF(152, 108), COEF( 44, 8)},
|
|
{COEF( 0, 16), COEF( 64, 132), COEF(152, 104), COEF( 40, 4)},
|
|
{COEF( 0, 16), COEF( 68, 136), COEF(148, 104), COEF( 36, 4)},
|
|
{COEF( 0, 24), COEF( 72, 136), COEF(148, 96), COEF( 32, 4)},
|
|
{COEF( 0, 20), COEF( 76, 140), COEF(148, 92), COEF( 32, 4)},
|
|
{COEF( 0, 24), COEF( 84, 140), COEF(144, 88), COEF( 28, 4)},
|
|
{COEF( 4, 24), COEF( 88, 144), COEF(140, 84), COEF( 24, 4)},
|
|
{COEF( 0, 24), COEF( 84, 140), COEF(144, 88), COEF( 28, 4)},
|
|
{COEF( 0, 20), COEF( 76, 140), COEF(148, 92), COEF( 32, 4)},
|
|
{COEF( 0, 24), COEF( 72, 136), COEF(148, 96), COEF( 32, 4)},
|
|
{COEF( 0, 16), COEF( 68, 136), COEF(148, 104), COEF( 36, 4)},
|
|
{COEF( 0, 16), COEF( 64, 132), COEF(152, 104), COEF( 40, 4)},
|
|
{COEF( 0, 12), COEF( 60, 128), COEF(152, 108), COEF( 44, 8)},
|
|
{COEF( 0, 12), COEF( 56, 124), COEF(152, 112), COEF( 48, 8)}
|
|
}, { /* 8:3 Zoom-out */
|
|
{COEF( 0, 16), COEF( 60, 112), COEF(140, 112), COEF( 56, 16)},
|
|
{COEF( 4, 20), COEF( 64, 116), COEF(136, 108), COEF( 52, 12)},
|
|
{COEF( 4, 24), COEF( 64, 120), COEF(136, 104), COEF( 48, 12)},
|
|
{COEF( 4, 24), COEF( 68, 120), COEF(136, 100), COEF( 48, 12)},
|
|
{COEF( 4, 24), COEF( 72, 124), COEF(136, 100), COEF( 44, 8)},
|
|
{COEF( 4, 28), COEF( 76, 124), COEF(136, 96), COEF( 40, 8)},
|
|
{COEF( 8, 28), COEF( 80, 128), COEF(132, 92), COEF( 36, 8)},
|
|
{COEF( 8, 32), COEF( 84, 128), COEF(132, 88), COEF( 32, 8)},
|
|
{COEF( 8, 32), COEF( 88, 128), COEF(132, 88), COEF( 32, 8)},
|
|
{COEF( 8, 32), COEF( 84, 128), COEF(132, 92), COEF( 32, 8)},
|
|
{COEF( 8, 28), COEF( 80, 128), COEF(132, 96), COEF( 36, 8)},
|
|
{COEF( 4, 28), COEF( 76, 124), COEF(136, 72), COEF( 40, 8)},
|
|
{COEF( 4, 24), COEF( 72, 124), COEF(136, 100), COEF( 44, 8)},
|
|
{COEF( 4, 24), COEF( 68, 120), COEF(136, 100), COEF( 48, 12)},
|
|
{COEF( 4, 24), COEF( 64, 120), COEF(136, 104), COEF( 48, 12)},
|
|
{COEF( 4, 20), COEF( 64, 116), COEF(136, 108), COEF( 52, 12)}
|
|
}, { /* 8:2 Zoom-out */
|
|
{COEF( 0, 20), COEF( 64, 108), COEF(132, 108), COEF( 60, 20)},
|
|
{COEF( 8, 24), COEF( 64, 108), COEF(128, 104), COEF( 56, 20)},
|
|
{COEF( 8, 24), COEF( 68, 112), COEF(128, 100), COEF( 52, 20)},
|
|
{COEF( 8, 24), COEF( 72, 116), COEF(128, 100), COEF( 48, 16)},
|
|
{COEF( 8, 28), COEF( 76, 116), COEF(124, 96), COEF( 48, 16)},
|
|
{COEF( 8, 32), COEF( 80, 120), COEF(124, 92), COEF( 44, 12)},
|
|
{COEF( 8, 32), COEF( 80, 120), COEF(124, 92), COEF( 44, 12)},
|
|
{COEF( 8, 36), COEF( 84, 120), COEF(124, 88), COEF( 40, 12)},
|
|
{COEF(12, 40), COEF( 88, 124), COEF(120, 84), COEF( 36, 8)},
|
|
{COEF( 8, 36), COEF( 84, 120), COEF(124, 88), COEF( 40, 12)},
|
|
{COEF( 8, 32), COEF( 80, 120), COEF(124, 92), COEF( 44, 12)},
|
|
{COEF( 8, 32), COEF( 80, 120), COEF(124, 92), COEF( 44, 12)},
|
|
{COEF( 8, 28), COEF( 76, 116), COEF(124, 96), COEF( 48, 16)},
|
|
{COEF( 8, 24), COEF( 72, 116), COEF(128, 100), COEF( 48, 16)},
|
|
{COEF( 8, 24), COEF( 68, 112), COEF(128, 100), COEF( 52, 20)},
|
|
{COEF( 8, 24), COEF( 64, 108), COEF(128, 100), COEF( 56, 20)}
|
|
}
|
|
};
|
|
|
|
static const __u32 sc_coef_4t_blur1[7][16][2] = {
|
|
{ /* 8:8 or zoom-in */
|
|
{COEF( 0, 108), COEF(304, 100)},
|
|
{COEF( 0, 124), COEF(304, 84)},
|
|
{COEF( 0, 140), COEF(300, 72)},
|
|
{COEF( 4, 156), COEF(292, 60)},
|
|
{COEF( 4, 176), COEF(284, 48)},
|
|
{COEF( 8, 192), COEF(276, 36)},
|
|
{COEF( 12, 212), COEF(260, 28)},
|
|
{COEF( 16, 228), COEF(244, 24)},
|
|
{COEF( 20, 244), COEF(232, 16)},
|
|
{COEF( 24, 244), COEF(228, 16)},
|
|
{COEF( 28, 260), COEF(212, 12)},
|
|
{COEF( 36, 276), COEF(192, 8)},
|
|
{COEF( 48, 284), COEF(176, 4)},
|
|
{COEF( 60, 292), COEF(156, 4)},
|
|
{COEF( 72, 300), COEF(140, 0)},
|
|
{COEF( 84, 304), COEF(124, 0)}
|
|
}, { /* 8:7 Zoom-out */
|
|
{COEF( 0, 116), COEF(292, 104)},
|
|
{COEF( 4, 128), COEF(288, 92)},
|
|
{COEF( 4, 144), COEF(288, 76)},
|
|
{COEF( 8, 160), COEF(280, 64)},
|
|
{COEF( 8, 176), COEF(272, 56)},
|
|
{COEF( 12, 192), COEF(264, 44)},
|
|
{COEF( 16, 208), COEF(252, 36)},
|
|
{COEF( 20, 224), COEF(240, 28)},
|
|
{COEF( 28, 232), COEF(228, 24)},
|
|
{COEF( 28, 240), COEF(224, 20)},
|
|
{COEF( 36, 252), COEF(208, 16)},
|
|
{COEF( 44, 264), COEF(192, 12)},
|
|
{COEF( 56, 272), COEF(176, 8)},
|
|
{COEF( 64, 280), COEF(160, 8)},
|
|
{COEF( 76, 288), COEF(144, 4)},
|
|
{COEF( 92, 288), COEF(128, 4)}
|
|
}, { /* 8:6 Zoom-out */
|
|
{COEF( 0, 120), COEF(276, 116)},
|
|
{COEF( 8, 132), COEF(276, 96)},
|
|
{COEF( 8, 148), COEF(272, 84)},
|
|
{COEF( 12, 164), COEF(264, 72)},
|
|
{COEF( 12, 176), COEF(260, 64)},
|
|
{COEF( 16, 192), COEF(252, 52)},
|
|
{COEF( 20, 204), COEF(244, 44)},
|
|
{COEF( 28, 216), COEF(232, 36)},
|
|
{COEF( 32, 232), COEF(220, 28)},
|
|
{COEF( 36, 232), COEF(216, 28)},
|
|
{COEF( 44, 244), COEF(204, 20)},
|
|
{COEF( 52, 252), COEF(192, 16)},
|
|
{COEF( 64, 260), COEF(176, 12)},
|
|
{COEF( 72, 264), COEF(164, 12)},
|
|
{COEF( 84, 272), COEF(148, 8)},
|
|
{COEF( 96, 276), COEF(132, 8)}
|
|
}, { /* 8:5 Zoom-out */
|
|
{COEF( 0, 128), COEF(264, 120)},
|
|
{COEF( 12, 136), COEF(264, 100)},
|
|
{COEF( 12, 152), COEF(260, 88)},
|
|
{COEF( 16, 164), COEF(256, 76)},
|
|
{COEF( 16, 176), COEF(252, 68)},
|
|
{COEF( 20, 192), COEF(244, 56)},
|
|
{COEF( 28, 200), COEF(236, 48)},
|
|
{COEF( 32, 216), COEF(224, 50)},
|
|
{COEF( 40, 224), COEF(216, 32)},
|
|
{COEF( 40, 224), COEF(216, 32)},
|
|
{COEF( 48, 236), COEF(200, 28)},
|
|
{COEF( 56, 244), COEF(192, 20)},
|
|
{COEF( 68, 252), COEF(176, 16)},
|
|
{COEF( 76, 256), COEF(164, 16)},
|
|
{COEF( 88, 260), COEF(152, 12)},
|
|
{COEF(100, 264), COEF(136, 12)}
|
|
}, { /* 8:4 Zoom-out */
|
|
{COEF( 0, 136), COEF(256, 120)},
|
|
{COEF( 12, 140), COEF(256, 104)},
|
|
{COEF( 16, 152), COEF(252, 92)},
|
|
{COEF( 16, 164), COEF(248, 84)},
|
|
{COEF( 20, 176), COEF(244, 72)},
|
|
{COEF( 24, 188), COEF(240, 60)},
|
|
{COEF( 32, 200), COEF(228, 52)},
|
|
{COEF( 36, 212), COEF(220, 44)},
|
|
{COEF( 44, 220), COEF(212, 36)},
|
|
{COEF( 52, 200), COEF(228, 32)},
|
|
{COEF( 52, 228), COEF(200, 32)},
|
|
{COEF( 60, 240), COEF(188, 24)},
|
|
{COEF( 72, 244), COEF(176, 20)},
|
|
{COEF( 84, 248), COEF(164, 16)},
|
|
{COEF( 92, 252), COEF(152, 16)},
|
|
{COEF(104, 256), COEF(140, 12)}
|
|
}, { /* 8:3 Zoom-out */
|
|
{COEF( 0, 128), COEF(248, 128)},
|
|
{COEF( 16, 140), COEF(248, 108)},
|
|
{COEF( 16, 152), COEF(244, 100)},
|
|
{COEF( 20, 164), COEF(240, 88)},
|
|
{COEF( 24, 176), COEF(236, 76)},
|
|
{COEF( 28, 188), COEF(232, 64)},
|
|
{COEF( 36, 196), COEF(224, 56)},
|
|
{COEF( 40, 208), COEF(216, 48)},
|
|
{COEF( 48, 216), COEF(208, 40)},
|
|
{COEF( 48, 216), COEF(208, 40)},
|
|
{COEF( 56, 224), COEF(196, 36)},
|
|
{COEF( 64, 232), COEF(188, 28)},
|
|
{COEF( 76, 236), COEF(176, 24)},
|
|
{COEF( 88, 240), COEF(164, 20)},
|
|
{COEF(100, 244), COEF(152, 16)},
|
|
{COEF(108, 248), COEF(140, 16)}
|
|
}, { /* 8:2 Zoom-out */
|
|
{COEF( 8, 132), COEF(244, 128)},
|
|
{COEF( 20, 144), COEF(244, 104)},
|
|
{COEF( 20, 152), COEF(240, 100)},
|
|
{COEF( 24, 164), COEF(236, 88)},
|
|
{COEF( 28, 176), COEF(232, 76)},
|
|
{COEF( 32, 184), COEF(228, 68)},
|
|
{COEF( 36, 196), COEF(220, 60)},
|
|
{COEF( 44, 204), COEF(212, 52)},
|
|
{COEF( 52, 212), COEF(204, 44)},
|
|
{COEF( 52, 212), COEF(204, 44)},
|
|
{COEF( 60, 220), COEF(196, 36)},
|
|
{COEF( 68, 228), COEF(184, 32)},
|
|
{COEF( 76, 232), COEF(176, 28)},
|
|
{COEF( 88, 236), COEF(164, 24)},
|
|
{COEF(100, 240), COEF(152, 20)},
|
|
{COEF(104, 244), COEF(144, 20)}
|
|
},
|
|
};
|
|
|
|
/* CSC(Color Space Conversion) coefficient value */
|
|
static struct sc_csc_tab sc_no_csc = {
|
|
{ 0x200, 0x000, 0x000, 0x000, 0x200, 0x000, 0x000, 0x000, 0x200 },
|
|
};
|
|
|
|
static struct sc_csc_tab sc_y2r = {
|
|
/* REC.601 Narrow */
|
|
{ 0x0254, 0x0000, 0x0331, 0x0254, 0xFF37, 0xFE60, 0x0254, 0x0409, 0x0000 },
|
|
/* REC.601 Wide */
|
|
{ 0x0200, 0x0000, 0x02BE, 0x0200, 0xFF54, 0xFE9B, 0x0200, 0x0377, 0x0000 },
|
|
/* REC.709 Narrow */
|
|
{ 0x0254, 0x0000, 0x0396, 0x0254, 0xFF93, 0xFEEF, 0x0254, 0x043A, 0x0000 },
|
|
/* REC.709 Wide */
|
|
{ 0x0200, 0x0000, 0x0314, 0x0200, 0xFFA2, 0xFF16, 0x0200, 0x03A1, 0x0000 },
|
|
/* BT.2020 Narrow */
|
|
{ 0x0254, 0x0000, 0x035B, 0x0254, 0xFFA0, 0xFEB3, 0x0254, 0x0449, 0x0000 },
|
|
/* BT.2020 Wide */
|
|
{ 0x0200, 0x0000, 0x02E2, 0x0200, 0xFFAE, 0xFEE2, 0x0200, 0x03AE, 0x0000 },
|
|
};
|
|
|
|
static struct sc_csc_tab sc_r2y = {
|
|
/* REC.601 Narrow */
|
|
{ 0x0083, 0x0102, 0x0032, 0xFFB4, 0xFF6B, 0x00E1, 0x00E1, 0xFF44, 0xFFDB },
|
|
/* REC.601 Wide */
|
|
{ 0x0099, 0x012D, 0x003A, 0xFFA8, 0xFF53, 0x0106, 0x0106, 0xFF25, 0xFFD5 },
|
|
/* REC.709 Narrow */
|
|
{ 0x005D, 0x013A, 0x0020, 0xFFCC, 0xFF53, 0x00E1, 0x00E1, 0xFF34, 0xFFEB },
|
|
/* REC.709 Wide */
|
|
{ 0x006D, 0x016E, 0x0025, 0xFFC4, 0xFF36, 0x0106, 0x0106, 0xFF12, 0xFFE8 },
|
|
/* BT.2020 Narrow */
|
|
{ 0x0074, 0x012A, 0x001A, 0xFFC1, 0xFF5E, 0x00E1, 0x00E1, 0xFF31, 0xFFEE },
|
|
/* BT.2020 Wide */
|
|
{ 0x0087, 0x015B, 0x001E, 0xFFB7, 0xFF43, 0x0106, 0x0106, 0xFF0F, 0xFFEB },
|
|
};
|
|
|
|
static struct sc_csc_tab *sc_csc_list[] = {
|
|
[0] = &sc_no_csc,
|
|
[1] = &sc_y2r,
|
|
[2] = &sc_r2y,
|
|
};
|
|
|
|
static struct sc_bl_op_val sc_bl_op_tbl[] = {
|
|
/* Sc, Sa, Dc, Da */
|
|
{ZERO, ZERO, ZERO, ZERO}, /* CLEAR */
|
|
{ ONE, ONE, ZERO, ZERO}, /* SRC */
|
|
{ZERO, ZERO, ONE, ONE}, /* DST */
|
|
{ ONE, ONE, INV_SA, INV_SA}, /* SRC_OVER */
|
|
{INV_DA, ONE, ONE, INV_SA}, /* DST_OVER */
|
|
{DST_A, DST_A, ZERO, ZERO}, /* SRC_IN */
|
|
{ZERO, ZERO, SRC_A, SRC_A}, /* DST_IN */
|
|
{INV_DA, INV_DA, ZERO, ZERO}, /* SRC_OUT */
|
|
{ZERO, ZERO, INV_SA, INV_SA}, /* DST_OUT */
|
|
{DST_A, ZERO, INV_SA, ONE}, /* SRC_ATOP */
|
|
{INV_DA, ONE, SRC_A, ZERO}, /* DST_ATOP */
|
|
{INV_DA, ONE, INV_SA, ONE}, /* XOR: need to WA */
|
|
{INV_DA, ONE, INV_SA, INV_SA}, /* DARKEN */
|
|
{INV_DA, ONE, INV_SA, INV_SA}, /* LIGHTEN */
|
|
{INV_DA, ONE, INV_SA, INV_SA}, /* MULTIPLY */
|
|
{ONE, ONE, INV_SC, INV_SA}, /* SCREEN */
|
|
{ONE, ONE, ONE, ONE}, /* ADD */
|
|
};
|
|
|
|
int sc_hwset_src_image_format(struct sc_dev *sc, const struct sc_fmt *fmt)
|
|
{
|
|
writel(fmt->cfg_val, sc->regs + SCALER_SRC_CFG);
|
|
return 0;
|
|
}
|
|
|
|
int sc_hwset_dst_image_format(struct sc_dev *sc, const struct sc_fmt *fmt)
|
|
{
|
|
writel(fmt->cfg_val, sc->regs + SCALER_DST_CFG);
|
|
|
|
/*
|
|
* When output format is RGB,
|
|
* CSC_Y_OFFSET_DST_EN should be 0
|
|
* to avoid color distortion
|
|
*/
|
|
if (fmt->is_rgb) {
|
|
writel(readl(sc->regs + SCALER_CFG) &
|
|
~SCALER_CFG_CSC_Y_OFFSET_DST,
|
|
sc->regs + SCALER_CFG);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void sc_hwset_pre_multi_format(struct sc_dev *sc, bool src, bool dst)
|
|
{
|
|
unsigned long cfg = readl(sc->regs + SCALER_SRC_CFG);
|
|
|
|
if (sc->version == SCALER_VERSION(4, 0, 1)) {
|
|
if (src != dst)
|
|
dev_err(sc->dev,
|
|
"pre-multi fmt should be same between src and dst\n");
|
|
return;
|
|
}
|
|
|
|
if (src && ((cfg & SCALER_CFG_FMT_MASK) == SCALER_CFG_FMT_ARGB8888)) {
|
|
cfg &= ~SCALER_CFG_FMT_MASK;
|
|
cfg |= SCALER_CFG_FMT_P_ARGB8888;
|
|
writel(cfg, sc->regs + SCALER_SRC_CFG);
|
|
}
|
|
|
|
cfg = readl(sc->regs + SCALER_DST_CFG);
|
|
if (dst && ((cfg & SCALER_CFG_FMT_MASK) == SCALER_CFG_FMT_ARGB8888)) {
|
|
cfg &= ~SCALER_CFG_FMT_MASK;
|
|
cfg |= SCALER_CFG_FMT_P_ARGB8888;
|
|
writel(cfg, sc->regs + SCALER_DST_CFG);
|
|
}
|
|
}
|
|
|
|
void get_blend_value(unsigned int *cfg, u32 val, bool pre_multi)
|
|
{
|
|
unsigned int tmp;
|
|
|
|
*cfg &= ~(SCALER_SEL_INV_MASK | SCALER_SEL_MASK |
|
|
SCALER_OP_SEL_INV_MASK | SCALER_OP_SEL_MASK);
|
|
|
|
if (val == 0xff) {
|
|
*cfg |= (1 << SCALER_SEL_INV_SHIFT);
|
|
} else {
|
|
if (pre_multi)
|
|
*cfg |= (1 << SCALER_SEL_SHIFT);
|
|
else
|
|
*cfg |= (2 << SCALER_SEL_SHIFT);
|
|
tmp = val & 0xf;
|
|
*cfg |= (tmp << SCALER_OP_SEL_SHIFT);
|
|
}
|
|
|
|
if (val >= BL_INV_BIT_OFFSET)
|
|
*cfg |= (1 << SCALER_OP_SEL_INV_SHIFT);
|
|
}
|
|
|
|
void sc_hwset_blend(struct sc_dev *sc, enum sc_blend_op bl_op, bool pre_multi,
|
|
unsigned char g_alpha)
|
|
{
|
|
unsigned int cfg = readl(sc->regs + SCALER_CFG);
|
|
int idx = bl_op - 1;
|
|
|
|
cfg |= SCALER_CFG_BLEND_EN;
|
|
writel(cfg, sc->regs + SCALER_CFG);
|
|
|
|
cfg = readl(sc->regs + SCALER_SRC_BLEND_COLOR);
|
|
get_blend_value(&cfg, sc_bl_op_tbl[idx].src_color, pre_multi);
|
|
if (g_alpha < 0xff)
|
|
cfg |= (SRC_GA << SCALER_OP_SEL_SHIFT);
|
|
writel(cfg, sc->regs + SCALER_SRC_BLEND_COLOR);
|
|
sc_dbg("src_blend_color is 0x%x, %d\n", cfg, pre_multi);
|
|
|
|
cfg = readl(sc->regs + SCALER_SRC_BLEND_ALPHA);
|
|
get_blend_value(&cfg, sc_bl_op_tbl[idx].src_alpha, 1);
|
|
if (g_alpha < 0xff)
|
|
cfg |= (SRC_GA << SCALER_OP_SEL_SHIFT) | (g_alpha << 0);
|
|
writel(cfg, sc->regs + SCALER_SRC_BLEND_ALPHA);
|
|
sc_dbg("src_blend_alpha is 0x%x\n", cfg);
|
|
|
|
cfg = readl(sc->regs + SCALER_DST_BLEND_COLOR);
|
|
get_blend_value(&cfg, sc_bl_op_tbl[idx].dst_color, pre_multi);
|
|
if (g_alpha < 0xff)
|
|
cfg |= ((INV_SAGA & 0xf) << SCALER_OP_SEL_SHIFT);
|
|
writel(cfg, sc->regs + SCALER_DST_BLEND_COLOR);
|
|
sc_dbg("dst_blend_color is 0x%x\n", cfg);
|
|
|
|
cfg = readl(sc->regs + SCALER_DST_BLEND_ALPHA);
|
|
get_blend_value(&cfg, sc_bl_op_tbl[idx].dst_alpha, 1);
|
|
if (g_alpha < 0xff)
|
|
cfg |= ((INV_SAGA & 0xf) << SCALER_OP_SEL_SHIFT);
|
|
writel(cfg, sc->regs + SCALER_DST_BLEND_ALPHA);
|
|
sc_dbg("dst_blend_alpha is 0x%x\n", cfg);
|
|
|
|
/*
|
|
* If dst format is non-premultiplied format
|
|
* and blending operation is enabled,
|
|
* result image should be divided by alpha value
|
|
* because the result is always pre-multiplied.
|
|
*/
|
|
if (!pre_multi) {
|
|
cfg = readl(sc->regs + SCALER_CFG);
|
|
cfg |= SCALER_CFG_BL_DIV_ALPHA_EN;
|
|
writel(cfg, sc->regs + SCALER_CFG);
|
|
}
|
|
}
|
|
|
|
void sc_hwset_color_fill(struct sc_dev *sc, unsigned int val)
|
|
{
|
|
unsigned int cfg = readl(sc->regs + SCALER_CFG);
|
|
|
|
cfg |= SCALER_CFG_FILL_EN;
|
|
writel(cfg, sc->regs + SCALER_CFG);
|
|
|
|
cfg = readl(sc->regs + SCALER_FILL_COLOR);
|
|
cfg = val;
|
|
writel(cfg, sc->regs + SCALER_FILL_COLOR);
|
|
sc_dbg("color filled is 0x%08x\n", val);
|
|
}
|
|
|
|
void sc_hwset_dith(struct sc_dev *sc, unsigned int val)
|
|
{
|
|
unsigned int cfg = readl(sc->regs + SCALER_DITH_CFG);
|
|
|
|
cfg &= ~(SCALER_DITH_R_MASK | SCALER_DITH_G_MASK | SCALER_DITH_B_MASK);
|
|
cfg |= val;
|
|
writel(cfg, sc->regs + SCALER_DITH_CFG);
|
|
}
|
|
|
|
void sc_hwset_csc_coef(struct sc_dev *sc, enum sc_csc_idx idx,
|
|
struct sc_csc *csc)
|
|
{
|
|
unsigned int i, j, tmp;
|
|
unsigned long cfg;
|
|
int *csc_eq_val;
|
|
|
|
if (idx == NO_CSC) {
|
|
csc_eq_val = sc_csc_list[idx]->narrow_601;
|
|
} else {
|
|
if (csc->csc_eq == V4L2_COLORSPACE_REC709) {
|
|
if (csc->csc_range == SC_CSC_NARROW)
|
|
csc_eq_val = sc_csc_list[idx]->narrow_709;
|
|
else
|
|
csc_eq_val = sc_csc_list[idx]->wide_709;
|
|
} else if (csc->csc_eq == V4L2_COLORSPACE_BT2020) {
|
|
if (csc->csc_range == SC_CSC_NARROW)
|
|
csc_eq_val = sc_csc_list[idx]->narrow_2020;
|
|
else
|
|
csc_eq_val = sc_csc_list[idx]->wide_2020;
|
|
} else {
|
|
if (csc->csc_range == SC_CSC_NARROW)
|
|
csc_eq_val = sc_csc_list[idx]->narrow_601;
|
|
else
|
|
csc_eq_val = sc_csc_list[idx]->wide_601;
|
|
}
|
|
}
|
|
|
|
tmp = SCALER_CSC_COEF22 - SCALER_CSC_COEF00;
|
|
|
|
for (i = 0, j = 0; i < 9; i++, j += 4) {
|
|
cfg = readl(sc->regs + SCALER_CSC_COEF00 + j);
|
|
cfg &= ~SCALER_CSC_COEF_MASK;
|
|
cfg |= csc_eq_val[i];
|
|
writel(cfg, sc->regs + SCALER_CSC_COEF00 + j);
|
|
sc_dbg("csc value %d - %d\n", i, csc_eq_val[i]);
|
|
}
|
|
|
|
/* set CSC_Y_OFFSET_EN */
|
|
cfg = readl(sc->regs + SCALER_CFG);
|
|
if (idx == CSC_Y2R) {
|
|
if (csc->csc_range == SC_CSC_WIDE)
|
|
cfg &= ~SCALER_CFG_CSC_Y_OFFSET_SRC;
|
|
else
|
|
cfg |= SCALER_CFG_CSC_Y_OFFSET_SRC;
|
|
} else if (idx == CSC_R2Y) {
|
|
if (csc->csc_range == SC_CSC_WIDE)
|
|
cfg &= ~SCALER_CFG_CSC_Y_OFFSET_DST;
|
|
else
|
|
cfg |= SCALER_CFG_CSC_Y_OFFSET_DST;
|
|
}
|
|
writel(cfg, sc->regs + SCALER_CFG);
|
|
}
|
|
|
|
static const __u32 sc_scaling_ratio[] = {
|
|
1048576, /* 0: 8:8 scaing or zoom-in */
|
|
1198372, /* 1: 8:7 zoom-out */
|
|
1398101, /* 2: 8:6 zoom-out */
|
|
1677721, /* 3: 8:5 zoom-out */
|
|
2097152, /* 4: 8:4 zoom-out */
|
|
2796202, /* 5: 8:3 zoom-out */
|
|
/* higher ratio -> 6: 8:2 zoom-out */
|
|
};
|
|
|
|
static unsigned int sc_get_scale_filter(unsigned int ratio)
|
|
{
|
|
unsigned int filter;
|
|
|
|
for (filter = 0; filter < ARRAY_SIZE(sc_scaling_ratio); filter++)
|
|
if (ratio <= sc_scaling_ratio[filter])
|
|
return filter;
|
|
|
|
return filter;
|
|
}
|
|
|
|
static u32 sc_coef_adjust(u32 val)
|
|
{
|
|
/*
|
|
* Truncate LSB 2 bit of two 11 bit value like below.
|
|
* [26:16] -> [24:16], [10:0] -> [8:0]
|
|
*
|
|
* If val has 0x01BC0038, for example, it will return 0x006F000E.
|
|
*/
|
|
return ((val >> 2) & 0x1ff01ff);
|
|
}
|
|
|
|
#define sc_coef_adj(x, val) (unlikely(x) ? sc_coef_adjust(val) : val)
|
|
void sc_hwset_polyphase_hcoef(struct sc_dev *sc,
|
|
unsigned int yratio, unsigned int cratio,
|
|
unsigned int filter)
|
|
{
|
|
unsigned int phase;
|
|
unsigned int yfilter = sc_get_scale_filter(yratio);
|
|
unsigned int cfilter = sc_get_scale_filter(cratio);
|
|
const __u32 (*sc_coef_8t)[16][4] = sc_coef_8t_org;
|
|
bool bit_adj = !sc->variant->pixfmt_10bit;
|
|
|
|
if (sc_set_blur || filter == SC_FT_BLUR)
|
|
sc_coef_8t = sc_coef_8t_blur1;
|
|
|
|
BUG_ON(yfilter >= ARRAY_SIZE(sc_coef_8t_org));
|
|
BUG_ON(cfilter >= ARRAY_SIZE(sc_coef_8t_org));
|
|
|
|
BUILD_BUG_ON(ARRAY_SIZE(sc_coef_8t_org[yfilter]) < 9);
|
|
BUILD_BUG_ON(ARRAY_SIZE(sc_coef_8t_org[cfilter]) < 9);
|
|
|
|
for (phase = 0; phase < 9; phase++) {
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[yfilter][phase][3]),
|
|
sc->regs + SCALER_YHCOEF + phase * 16);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[yfilter][phase][2]),
|
|
sc->regs + SCALER_YHCOEF + phase * 16 + 4);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[yfilter][phase][1]),
|
|
sc->regs + SCALER_YHCOEF + phase * 16 + 8);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[yfilter][phase][0]),
|
|
sc->regs + SCALER_YHCOEF + phase * 16 + 12);
|
|
}
|
|
|
|
for (phase = 0; phase < 9; phase++) {
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[cfilter][phase][3]),
|
|
sc->regs + SCALER_CHCOEF + phase * 16);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[cfilter][phase][2]),
|
|
sc->regs + SCALER_CHCOEF + phase * 16 + 4);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[cfilter][phase][1]),
|
|
sc->regs + SCALER_CHCOEF + phase * 16 + 8);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_8t[cfilter][phase][0]),
|
|
sc->regs + SCALER_CHCOEF + phase * 16 + 12);
|
|
}
|
|
}
|
|
|
|
void sc_hwset_polyphase_vcoef(struct sc_dev *sc,
|
|
unsigned int yratio, unsigned int cratio,
|
|
unsigned int filter)
|
|
{
|
|
unsigned int phase;
|
|
unsigned int yfilter = sc_get_scale_filter(yratio);
|
|
unsigned int cfilter = sc_get_scale_filter(cratio);
|
|
const __u32 (*sc_coef_4t)[16][2] = sc_coef_4t_org;
|
|
bool bit_adj = !sc->variant->pixfmt_10bit;
|
|
|
|
if (sc_set_blur || filter == SC_FT_BLUR)
|
|
sc_coef_4t = sc_coef_4t_blur1;
|
|
|
|
BUG_ON(yfilter >= ARRAY_SIZE(sc_coef_4t_org));
|
|
BUG_ON(cfilter >= ARRAY_SIZE(sc_coef_4t_org));
|
|
|
|
BUILD_BUG_ON(ARRAY_SIZE(sc_coef_4t_org[yfilter]) < 9);
|
|
BUILD_BUG_ON(ARRAY_SIZE(sc_coef_4t_org[cfilter]) < 9);
|
|
|
|
/* reset value of the coefficient registers are the 8:8 table */
|
|
for (phase = 0; phase < 9; phase++) {
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_4t[yfilter][phase][1]),
|
|
sc->regs + SCALER_YVCOEF + phase * 8);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_4t[yfilter][phase][0]),
|
|
sc->regs + SCALER_YVCOEF + phase * 8 + 4);
|
|
}
|
|
|
|
for (phase = 0; phase < 9; phase++) {
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_4t[cfilter][phase][1]),
|
|
sc->regs + SCALER_CVCOEF + phase * 8);
|
|
__raw_writel(sc_coef_adj(bit_adj, sc_coef_4t[cfilter][phase][0]),
|
|
sc->regs + SCALER_CVCOEF + phase * 8 + 4);
|
|
}
|
|
}
|
|
|
|
void sc_hwset_src_imgsize(struct sc_dev *sc, struct sc_frame *frame)
|
|
{
|
|
unsigned long cfg = 0;
|
|
|
|
cfg &= ~(SCALER_SRC_CSPAN_MASK | SCALER_SRC_YSPAN_MASK);
|
|
cfg |= frame->width;
|
|
|
|
/*
|
|
* TODO: C width should be half of Y width
|
|
* but, how to get the diffferent c width from user
|
|
* like AYV12 format
|
|
*/
|
|
if (frame->sc_fmt->num_comp == 2)
|
|
cfg |= (frame->width << frame->sc_fmt->cspan) << 16;
|
|
if (frame->sc_fmt->num_comp == 3) {
|
|
if (sc_fmt_is_ayv12(frame->sc_fmt->pixelformat))
|
|
cfg |= ALIGN(frame->width >> 1, 16) << 16;
|
|
else if (frame->sc_fmt->cspan) /* YUV444 */
|
|
cfg |= frame->width << 16;
|
|
else
|
|
cfg |= (frame->width >> 1) << 16;
|
|
}
|
|
|
|
writel(cfg, sc->regs + SCALER_SRC_SPAN);
|
|
}
|
|
|
|
void sc_hwset_intsrc_imgsize(struct sc_dev *sc, int num_comp, __u32 width)
|
|
{
|
|
unsigned long cfg = 0;
|
|
|
|
cfg &= ~(SCALER_SRC_CSPAN_MASK | SCALER_SRC_YSPAN_MASK);
|
|
cfg |= width;
|
|
|
|
/*
|
|
* TODO: C width should be half of Y width
|
|
* but, how to get the diffferent c width from user
|
|
* like AYV12 format
|
|
*/
|
|
if (num_comp == 2)
|
|
cfg |= width << 16;
|
|
if (num_comp == 3)
|
|
cfg |= (width >> 1) << 16;
|
|
|
|
writel(cfg, sc->regs + SCALER_SRC_SPAN);
|
|
}
|
|
|
|
void sc_hwset_dst_imgsize(struct sc_dev *sc, struct sc_frame *frame)
|
|
{
|
|
unsigned long cfg = 0;
|
|
|
|
cfg &= ~(SCALER_DST_CSPAN_MASK | SCALER_DST_YSPAN_MASK);
|
|
cfg |= frame->width;
|
|
|
|
/*
|
|
* TODO: C width should be half of Y width
|
|
* but, how to get the diffferent c width from user
|
|
* like AYV12 format
|
|
*/
|
|
if (frame->sc_fmt->num_comp == 2)
|
|
cfg |= (frame->width << frame->sc_fmt->cspan) << 16;
|
|
if (frame->sc_fmt->num_comp == 3) {
|
|
if (sc_fmt_is_ayv12(frame->sc_fmt->pixelformat))
|
|
cfg |= ALIGN(frame->width >> 1, 16) << 16;
|
|
else if (frame->sc_fmt->cspan) /* YUV444 */
|
|
cfg |= frame->width << 16;
|
|
else
|
|
cfg |= (frame->width >> 1) << 16;
|
|
}
|
|
|
|
writel(cfg, sc->regs + SCALER_DST_SPAN);
|
|
}
|
|
|
|
int sc_calc_s10b_planesize(u32 pixelformat, u32 width, u32 height,
|
|
u32 *ysize, u32 *csize, bool only_8bit);
|
|
static void sc_hwset_src_2bit_addr(struct sc_dev *sc, struct sc_frame *frame)
|
|
{
|
|
u32 yaddr_2bit, caddr_2bit;
|
|
unsigned long cfg = 0;
|
|
|
|
BUG_ON(frame->sc_fmt->num_comp != 2);
|
|
|
|
sc_calc_s10b_planesize(frame->sc_fmt->pixelformat,
|
|
frame->width, frame->height,
|
|
&yaddr_2bit, &caddr_2bit, true);
|
|
yaddr_2bit += frame->addr.ioaddr[SC_PLANE_Y];
|
|
caddr_2bit += frame->addr.ioaddr[SC_PLANE_CB];
|
|
|
|
writel(yaddr_2bit, sc->regs + SCALER_SRC_2BIT_Y_BASE);
|
|
writel(caddr_2bit, sc->regs + SCALER_SRC_2BIT_C_BASE);
|
|
|
|
cfg &= ~(SCALER_SRC_2BIT_CSPAN_MASK | SCALER_SRC_2BIT_YSPAN_MASK);
|
|
cfg |= ALIGN(frame->width, 16);
|
|
cfg |= (ALIGN(frame->width, 16) << frame->sc_fmt->cspan) << 16;
|
|
writel(cfg, sc->regs + SCALER_SRC_2BIT_SPAN);
|
|
}
|
|
|
|
void sc_hwset_src_addr(struct sc_dev *sc, struct sc_frame *frame)
|
|
{
|
|
struct sc_addr *addr = &frame->addr;
|
|
|
|
writel(addr->ioaddr[SC_PLANE_Y], sc->regs + SCALER_SRC_Y_BASE);
|
|
writel(addr->ioaddr[SC_PLANE_CB], sc->regs + SCALER_SRC_CB_BASE);
|
|
writel(addr->ioaddr[SC_PLANE_CR], sc->regs + SCALER_SRC_CR_BASE);
|
|
|
|
if (sc_fmt_is_s10bit_yuv(frame->sc_fmt->pixelformat) &&
|
|
sc->variant->pixfmt_10bit)
|
|
sc_hwset_src_2bit_addr(sc, frame);
|
|
}
|
|
|
|
static void sc_hwset_dst_2bit_addr(struct sc_dev *sc, struct sc_frame *frame)
|
|
{
|
|
u32 yaddr_2bit, caddr_2bit;
|
|
unsigned long cfg = 0;
|
|
|
|
BUG_ON(frame->sc_fmt->num_comp != 2);
|
|
|
|
sc_calc_s10b_planesize(frame->sc_fmt->pixelformat,
|
|
frame->width, frame->height,
|
|
&yaddr_2bit, &caddr_2bit, true);
|
|
yaddr_2bit += frame->addr.ioaddr[SC_PLANE_Y];
|
|
caddr_2bit += frame->addr.ioaddr[SC_PLANE_CB];
|
|
|
|
writel(yaddr_2bit, sc->regs + SCALER_DST_2BIT_Y_BASE);
|
|
writel(caddr_2bit, sc->regs + SCALER_DST_2BIT_C_BASE);
|
|
|
|
cfg &= ~(SCALER_DST_2BIT_CSPAN_MASK | SCALER_DST_2BIT_YSPAN_MASK);
|
|
cfg |= ALIGN(frame->width, 16);
|
|
cfg |= (ALIGN(frame->width, 16) << frame->sc_fmt->cspan) << 16;
|
|
writel(cfg, sc->regs + SCALER_DST_2BIT_SPAN);
|
|
}
|
|
|
|
void sc_hwset_dst_addr(struct sc_dev *sc, struct sc_frame *frame)
|
|
{
|
|
struct sc_addr *addr = &frame->addr;
|
|
|
|
writel(addr->ioaddr[SC_PLANE_Y], sc->regs + SCALER_DST_Y_BASE);
|
|
writel(addr->ioaddr[SC_PLANE_CB], sc->regs + SCALER_DST_CB_BASE);
|
|
writel(addr->ioaddr[SC_PLANE_CR], sc->regs + SCALER_DST_CR_BASE);
|
|
|
|
if (sc_fmt_is_s10bit_yuv(frame->sc_fmt->pixelformat) &&
|
|
sc->variant->pixfmt_10bit)
|
|
sc_hwset_dst_2bit_addr(sc, frame);
|
|
}
|
|
|
|
void sc_hwregs_dump(struct sc_dev *sc)
|
|
{
|
|
dev_notice(sc->dev, "Dumping control registers...\n");
|
|
pr_notice("------------------------------------------------\n");
|
|
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x000, 0x044 - 0x000 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x050, 0x058 - 0x050 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x060, 0x134 - 0x060 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x140, 0x214 - 0x140 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x220, 0x240 - 0x220 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x250, 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x260, 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x278, 4, false);
|
|
if (sc->version <= SCALER_VERSION(2, 1, 1))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x280, 0x28C - 0x280 + 4, false);
|
|
if (sc->version >= SCALER_VERSION(5, 0, 0))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x280, 0x288 - 0x280 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x290, 0x298 - 0x290 + 4, false);
|
|
if (sc->version <= SCALER_VERSION(2, 1, 1))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x2A8, 0x2A8 - 0x2A0 + 4, false);
|
|
if (sc->version >= SCALER_VERSION(5, 0, 0))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x2A0, 0x2A8 - 0x2A0 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x2B0, 0x2C4 - 0x2B0 + 4, false);
|
|
if (sc->version >= SCALER_VERSION(3, 0, 0))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x2D0, 0x2DC - 0x2D0 + 4, false);
|
|
if (sc->version >= SCALER_VERSION(5, 0, 0))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x2E0, 0x2E8 - 0x2E0 + 4, false);
|
|
|
|
if (sc->version >= SCALER_VERSION(5, 0, 0))
|
|
goto end;
|
|
|
|
/* shadow registers */
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1004, 0x1004 - 0x1004 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1010, 0x1044 - 0x1010 + 4, false);
|
|
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1050, 0x1058 - 0x1050 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1060, 0x1134 - 0x1060 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1140, 0x1214 - 0x1140 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1220, 0x1240 - 0x1220 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1250, 4, false);
|
|
if (sc->version <= SCALER_VERSION(2, 1, 1) ||
|
|
sc->version <= SCALER_VERSION(4, 2, 0))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1280, 0x128C - 0x1280 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1290, 0x1298 - 0x1290 + 4, false);
|
|
if (sc->version >= SCALER_VERSION(3, 0, 0))
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x12D0, 0x12DC - 0x12D0 + 4, false);
|
|
if (sc->version >= SCALER_VERSION(4, 2, 0)) {
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1300, 0x1304 - 0x1300 + 4, false);
|
|
print_hex_dump(KERN_NOTICE, "", DUMP_PREFIX_ADDRESS, 16, 4,
|
|
sc->regs + 0x1310, 0x1318 - 0x1310 + 4, false);
|
|
}
|
|
|
|
end:
|
|
pr_notice("------------------------------------------------\n");
|
|
}
|
|
|
|
/* starts from the second status which is the begining of err status */
|
|
const static char *sc_irq_err_status[] = {
|
|
[ 0] = "illigal src color",
|
|
[ 1] = "illigal src Y base",
|
|
[ 2] = "illigal src Cb base",
|
|
[ 3] = "illigal src Cr base",
|
|
[ 4] = "illigal src Y span",
|
|
[ 5] = "illigal src C span",
|
|
[ 6] = "illigal src YH pos",
|
|
[ 7] = "illigal src YV pos",
|
|
[ 8] = "illigal src CH pos",
|
|
[ 9] = "illigal src CV pos",
|
|
[10] = "illigal src width",
|
|
[11] = "illigal src height",
|
|
[12] = "illigal dst color",
|
|
[13] = "illigal dst Y base",
|
|
[14] = "illigal dst Cb base",
|
|
[15] = "illigal dst Cr base",
|
|
[16] = "illigal dst Y span",
|
|
[17] = "illigal dst C span",
|
|
[18] = "illigal dst H pos",
|
|
[19] = "illigal dst V pos",
|
|
[20] = "illigal dst width",
|
|
[21] = "illigal dst height",
|
|
[23] = "illigal scaling ratio",
|
|
[25] = "illigal pre-scaler width/height",
|
|
[28] = "AXI Write Error Response",
|
|
[29] = "AXI Read Error Response",
|
|
[31] = "timeout",
|
|
};
|
|
|
|
static void sc_print_irq_err_status(struct sc_dev *sc, u32 status)
|
|
{
|
|
unsigned int i = 0;
|
|
|
|
status >>= 1; /* ignore the INT_STATUS_FRAME_END */
|
|
if (status) {
|
|
sc_hwregs_dump(sc);
|
|
if (sc->current_ctx)
|
|
sc_ctx_dump(sc->current_ctx);
|
|
|
|
while (status) {
|
|
if (status & 1)
|
|
dev_err(sc->dev,
|
|
"Scaler reported error %u: %s\n",
|
|
i + 1, sc_irq_err_status[i]);
|
|
i++;
|
|
status >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
u32 sc_hwget_and_clear_irq_status(struct sc_dev *sc)
|
|
{
|
|
u32 val = __raw_readl(sc->regs + SCALER_INT_STATUS);
|
|
sc_print_irq_err_status(sc, val);
|
|
__raw_writel(val, sc->regs + SCALER_INT_STATUS);
|
|
return val;
|
|
}
|