0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include "sun8i_ui_scaler.h"
0013 #include "sun8i_vi_scaler.h"
0014
0015 static const u32 lan2coefftab16[240] = {
0016 0x00004000, 0x00033ffe, 0x00063efc, 0x000a3bfb,
0017 0xff0f37fb, 0xfe1433fb, 0xfd192ffb, 0xfd1f29fb,
0018 0xfc2424fc, 0xfb291ffd, 0xfb2f19fd, 0xfb3314fe,
0019 0xfb370fff, 0xfb3b0a00, 0xfc3e0600, 0xfe3f0300,
0020
0021 0xff053804, 0xff083801, 0xff0a3700, 0xff0e34ff,
0022 0xff1232fd, 0xfe162ffd, 0xfd1b2cfc, 0xfd1f28fc,
0023 0xfd2323fd, 0xfc281ffd, 0xfc2c1bfd, 0xfd2f16fe,
0024 0xfd3212ff, 0xff340eff, 0x00360a00, 0x02370700,
0025
0026 0xff083207, 0xff0a3205, 0xff0d3103, 0xfe113001,
0027 0xfe142e00, 0xfe182bff, 0xfe1b29fe, 0xfe1f25fe,
0028 0xfe2222fe, 0xfe251ffe, 0xfe291bfe, 0xff2b18fe,
0029 0x002e14fe, 0x013010ff, 0x03310dff, 0x05310a00,
0030
0031 0xff0a2e09, 0xff0c2e07, 0xff0f2d05, 0xff122c03,
0032 0xfe152b02, 0xfe182901, 0xfe1b2700, 0xff1e24ff,
0033 0xff2121ff, 0xff241eff, 0x00261bff, 0x012818ff,
0034 0x022a15ff, 0x032c12ff, 0x052d0fff, 0x072d0c00,
0035
0036 0xff0c2a0b, 0xff0e2a09, 0xff102a07, 0xff132905,
0037 0xff162803, 0xff182702, 0xff1b2501, 0xff1e2300,
0038 0x00202000, 0x01221d00, 0x01251bff, 0x032618ff,
0039 0x042815ff, 0x052913ff, 0x072a10ff, 0x092a0d00,
0040
0041 0xff0d280c, 0xff0f280a, 0xff112808, 0xff142706,
0042 0xff162605, 0xff192503, 0x001b2302, 0x001d2201,
0043 0x011f1f01, 0x01221d00, 0x02231b00, 0x04241800,
0044 0x052616ff, 0x072713ff, 0x08271100, 0x0a280e00,
0045
0046 0xff0e260d, 0xff10260b, 0xff122609, 0xff142508,
0047 0x00152506, 0x00182305, 0x001b2203, 0x011d2002,
0048 0x011f1f01, 0x02201d01, 0x03221b00, 0x04231801,
0049 0x06241600, 0x08251300, 0x09261100, 0x0b260f00,
0050
0051 0xff0e250e, 0xff10250c, 0x0011250a, 0x00142408,
0052 0x00162307, 0x00182206, 0x011a2104, 0x011c2003,
0053 0x021e1e02, 0x03201c01, 0x04211a01, 0x05221801,
0054 0x07231600, 0x08241400, 0x0a241200, 0x0c241000,
0055
0056 0x000e240e, 0x0010240c, 0x0013230a, 0x00142309,
0057 0x00162208, 0x01182106, 0x011a2005, 0x021b1f04,
0058 0x031d1d03, 0x041e1c02, 0x05201a01, 0x06211801,
0059 0x07221601, 0x09231400, 0x0a231300, 0x0c231100,
0060
0061 0x000f220f, 0x0011220d, 0x0013220b, 0x0015210a,
0062 0x01162108, 0x01182007, 0x02191f06, 0x031a1e05,
0063 0x041c1c04, 0x051d1b03, 0x061f1902, 0x07201801,
0064 0x08211601, 0x0a211500, 0x0b221300, 0x0d221100,
0065
0066 0x0010210f, 0x0011210e, 0x0013210c, 0x0114200b,
0067 0x01161f0a, 0x02171f08, 0x03181e07, 0x031a1d06,
0068 0x041c1c04, 0x051d1a04, 0x071d1903, 0x081e1802,
0069 0x091f1602, 0x0b1f1501, 0x0c211300, 0x0e201200,
0070
0071 0x00102010, 0x0012200e, 0x0013200d, 0x01151f0b,
0072 0x01161f0a, 0x02171e09, 0x03191d07, 0x041a1c06,
0073 0x051b1b05, 0x061c1a04, 0x071d1903, 0x081e1703,
0074 0x0a1f1601, 0x0b1f1501, 0x0d201300, 0x0e201200,
0075
0076 0x00102010, 0x00121f0f, 0x00141f0d, 0x01141f0c,
0077 0x02161e0a, 0x03171d09, 0x03181d08, 0x041a1c06,
0078 0x051b1b05, 0x061c1a04, 0x081c1903, 0x091d1703,
0079 0x0a1e1602, 0x0c1e1501, 0x0d1f1400, 0x0e1f1201,
0080
0081 0x00111e11, 0x00131e0f, 0x01131e0e, 0x02151d0c,
0082 0x02161d0b, 0x03171c0a, 0x04181b09, 0x05191b07,
0083 0x061a1a06, 0x071b1905, 0x091b1804, 0x0a1c1703,
0084 0x0b1d1602, 0x0c1d1502, 0x0e1d1401, 0x0f1e1300,
0085
0086 0x00111e11, 0x00131d10, 0x01141d0e, 0x02151c0d,
0087 0x03161c0b, 0x04171b0a, 0x05171b09, 0x06181a08,
0088 0x07191907, 0x081a1806, 0x091a1805, 0x0a1b1704,
0089 0x0b1c1603, 0x0d1c1502, 0x0e1d1401, 0x0f1d1301,
0090 };
0091
0092 static u32 sun8i_ui_scaler_base(struct sun8i_mixer *mixer, int channel)
0093 {
0094 int vi_num = mixer->cfg->vi_num;
0095
0096 if (mixer->cfg->is_de3)
0097 return DE3_VI_SCALER_UNIT_BASE +
0098 DE3_VI_SCALER_UNIT_SIZE * vi_num +
0099 DE3_UI_SCALER_UNIT_SIZE * (channel - vi_num);
0100 else
0101 return DE2_VI_SCALER_UNIT_BASE +
0102 DE2_VI_SCALER_UNIT_SIZE * vi_num +
0103 DE2_UI_SCALER_UNIT_SIZE * (channel - vi_num);
0104 }
0105
0106 static int sun8i_ui_scaler_coef_index(unsigned int step)
0107 {
0108 unsigned int scale, int_part, float_part;
0109
0110 scale = step >> (SUN8I_UI_SCALER_SCALE_FRAC - 3);
0111 int_part = scale >> 3;
0112 float_part = scale & 0x7;
0113
0114 switch (int_part) {
0115 case 0:
0116 return 0;
0117 case 1:
0118 return float_part;
0119 case 2:
0120 return 8 + (float_part >> 1);
0121 case 3:
0122 return 12;
0123 case 4:
0124 return 13;
0125 default:
0126 return 14;
0127 }
0128 }
0129
0130 void sun8i_ui_scaler_enable(struct sun8i_mixer *mixer, int layer, bool enable)
0131 {
0132 u32 val, base;
0133
0134 if (WARN_ON(layer < mixer->cfg->vi_num))
0135 return;
0136
0137 base = sun8i_ui_scaler_base(mixer, layer);
0138
0139 if (enable)
0140 val = SUN8I_SCALER_GSU_CTRL_EN |
0141 SUN8I_SCALER_GSU_CTRL_COEFF_RDY;
0142 else
0143 val = 0;
0144
0145 regmap_write(mixer->engine.regs, SUN8I_SCALER_GSU_CTRL(base), val);
0146 }
0147
0148 void sun8i_ui_scaler_setup(struct sun8i_mixer *mixer, int layer,
0149 u32 src_w, u32 src_h, u32 dst_w, u32 dst_h,
0150 u32 hscale, u32 vscale, u32 hphase, u32 vphase)
0151 {
0152 u32 insize, outsize;
0153 int i, offset;
0154 u32 base;
0155
0156 if (WARN_ON(layer < mixer->cfg->vi_num))
0157 return;
0158
0159 base = sun8i_ui_scaler_base(mixer, layer);
0160
0161 hphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
0162 vphase <<= SUN8I_UI_SCALER_PHASE_FRAC - 16;
0163 hscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16;
0164 vscale <<= SUN8I_UI_SCALER_SCALE_FRAC - 16;
0165
0166 insize = SUN8I_UI_SCALER_SIZE(src_w, src_h);
0167 outsize = SUN8I_UI_SCALER_SIZE(dst_w, dst_h);
0168
0169 regmap_write(mixer->engine.regs,
0170 SUN8I_SCALER_GSU_OUTSIZE(base), outsize);
0171 regmap_write(mixer->engine.regs,
0172 SUN8I_SCALER_GSU_INSIZE(base), insize);
0173 regmap_write(mixer->engine.regs,
0174 SUN8I_SCALER_GSU_HSTEP(base), hscale);
0175 regmap_write(mixer->engine.regs,
0176 SUN8I_SCALER_GSU_VSTEP(base), vscale);
0177 regmap_write(mixer->engine.regs,
0178 SUN8I_SCALER_GSU_HPHASE(base), hphase);
0179 regmap_write(mixer->engine.regs,
0180 SUN8I_SCALER_GSU_VPHASE(base), vphase);
0181 offset = sun8i_ui_scaler_coef_index(hscale) *
0182 SUN8I_UI_SCALER_COEFF_COUNT;
0183 for (i = 0; i < SUN8I_UI_SCALER_COEFF_COUNT; i++)
0184 regmap_write(mixer->engine.regs,
0185 SUN8I_SCALER_GSU_HCOEFF(base, i),
0186 lan2coefftab16[offset + i]);
0187 }