1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4 
5 #include "spl_debug.h"
6 #include "dc_spl_filters.h"
7 #include "dc_spl_isharp_filters.h"
8 
9 //========================================
10 // Delta Gain 1DLUT
11 // LUT content is packed as 4-bytes into one DWORD/entry
12 // A_start = 0.000000
13 // A_end   = 10.000000
14 // A_gain  = 2.000000
15 // B_start = 11.000000
16 // B_end   = 86.000000
17 // C_start = 40.000000
18 // C_end   = 64.000000
19 //========================================
20 static const uint32_t filter_isharp_1D_lut_0[ISHARP_LUT_TABLE_SIZE] = {
21 0x02010000,
22 0x0A070503,
23 0x1614100D,
24 0x1C1B1918,
25 0x22211F1E,
26 0x27262423,
27 0x2A2A2928,
28 0x2D2D2C2B,
29 0x302F2F2E,
30 0x31313030,
31 0x31313131,
32 0x31313131,
33 0x30303031,
34 0x292D2F2F,
35 0x191D2125,
36 0x050A0F14,
37 0x00000000,
38 0x00000000,
39 0x00000000,
40 0x00000000,
41 0x00000000,
42 0x00000000,
43 0x00000000,
44 0x00000000,
45 0x00000000,
46 0x00000000,
47 0x00000000,
48 0x00000000,
49 0x00000000,
50 0x00000000,
51 0x00000000,
52 0x00000000,
53 };
54 //========================================
55 // Delta Gain 1DLUT
56 // LUT content is packed as 4-bytes into one DWORD/entry
57 // A_start = 0.000000
58 // A_end   = 10.000000
59 // A_gain  = 0.500000
60 // B_start = 11.000000
61 // B_end   = 127.000000
62 // C_start = 96.000000
63 // C_end   = 127.000000
64 //========================================
65 
66 static const uint32_t filter_isharp_1D_lut_0p5x[ISHARP_LUT_TABLE_SIZE] = {
67 0x00000000,
68 0x02020101,
69 0x06050403,
70 0x07070606,
71 0x09080808,
72 0x0A0A0A09,
73 0x0C0B0B0B,
74 0x0D0D0C0C,
75 0x0E0E0D0D,
76 0x0F0F0E0E,
77 0x100F0F0F,
78 0x10101010,
79 0x11111010,
80 0x11111111,
81 0x11111111,
82 0x11111111,
83 0x11111111,
84 0x11111111,
85 0x11111111,
86 0x10101111,
87 0x10101010,
88 0x0F0F0F10,
89 0x0E0E0F0F,
90 0x0D0D0E0E,
91 0x0C0C0D0D,
92 0x0B0B0B0C,
93 0x090A0A0A,
94 0x08080809,
95 0x06060707,
96 0x04050506,
97 0x02030304,
98 0x00010102,
99 };
100 //========================================
101 // Delta Gain 1DLUT
102 // LUT content is packed as 4-bytes into one DWORD/entry
103 // A_start = 0.000000
104 // A_end   = 10.000000
105 // A_gain  = 1.000000
106 // B_start = 11.000000
107 // B_end   = 127.000000
108 // C_start = 96.000000
109 // C_end   = 127.000000
110 //========================================
111 static const uint32_t filter_isharp_1D_lut_1p0x[ISHARP_LUT_TABLE_SIZE] = {
112 0x01000000,
113 0x05040302,
114 0x0B0A0806,
115 0x0E0E0D0C,
116 0x1211100F,
117 0x15141312,
118 0x17171615,
119 0x1A191918,
120 0x1C1B1B1A,
121 0x1E1D1D1C,
122 0x1F1F1E1E,
123 0x2020201F,
124 0x21212121,
125 0x22222222,
126 0x23232222,
127 0x23232323,
128 0x23232323,
129 0x22222323,
130 0x22222222,
131 0x21212121,
132 0x1F202020,
133 0x1E1E1F1F,
134 0x1C1D1D1E,
135 0x1A1B1B1C,
136 0x1819191A,
137 0x15161717,
138 0x12131415,
139 0x0F101112,
140 0x0C0D0E0E,
141 0x08090A0B,
142 0x04050607,
143 0x00010203,
144 };
145 //========================================
146 // Delta Gain 1DLUT
147 // LUT content is packed as 4-bytes into one DWORD/entry
148 // A_start = 0.000000
149 // A_end   = 10.000000
150 // A_gain  = 1.500000
151 // B_start = 11.000000
152 // B_end   = 127.000000
153 // C_start = 96.000000
154 // C_end   = 127.000000
155 //========================================
156 static const uint32_t filter_isharp_1D_lut_1p5x[ISHARP_LUT_TABLE_SIZE] = {
157 0x01010000,
158 0x07050402,
159 0x110F0C0A,
160 0x16141312,
161 0x1B191817,
162 0x1F1E1D1C,
163 0x23222120,
164 0x26262524,
165 0x2A292827,
166 0x2C2C2B2A,
167 0x2F2E2E2D,
168 0x3130302F,
169 0x32323131,
170 0x33333332,
171 0x34343433,
172 0x34343434,
173 0x34343434,
174 0x33343434,
175 0x32333333,
176 0x31313232,
177 0x2F303031,
178 0x2D2E2E2F,
179 0x2A2B2C2C,
180 0x2728292A,
181 0x24252626,
182 0x20212223,
183 0x1C1D1E1F,
184 0x1718191B,
185 0x12131416,
186 0x0C0E0F10,
187 0x0608090B,
188 0x00020305
189 };
190 //========================================
191 // Delta Gain 1DLUT
192 // LUT content is packed as 4-bytes into one DWORD/entry
193 // A_start = 0.000000
194 // A_end   = 10.000000
195 // A_gain  = 2.000000
196 // B_start = 11.000000
197 // B_end   = 127.000000
198 // C_start = 40.000000
199 // C_end   = 127.000000
200 //========================================
201 static const uint32_t filter_isharp_1D_lut_2p0x[ISHARP_LUT_TABLE_SIZE] = {
202 0x02010000,
203 0x0A070503,
204 0x1614100D,
205 0x1D1B1A18,
206 0x2322201F,
207 0x29282625,
208 0x2F2D2C2B,
209 0x33323130,
210 0x38373534,
211 0x3B3A3938,
212 0x3E3E3D3C,
213 0x4140403F,
214 0x43424241,
215 0x44444443,
216 0x45454545,
217 0x46454545,
218 0x45454546,
219 0x45454545,
220 0x43444444,
221 0x41424243,
222 0x3F404041,
223 0x3C3D3E3E,
224 0x38393A3B,
225 0x34353738,
226 0x30313233,
227 0x2B2C2D2F,
228 0x25262829,
229 0x1F202223,
230 0x181A1B1D,
231 0x10121416,
232 0x080B0D0E,
233 0x00020406,
234 };
235 //========================================
236 // Delta Gain 1DLUT
237 // LUT content is packed as 4-bytes into one DWORD/entry
238 // A_start = 0.000000
239 // A_end   = 10.000000
240 // A_gain  = 3.000000
241 // B_start = 11.000000
242 // B_end   = 127.000000
243 // C_start = 40.000000
244 // C_end   = 127.000000
245 //========================================
246 static const uint32_t filter_isharp_1D_lut_3p0x[ISHARP_LUT_TABLE_SIZE] = {
247 0x03010000,
248 0x0F0B0805,
249 0x211E1813,
250 0x2B292624,
251 0x3533302E,
252 0x3E3C3A37,
253 0x46444240,
254 0x4D4B4A48,
255 0x5352504F,
256 0x59575655,
257 0x5D5C5B5A,
258 0x61605F5E,
259 0x64646362,
260 0x66666565,
261 0x68686767,
262 0x68686868,
263 0x68686868,
264 0x67676868,
265 0x65656666,
266 0x62636464,
267 0x5E5F6061,
268 0x5A5B5C5D,
269 0x55565759,
270 0x4F505253,
271 0x484A4B4D,
272 0x40424446,
273 0x373A3C3E,
274 0x2E303335,
275 0x2426292B,
276 0x191B1E21,
277 0x0D101316,
278 0x0003060A,
279 };
280 
281 //========================================
282 // Wide scaler coefficients
283 //========================================================
284 // <using>			gen_scaler_coeffs.m
285 // <date>			15-Dec-2021
286 // <coeffDescrip>	6t_64p_LanczosEd_p_1_p_10qb_
287 // <num_taps>		6
288 // <num_phases>		64
289 // <CoefType>		LanczosEd
290 // <CoefQuant>		S1.10
291 //========================================================
292 static const uint16_t filter_isharp_wide_6tap_64p[198] = {
293 0x0000, 0x0000, 0x0400, 0x0000, 0x0000, 0x0000,
294 0x0003, 0x0FF3, 0x0400, 0x000D, 0x0FFD, 0x0000,
295 0x0006, 0x0FE7, 0x03FE, 0x001C, 0x0FF9, 0x0000,
296 0x0009, 0x0FDB, 0x03FC, 0x002B, 0x0FF5, 0x0000,
297 0x000C, 0x0FD0, 0x03F9, 0x003A, 0x0FF1, 0x0000,
298 0x000E, 0x0FC5, 0x03F5, 0x004A, 0x0FED, 0x0001,
299 0x0011, 0x0FBB, 0x03F0, 0x005A, 0x0FE9, 0x0001,
300 0x0013, 0x0FB2, 0x03EB, 0x006A, 0x0FE5, 0x0001,
301 0x0015, 0x0FA9, 0x03E4, 0x007B, 0x0FE1, 0x0002,
302 0x0017, 0x0FA1, 0x03DD, 0x008D, 0x0FDC, 0x0002,
303 0x0018, 0x0F99, 0x03D4, 0x00A0, 0x0FD8, 0x0003,
304 0x001A, 0x0F92, 0x03CB, 0x00B2, 0x0FD3, 0x0004,
305 0x001B, 0x0F8C, 0x03C1, 0x00C6, 0x0FCE, 0x0004,
306 0x001C, 0x0F86, 0x03B7, 0x00D9, 0x0FC9, 0x0005,
307 0x001D, 0x0F80, 0x03AB, 0x00EE, 0x0FC4, 0x0006,
308 0x001E, 0x0F7C, 0x039F, 0x0101, 0x0FBF, 0x0007,
309 0x001F, 0x0F78, 0x0392, 0x0115, 0x0FBA, 0x0008,
310 0x001F, 0x0F74, 0x0385, 0x012B, 0x0FB5, 0x0008,
311 0x0020, 0x0F71, 0x0376, 0x0140, 0x0FB0, 0x0009,
312 0x0020, 0x0F6E, 0x0367, 0x0155, 0x0FAB, 0x000B,
313 0x0020, 0x0F6C, 0x0357, 0x016B, 0x0FA6, 0x000C,
314 0x0020, 0x0F6A, 0x0347, 0x0180, 0x0FA2, 0x000D,
315 0x0020, 0x0F69, 0x0336, 0x0196, 0x0F9D, 0x000E,
316 0x0020, 0x0F69, 0x0325, 0x01AB, 0x0F98, 0x000F,
317 0x001F, 0x0F68, 0x0313, 0x01C3, 0x0F93, 0x0010,
318 0x001F, 0x0F69, 0x0300, 0x01D8, 0x0F8F, 0x0011,
319 0x001E, 0x0F69, 0x02ED, 0x01EF, 0x0F8B, 0x0012,
320 0x001D, 0x0F6A, 0x02D9, 0x0205, 0x0F87, 0x0014,
321 0x001D, 0x0F6C, 0x02C5, 0x021A, 0x0F83, 0x0015,
322 0x001C, 0x0F6E, 0x02B1, 0x0230, 0x0F7F, 0x0016,
323 0x001B, 0x0F70, 0x029C, 0x0247, 0x0F7B, 0x0017,
324 0x001A, 0x0F72, 0x0287, 0x025D, 0x0F78, 0x0018,
325 0x0019, 0x0F75, 0x0272, 0x0272, 0x0F75, 0x0019
326 };
327 // Blur and scale coefficients
328 //========================================================
329 // <using>			gen_BlurScale_coeffs.m
330 // <date>			25-Apr-2022
331 // <num_taps>		4
332 // <num_phases>		64
333 // <CoefType>		Blur & Scale LPF
334 // <CoefQuant>		S1.10
335 //========================================================
336 static const uint16_t filter_isharp_bs_4tap_in_6_64p[198] = {
337 0x0000, 0x00E5, 0x0237, 0x00E4, 0x0000, 0x0000,
338 0x0000, 0x00DE, 0x0237, 0x00EB, 0x0000, 0x0000,
339 0x0000, 0x00D7, 0x0236, 0x00F2, 0x0001, 0x0000,
340 0x0000, 0x00D0, 0x0235, 0x00FA, 0x0001, 0x0000,
341 0x0000, 0x00C9, 0x0234, 0x0101, 0x0002, 0x0000,
342 0x0000, 0x00C2, 0x0233, 0x0108, 0x0003, 0x0000,
343 0x0000, 0x00BB, 0x0232, 0x0110, 0x0003, 0x0000,
344 0x0000, 0x00B5, 0x0230, 0x0117, 0x0004, 0x0000,
345 0x0000, 0x00AE, 0x022E, 0x011F, 0x0005, 0x0000,
346 0x0000, 0x00A8, 0x022C, 0x0126, 0x0006, 0x0000,
347 0x0000, 0x00A2, 0x022A, 0x012D, 0x0007, 0x0000,
348 0x0000, 0x009C, 0x0228, 0x0134, 0x0008, 0x0000,
349 0x0000, 0x0096, 0x0225, 0x013C, 0x0009, 0x0000,
350 0x0000, 0x0090, 0x0222, 0x0143, 0x000B, 0x0000,
351 0x0000, 0x008A, 0x021F, 0x014B, 0x000C, 0x0000,
352 0x0000, 0x0085, 0x021C, 0x0151, 0x000E, 0x0000,
353 0x0000, 0x007F, 0x0218, 0x015A, 0x000F, 0x0000,
354 0x0000, 0x007A, 0x0215, 0x0160, 0x0011, 0x0000,
355 0x0000, 0x0074, 0x0211, 0x0168, 0x0013, 0x0000,
356 0x0000, 0x006F, 0x020D, 0x016F, 0x0015, 0x0000,
357 0x0000, 0x006A, 0x0209, 0x0176, 0x0017, 0x0000,
358 0x0000, 0x0065, 0x0204, 0x017E, 0x0019, 0x0000,
359 0x0000, 0x0060, 0x0200, 0x0185, 0x001B, 0x0000,
360 0x0000, 0x005C, 0x01FB, 0x018C, 0x001D, 0x0000,
361 0x0000, 0x0057, 0x01F6, 0x0193, 0x0020, 0x0000,
362 0x0000, 0x0053, 0x01F1, 0x019A, 0x0022, 0x0000,
363 0x0000, 0x004E, 0x01EC, 0x01A1, 0x0025, 0x0000,
364 0x0000, 0x004A, 0x01E6, 0x01A8, 0x0028, 0x0000,
365 0x0000, 0x0046, 0x01E1, 0x01AF, 0x002A, 0x0000,
366 0x0000, 0x0042, 0x01DB, 0x01B6, 0x002D, 0x0000,
367 0x0000, 0x003F, 0x01D5, 0x01BB, 0x0031, 0x0000,
368 0x0000, 0x003B, 0x01CF, 0x01C2, 0x0034, 0x0000,
369 0x0000, 0x0037, 0x01C9, 0x01C9, 0x0037, 0x0000
370 };
371 //========================================================
372 // <using>			gen_BlurScale_coeffs.m
373 // <date>			25-Apr-2022
374 // <num_taps>		4
375 // <num_phases>		64
376 // <CoefType>		Blur & Scale LPF
377 // <CoefQuant>		S1.10
378 //========================================================
379 static const uint16_t filter_isharp_bs_4tap_64p[132] = {
380 0x00E5, 0x0237, 0x00E4, 0x0000,
381 0x00DE, 0x0237, 0x00EB, 0x0000,
382 0x00D7, 0x0236, 0x00F2, 0x0001,
383 0x00D0, 0x0235, 0x00FA, 0x0001,
384 0x00C9, 0x0234, 0x0101, 0x0002,
385 0x00C2, 0x0233, 0x0108, 0x0003,
386 0x00BB, 0x0232, 0x0110, 0x0003,
387 0x00B5, 0x0230, 0x0117, 0x0004,
388 0x00AE, 0x022E, 0x011F, 0x0005,
389 0x00A8, 0x022C, 0x0126, 0x0006,
390 0x00A2, 0x022A, 0x012D, 0x0007,
391 0x009C, 0x0228, 0x0134, 0x0008,
392 0x0096, 0x0225, 0x013C, 0x0009,
393 0x0090, 0x0222, 0x0143, 0x000B,
394 0x008A, 0x021F, 0x014B, 0x000C,
395 0x0085, 0x021C, 0x0151, 0x000E,
396 0x007F, 0x0218, 0x015A, 0x000F,
397 0x007A, 0x0215, 0x0160, 0x0011,
398 0x0074, 0x0211, 0x0168, 0x0013,
399 0x006F, 0x020D, 0x016F, 0x0015,
400 0x006A, 0x0209, 0x0176, 0x0017,
401 0x0065, 0x0204, 0x017E, 0x0019,
402 0x0060, 0x0200, 0x0185, 0x001B,
403 0x005C, 0x01FB, 0x018C, 0x001D,
404 0x0057, 0x01F6, 0x0193, 0x0020,
405 0x0053, 0x01F1, 0x019A, 0x0022,
406 0x004E, 0x01EC, 0x01A1, 0x0025,
407 0x004A, 0x01E6, 0x01A8, 0x0028,
408 0x0046, 0x01E1, 0x01AF, 0x002A,
409 0x0042, 0x01DB, 0x01B6, 0x002D,
410 0x003F, 0x01D5, 0x01BB, 0x0031,
411 0x003B, 0x01CF, 0x01C2, 0x0034,
412 0x0037, 0x01C9, 0x01C9, 0x0037,
413 };
414 //========================================================
415 // <using>			gen_BlurScale_coeffs.m
416 // <date>			09-Jun-2022
417 // <num_taps>		3
418 // <num_phases>		64
419 // <CoefType>		Blur & Scale LPF
420 // <CoefQuant>		S1.10
421 //========================================================
422 static const uint16_t filter_isharp_bs_3tap_64p[99] = {
423 0x0200, 0x0200, 0x0000,
424 0x01F6, 0x0206, 0x0004,
425 0x01EC, 0x020B, 0x0009,
426 0x01E2, 0x0211, 0x000D,
427 0x01D8, 0x0216, 0x0012,
428 0x01CE, 0x021C, 0x0016,
429 0x01C4, 0x0221, 0x001B,
430 0x01BA, 0x0226, 0x0020,
431 0x01B0, 0x022A, 0x0026,
432 0x01A6, 0x022F, 0x002B,
433 0x019C, 0x0233, 0x0031,
434 0x0192, 0x0238, 0x0036,
435 0x0188, 0x023C, 0x003C,
436 0x017E, 0x0240, 0x0042,
437 0x0174, 0x0244, 0x0048,
438 0x016A, 0x0248, 0x004E,
439 0x0161, 0x024A, 0x0055,
440 0x0157, 0x024E, 0x005B,
441 0x014D, 0x0251, 0x0062,
442 0x0144, 0x0253, 0x0069,
443 0x013A, 0x0256, 0x0070,
444 0x0131, 0x0258, 0x0077,
445 0x0127, 0x025B, 0x007E,
446 0x011E, 0x025C, 0x0086,
447 0x0115, 0x025E, 0x008D,
448 0x010B, 0x0260, 0x0095,
449 0x0102, 0x0262, 0x009C,
450 0x00F9, 0x0263, 0x00A4,
451 0x00F0, 0x0264, 0x00AC,
452 0x00E7, 0x0265, 0x00B4,
453 0x00DF, 0x0264, 0x00BD,
454 0x00D6, 0x0265, 0x00C5,
455 0x00CD, 0x0266, 0x00CD,
456 };
457 
458 /* Converted Blur & Scale coeff tables from S1.10 to S1.12 */
459 static uint16_t filter_isharp_bs_4tap_in_6_64p_s1_12[198];
460 static uint16_t filter_isharp_bs_4tap_64p_s1_12[132];
461 static uint16_t filter_isharp_bs_3tap_64p_s1_12[99];
462 
463 /* Pre-generated 1DLUT for given setup and sharpness level */
464 struct isharp_1D_lut_pregen filter_isharp_1D_lut_pregen[NUM_SHARPNESS_SETUPS] = {
465 	{
466 		0, 0,
467 		{
468 			0, 0, 0, 0, 0, 0, 0, 0,
469 			0, 0, 0, 0, 0, 0, 0, 0,
470 			0, 0, 0, 0, 0, 0, 0, 0,
471 			0, 0, 0, 0, 0, 0, 0, 0,
472 		}
473 	},
474 	{
475 		0, 0,
476 		{
477 			0, 0, 0, 0, 0, 0, 0, 0,
478 			0, 0, 0, 0, 0, 0, 0, 0,
479 			0, 0, 0, 0, 0, 0, 0, 0,
480 			0, 0, 0, 0, 0, 0, 0, 0,
481 		}
482 	},
483 	{
484 		0, 0,
485 		{
486 			0, 0, 0, 0, 0, 0, 0, 0,
487 			0, 0, 0, 0, 0, 0, 0, 0,
488 			0, 0, 0, 0, 0, 0, 0, 0,
489 			0, 0, 0, 0, 0, 0, 0, 0,
490 		}
491 	},
492 	{
493 		0, 0,
494 		{
495 			0, 0, 0, 0, 0, 0, 0, 0,
496 			0, 0, 0, 0, 0, 0, 0, 0,
497 			0, 0, 0, 0, 0, 0, 0, 0,
498 			0, 0, 0, 0, 0, 0, 0, 0,
499 		}
500 	},
501 };
502 
503 struct scale_ratio_to_sharpness_level_adj sharpness_level_adj[NUM_SHARPNESS_ADJ_LEVELS] = {
504 	{1125, 1000, 0},
505 	{11, 10, 1},
506 	{1075, 1000, 2},
507 	{105, 100, 3},
508 	{1025, 1000, 4},
509 	{1, 1, 5},
510 };
511 
spl_get_filter_isharp_1D_lut_0(void)512 const uint32_t *spl_get_filter_isharp_1D_lut_0(void)
513 {
514 	return filter_isharp_1D_lut_0;
515 }
spl_get_filter_isharp_1D_lut_0p5x(void)516 const uint32_t *spl_get_filter_isharp_1D_lut_0p5x(void)
517 {
518 	return filter_isharp_1D_lut_0p5x;
519 }
spl_get_filter_isharp_1D_lut_1p0x(void)520 const uint32_t *spl_get_filter_isharp_1D_lut_1p0x(void)
521 {
522 	return filter_isharp_1D_lut_1p0x;
523 }
spl_get_filter_isharp_1D_lut_1p5x(void)524 const uint32_t *spl_get_filter_isharp_1D_lut_1p5x(void)
525 {
526 	return filter_isharp_1D_lut_1p5x;
527 }
spl_get_filter_isharp_1D_lut_2p0x(void)528 const uint32_t *spl_get_filter_isharp_1D_lut_2p0x(void)
529 {
530 	return filter_isharp_1D_lut_2p0x;
531 }
spl_get_filter_isharp_1D_lut_3p0x(void)532 const uint32_t *spl_get_filter_isharp_1D_lut_3p0x(void)
533 {
534 	return filter_isharp_1D_lut_3p0x;
535 }
spl_get_filter_isharp_wide_6tap_64p(void)536 const uint16_t *spl_get_filter_isharp_wide_6tap_64p(void)
537 {
538 	return filter_isharp_wide_6tap_64p;
539 }
spl_get_filter_isharp_bs_4tap_in_6_64p(void)540 uint16_t *spl_get_filter_isharp_bs_4tap_in_6_64p(void)
541 {
542 	return filter_isharp_bs_4tap_in_6_64p_s1_12;
543 }
spl_get_filter_isharp_bs_4tap_64p(void)544 uint16_t *spl_get_filter_isharp_bs_4tap_64p(void)
545 {
546 	return filter_isharp_bs_4tap_64p_s1_12;
547 }
spl_get_filter_isharp_bs_3tap_64p(void)548 uint16_t *spl_get_filter_isharp_bs_3tap_64p(void)
549 {
550 	return filter_isharp_bs_3tap_64p_s1_12;
551 }
552 
spl_calculate_sharpness_level_adj(struct spl_fixed31_32 ratio)553 static unsigned int spl_calculate_sharpness_level_adj(struct spl_fixed31_32 ratio)
554 {
555 	int j;
556 	struct spl_fixed31_32 ratio_level;
557 	struct scale_ratio_to_sharpness_level_adj *lookup_ptr;
558 	unsigned int sharpness_level_down_adj;
559 
560 	/*
561 	 * Adjust sharpness level based on current scaling ratio
562 	 *
563 	 * We have 5 discrete scaling ratios which we will use to adjust the
564 	 *  sharpness level down by 1 as we pass each ratio.  The ratios
565 	 *  are
566 	 *
567 	 * 1.125 upscale and higher - no adj
568 	 * 1.100 - under 1.125 - adj level down 1
569 	 * 1.075 - under 1.100 - adj level down 2
570 	 * 1.050 - under 1.075 - adj level down 3
571 	 * 1.025 - under 1.050 - adj level down 4
572 	 * 1.000 - under 1.025 - adj level down 5
573 	 *
574 	 */
575 	j = 0;
576 	sharpness_level_down_adj = 0;
577 	lookup_ptr = sharpness_level_adj;
578 	while (j < NUM_SHARPNESS_ADJ_LEVELS) {
579 		ratio_level = spl_fixpt_from_fraction(lookup_ptr->ratio_numer,
580 			lookup_ptr->ratio_denom);
581 		if (ratio.value >= ratio_level.value) {
582 			sharpness_level_down_adj = lookup_ptr->level_down_adj;
583 			break;
584 		}
585 		lookup_ptr++;
586 		j++;
587 	}
588 	return sharpness_level_down_adj;
589 }
590 
spl_calculate_sharpness_level(struct spl_fixed31_32 ratio,int discrete_sharpness_level,enum system_setup setup,struct spl_sharpness_range sharpness_range,enum scale_to_sharpness_policy scale_to_sharpness_policy)591 static unsigned int spl_calculate_sharpness_level(struct spl_fixed31_32 ratio,
592 		int discrete_sharpness_level, enum system_setup setup,
593 		struct spl_sharpness_range sharpness_range,
594 		enum scale_to_sharpness_policy scale_to_sharpness_policy)
595 {
596 	unsigned int sharpness_level = 0;
597 	unsigned int sharpness_level_down_adj = 0;
598 
599 	int min_sharpness, max_sharpness, mid_sharpness;
600 
601 	/*
602 	 * Adjust sharpness level if policy requires we adjust it based on
603 	 *  scale ratio.  Based on scale ratio, we may adjust the sharpness
604 	 *  level down by a certain number of steps.  We will not select
605 	 *  a sharpness value of 0 so the lowest sharpness level will be
606 	 *  0 or 1 depending on what the min_sharpness is
607 	 *
608 	 * If the policy is no required, this code maybe removed at a later
609 	 *  date
610 	 */
611 	switch (setup) {
612 
613 	case HDR_L:
614 		min_sharpness = sharpness_range.hdr_rgb_min;
615 		max_sharpness = sharpness_range.hdr_rgb_max;
616 		mid_sharpness = sharpness_range.hdr_rgb_mid;
617 		if (scale_to_sharpness_policy == SCALE_TO_SHARPNESS_ADJ_ALL)
618 			sharpness_level_down_adj = spl_calculate_sharpness_level_adj(ratio);
619 		break;
620 	case HDR_NL:
621 		/* currently no use case, use Non-linear SDR values for now */
622 	case SDR_NL:
623 		min_sharpness = sharpness_range.sdr_yuv_min;
624 		max_sharpness = sharpness_range.sdr_yuv_max;
625 		mid_sharpness = sharpness_range.sdr_yuv_mid;
626 		if (scale_to_sharpness_policy >= SCALE_TO_SHARPNESS_ADJ_YUV)
627 			sharpness_level_down_adj = spl_calculate_sharpness_level_adj(ratio);
628 		break;
629 	case SDR_L:
630 	default:
631 		min_sharpness = sharpness_range.sdr_rgb_min;
632 		max_sharpness = sharpness_range.sdr_rgb_max;
633 		mid_sharpness = sharpness_range.sdr_rgb_mid;
634 		if (scale_to_sharpness_policy == SCALE_TO_SHARPNESS_ADJ_ALL)
635 			sharpness_level_down_adj = spl_calculate_sharpness_level_adj(ratio);
636 		break;
637 	}
638 
639 	if ((min_sharpness == 0) && (sharpness_level_down_adj >= discrete_sharpness_level))
640 		discrete_sharpness_level = 1;
641 	else if (sharpness_level_down_adj >= discrete_sharpness_level)
642 		discrete_sharpness_level = 0;
643 	else
644 		discrete_sharpness_level -= sharpness_level_down_adj;
645 
646 	int lower_half_step_size = (mid_sharpness - min_sharpness) / 5;
647 	int upper_half_step_size = (max_sharpness - mid_sharpness) / 5;
648 
649 	// lower half linear approximation
650 	if (discrete_sharpness_level < 5)
651 		sharpness_level = min_sharpness + (lower_half_step_size * discrete_sharpness_level);
652 	// upper half linear approximation
653 	else
654 		sharpness_level = mid_sharpness + (upper_half_step_size * (discrete_sharpness_level - 5));
655 
656 	return sharpness_level;
657 }
658 
spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio,enum system_setup setup,struct adaptive_sharpness sharpness,enum scale_to_sharpness_policy scale_to_sharpness_policy)659 void spl_build_isharp_1dlut_from_reference_curve(struct spl_fixed31_32 ratio, enum system_setup setup,
660 	struct adaptive_sharpness sharpness, enum scale_to_sharpness_policy scale_to_sharpness_policy)
661 {
662 	uint8_t *byte_ptr_1dlut_src, *byte_ptr_1dlut_dst;
663 	struct spl_fixed31_32 sharp_base, sharp_calc, sharp_level;
664 	int j;
665 	int size_1dlut;
666 	int sharp_calc_int;
667 	uint32_t filter_pregen_store[ISHARP_LUT_TABLE_SIZE];
668 
669 	/* Custom sharpnessX1000 value */
670 	unsigned int sharpnessX1000 = spl_calculate_sharpness_level(ratio,
671 			sharpness.sharpness_level, setup,
672 			sharpness.sharpness_range, scale_to_sharpness_policy);
673 	sharp_level = spl_fixpt_from_fraction(sharpnessX1000, 1000);
674 
675 	/*
676 	 * Check if pregen 1dlut table is already precalculated
677 	 * If numer/denom is different, then recalculate
678 	 */
679 	if ((filter_isharp_1D_lut_pregen[setup].sharpness_numer == sharpnessX1000) &&
680 		(filter_isharp_1D_lut_pregen[setup].sharpness_denom == 1000))
681 		return;
682 
683 	/*
684 	 * Calculate LUT_128_gained with this equation:
685 	 *
686 	 * LUT_128_gained[i] = (uint8)(0.5 + min(255,(double)(LUT_128[i])*sharpLevel/iGain))
687 	 *  where LUT_128[i] is contents of 3p0x isharp 1dlut
688 	 *  where sharpLevel is desired sharpness level
689 	 *  where iGain is base sharpness level 3.0
690 	 *  where LUT_128_gained[i] is adjusted 1dlut value based on desired sharpness level
691 	 */
692 	byte_ptr_1dlut_src = (uint8_t *)filter_isharp_1D_lut_3p0x;
693 	byte_ptr_1dlut_dst = (uint8_t *)filter_pregen_store;
694 	size_1dlut = sizeof(filter_isharp_1D_lut_3p0x);
695 	memset(byte_ptr_1dlut_dst, 0, size_1dlut);
696 	for (j = 0; j < size_1dlut; j++) {
697 		sharp_base = spl_fixpt_from_int((int)*byte_ptr_1dlut_src);
698 		sharp_calc = spl_fixpt_mul(sharp_base, sharp_level);
699 		sharp_calc = spl_fixpt_div(sharp_calc, spl_fixpt_from_int(3));
700 		sharp_calc = spl_fixpt_min(spl_fixpt_from_int(255), sharp_calc);
701 		sharp_calc = spl_fixpt_add(sharp_calc, spl_fixpt_from_fraction(1, 2));
702 		sharp_calc_int = spl_fixpt_floor(sharp_calc);
703 		/* Clamp it at 0x7F so it doesn't wrap */
704 		if (sharp_calc_int > 127)
705 			sharp_calc_int = 127;
706 		*byte_ptr_1dlut_dst = (uint8_t)sharp_calc_int;
707 
708 		byte_ptr_1dlut_src++;
709 		byte_ptr_1dlut_dst++;
710 	}
711 
712 	/* Update 1dlut table and sharpness level */
713 	memcpy((void *)filter_isharp_1D_lut_pregen[setup].value, (void *)filter_pregen_store, size_1dlut);
714 	filter_isharp_1D_lut_pregen[setup].sharpness_numer = sharpnessX1000;
715 	filter_isharp_1D_lut_pregen[setup].sharpness_denom = 1000;
716 }
717 
spl_get_pregen_filter_isharp_1D_lut(enum system_setup setup)718 uint32_t *spl_get_pregen_filter_isharp_1D_lut(enum system_setup setup)
719 {
720 	return filter_isharp_1D_lut_pregen[setup].value;
721 }
722 
spl_init_blur_scale_coeffs(void)723 void spl_init_blur_scale_coeffs(void)
724 {
725 	convert_filter_s1_10_to_s1_12(filter_isharp_bs_3tap_64p,
726 		filter_isharp_bs_3tap_64p_s1_12, 3);
727 	convert_filter_s1_10_to_s1_12(filter_isharp_bs_4tap_64p,
728 		filter_isharp_bs_4tap_64p_s1_12, 4);
729 	convert_filter_s1_10_to_s1_12(filter_isharp_bs_4tap_in_6_64p,
730 		filter_isharp_bs_4tap_in_6_64p_s1_12, 6);
731 }
732 
spl_dscl_get_blur_scale_coeffs_64p(int taps)733 uint16_t *spl_dscl_get_blur_scale_coeffs_64p(int taps)
734 {
735 	if (taps == 3)
736 		return spl_get_filter_isharp_bs_3tap_64p();
737 	else if (taps == 4)
738 		return spl_get_filter_isharp_bs_4tap_64p();
739 	else if (taps == 6)
740 		return spl_get_filter_isharp_bs_4tap_in_6_64p();
741 	else {
742 		/* should never happen, bug */
743 		SPL_BREAK_TO_DEBUGGER();
744 		return NULL;
745 	}
746 }
747 
spl_set_blur_scale_data(struct dscl_prog_data * dscl_prog_data,const struct spl_scaler_data * data)748 void spl_set_blur_scale_data(struct dscl_prog_data *dscl_prog_data,
749 		const struct spl_scaler_data *data)
750 {
751 	dscl_prog_data->filter_blur_scale_h =
752 		spl_dscl_get_blur_scale_coeffs_64p(data->taps.h_taps);
753 
754 	dscl_prog_data->filter_blur_scale_v =
755 		spl_dscl_get_blur_scale_coeffs_64p(data->taps.v_taps);
756 }
757 
758