// SPDX-License-Identifier: GPL-2.0
/*
* Rockchip RK3288 VPU codec driver
*
* Copyright ( c ) 2014 Rockchip Electronics Co . , Ltd .
* Hertz Wong < hertz . wong @ rock - chips . com >
* Herman Chen < herman . chen @ rock - chips . com >
*
* Copyright ( C ) 2014 Google , Inc .
* Tomasz Figa < tfiga @ chromium . org >
*/
#include <linux/types.h>
#include <media/v4l2-h264.h>
#include <media/v4l2-mem2mem.h>
#include "hantro.h"
#include "hantro_hw.h"
/* Size with u32 units. */
#define CABAC_INIT_BUFFER_SIZE (460 * 2 )
#define POC_BUFFER_SIZE 34
#define SCALING_LIST_SIZE (6 * 16 + 2 * 64 )
/*
* For valid and long term reference marking , index are reversed , so bit 31
* indicates the status of the picture 0 .
*/
#define REF_BIT(i) BIT(32 - 1 - (i))
/* Data structure describing auxiliary buffer format. */
struct hantro_h264_dec_priv_tbl {
u32 cabac_table[CABAC_INIT_BUFFER_SIZE];
u32 poc[POC_BUFFER_SIZE];
u8 scaling_list[SCALING_LIST_SIZE];
};
/*
* Constant CABAC table .
* From drivers / media / platform / rk3288 - vpu / rk3288_vpu_hw_h264d . c
* in https : //chromium.googlesource.com/chromiumos/third_party/kernel,
* chromeos - 3 . 14 branch .
*/
static const u32 h264_cabac_table[] = {
0 x14f10236, 0 x034a14f1, 0 x0236034a, 0 xe47fe968, 0 xfa35ff36, 0 x07330000,
0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000,
0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000,
0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000,
0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000, 0 x00000000,
0 x0029003f, 0 x003f003f, 0 xf7530456, 0 x0061f948, 0 x0d29033e, 0 x000b0137,
0 x0045ef7f, 0 xf3660052, 0 xf94aeb6b, 0 xe57fe17f, 0 xe87fee5f, 0 xe57feb72,
0 xe27fef7b, 0 xf473f07a, 0 xf573f43f, 0 xfe44f154, 0 xf368fd46, 0 xf85df65a,
0 xe27fff4a, 0 xfa61f95b, 0 xec7ffc38, 0 xfb52f94c, 0 xea7df95d, 0 xf557fd4d,
0 xfb47fc3f, 0 xfc44f454, 0 xf93ef941, 0 x083d0538, 0 xfe420140, 0 x003dfe4e,
0 x01320734, 0 x0a23002c, 0 x0b26012d, 0 x002e052c, 0 x1f110133, 0 x07321c13,
0 x10210e3e, 0 xf36cf164, 0 xf365f35b, 0 xf45ef658, 0 xf054f656, 0 xf953f357,
0 xed5e0146, 0 x0048fb4a, 0 x123bf866, 0 xf164005f, 0 xfc4b0248, 0 xf54bfd47,
0 x0f2ef345, 0 x003e0041, 0 x1525f148, 0 x09391036, 0 x003e0c48, 0 x18000f09,
0 x08190d12, 0 x0f090d13, 0 x0a250c12, 0 x061d1421, 0 x0f1e042d, 0 x013a003e,
0 x073d0c26, 0 x0b2d0f27, 0 x0b2a0d2c, 0 x102d0c29, 0 x0a311e22, 0 x122a0a37,
0 x1133112e, 0 x00591aed, 0 x16ef1aef, 0 x1ee71cec, 0 x21e925e5, 0 x21e928e4,
0 x26ef21f5, 0 x28f129fa, 0 x26012911, 0 x1efa1b03, 0 x1a1625f0, 0 x23fc26f8,
0 x26fd2503, 0 x26052a00, 0 x23102716, 0 x0e301b25, 0 x153c0c44, 0 x0261fd47,
0 xfa2afb32, 0 xfd36fe3e, 0 x003a013f, 0 xfe48ff4a, 0 xf75bfb43, 0 xfb1bfd27,
0 xfe2c002e, 0 xf040f844, 0 xf64efa4d, 0 xf656f45c, 0 xf137f63c, 0 xfa3efc41,
0 xf449f84c, 0 xf950f758, 0 xef6ef561, 0 xec54f54f, 0 xfa49fc4a, 0 xf356f360,
0 xf561ed75, 0 xf84efb21, 0 xfc30fe35, 0 xfd3ef347, 0 xf64ff456, 0 xf35af261,
0 x0000fa5d, 0 xfa54f84f, 0 x0042ff47, 0 x003efe3c, 0 xfe3bfb4b, 0 xfd3efc3a,
0 xf742ff4f, 0 x00470344, 0 x0a2cf93e, 0 x0f240e28, 0 x101b0c1d, 0 x012c1424,
0 x1220052a, 0 x01300a3e, 0 x112e0940, 0 xf468f561, 0 xf060f958, 0 xf855f955,
0 xf755f358, 0 x0442fd4d, 0 xfd4cfa4c, 0 x0a3aff4c, 0 xff53f963, 0 xf25f025f,
0 x004cfb4a, 0 x0046f54b, 0 x01440041, 0 xf249033e, 0 x043eff44, 0 xf34b0b37,
0 x05400c46, 0 x0f060613, 0 x07100c0e, 0 x120d0d0b, 0 x0d0f0f10, 0 x0c170d17,
0 x0f140e1a, 0 x0e2c1128, 0 x112f1811, 0 x15151916, 0 x1f1b161d, 0 x13230e32,
0 x0a39073f, 0 xfe4dfc52, 0 xfd5e0945, 0 xf46d24dd, 0 x24de20e6, 0 x25e22ce0,
0 x22ee22f1, 0 x28f121f9, 0 x23fb2100, 0 x2602210d, 0 x17230d3a, 0 x1dfd1a00,
0 x161e1ff9, 0 x23f122fd, 0 x220324ff, 0 x2205200b, 0 x2305220c, 0 x270b1e1d,
0 x221a1d27, 0 x13421f15, 0 x1f1f1932, 0 xef78ec70, 0 xee72f555, 0 xf15cf259,
0 xe647f151, 0 xf2500044, 0 xf246e838, 0 xe944e832, 0 xf54a17f3, 0 x1af328f1,
0 x31f22c03, 0 x2d062c22, 0 x21361352, 0 xfd4bff17, 0 x0122012b, 0 x0036fe37,
0 x003d0140, 0 x0044f75c, 0 xf26af361, 0 xf15af45a, 0 xee58f649, 0 xf74ff256,
0 xf649f646, 0 xf645fb42, 0 xf740fb3a, 0 x023b15f6, 0 x18f51cf8, 0 x1cff1d03,
0 x1d092314, 0 x1d240e43, 0 x14f10236, 0 x034a14f1, 0 x0236034a, 0 xe47fe968,
0 xfa35ff36, 0 x07331721, 0 x17021500, 0 x01090031, 0 xdb760539, 0 xf34ef541,
0 x013e0c31, 0 xfc491132, 0 x1240092b, 0 x1d001a43, 0 x105a0968, 0 xd27fec68,
0 x0143f34e, 0 xf541013e, 0 xfa56ef5f, 0 xfa3d092d, 0 xfd45fa51, 0 xf5600637,
0 x0743fb56, 0 x0258003a, 0 xfd4cf65e, 0 x05360445, 0 xfd510058, 0 xf943fb4a,
0 xfc4afb50, 0 xf948013a, 0 x0029003f, 0 x003f003f, 0 xf7530456, 0 x0061f948,
0 x0d29033e, 0 x002dfc4e, 0 xfd60e57e, 0 xe462e765, 0 xe943e452, 0 xec5ef053,
0 xea6eeb5b, 0 xee66f35d, 0 xe37ff95c, 0 xfb59f960, 0 xf36cfd2e, 0 xff41ff39,
0 xf75dfd4a, 0 xf75cf857, 0 xe97e0536, 0 x063c063b, 0 x0645ff30, 0 x0044fc45,
0 xf858fe55, 0 xfa4eff4b, 0 xf94d0236, 0 x0532fd44, 0 x0132062a, 0 xfc51013f,
0 xfc460043, 0 x0239fe4c, 0 x0b230440, 0 x013d0b23, 0 x12190c18, 0 x0d1d0d24,
0 xf65df949, 0 xfe490d2e, 0 x0931f964, 0 x09350235, 0 x0535fe3d, 0 x00380038,
0 xf33ffb3c, 0 xff3e0439, 0 xfa450439, 0 x0e270433, 0 x0d440340, 0 x013d093f,
0 x07321027, 0 x052c0434, 0 x0b30fb3c, 0 xff3b003b, 0 x1621052c, 0 x0e2bff4e,
0 x003c0945, 0 x0b1c0228, 0 x032c0031, 0 x002e022c, 0 x0233002f, 0 x0427023e,
0 x062e0036, 0 x0336023a, 0 x043f0633, 0 x06390735, 0 x06340637, 0 x0b2d0e24,
0 x0835ff52, 0 x0737fd4e, 0 x0f2e161f, 0 xff541907, 0 x1ef91c03, 0 x1c042000,
0 x22ff1e06, 0 x1e062009, 0 x1f131a1b, 0 x1a1e2514, 0 x1c221146, 0 x0143053b,
0 x0943101e, 0 x12201223, 0 x161d181f, 0 x1726122b, 0 x14290b3f, 0 x093b0940,
0 xff5efe59, 0 xf76cfa4c, 0 xfe2c002d, 0 x0034fd40, 0 xfe3bfc46, 0 xfc4bf852,
0 xef66f74d, 0 x0318002a, 0 x00300037, 0 xfa3bf947, 0 xf453f557, 0 xe277013a,
0 xfd1dff24, 0 x0126022b, 0 xfa37003a, 0 x0040fd4a, 0 xf65a0046, 0 xfc1d051f,
0 x072a013b, 0 xfe3afd48, 0 xfd51f561, 0 x003a0805, 0 x0a0e0e12, 0 x0d1b0228,
0 x003afd46, 0 xfa4ff855, 0 x0000f36a, 0 xf06af657, 0 xeb72ee6e, 0 xf262ea6e,
0 xeb6aee67, 0 xeb6be96c, 0 xe670f660, 0 xf45ffb5b, 0 xf75dea5e, 0 xfb560943,
0 xfc50f655, 0 xff46073c, 0 x093a053d, 0 x0c320f32, 0 x12311136, 0 x0a29072e,
0 xff330731, 0 x08340929, 0 x062f0237, 0 x0d290a2c, 0 x06320535, 0 x0d31043f,
0 x0640fe45, 0 xfe3b0646, 0 x0a2c091f, 0 x0c2b0335, 0 x0e220a26, 0 xfd340d28,
0 x1120072c, 0 x07260d32, 0 x0a391a2b, 0 x0e0b0b0e, 0 x090b120b, 0 x150917fe,
0 x20f120f1, 0 x22eb27e9, 0 x2adf29e1, 0 x2ee426f4, 0 x151d2de8, 0 x35d330e6,
0 x41d52bed, 0 x27f61e09, 0 x121a141b, 0 x0039f252, 0 xfb4bed61, 0 xdd7d1b00,
0 x1c001ffc, 0 x1b062208, 0 x1e0a1816, 0 x21131620, 0 x1a1f1529, 0 x1a2c172f,
0 x10410e47, 0 x083c063f, 0 x11411518, 0 x17141a17, 0 x1b201c17, 0 x1c181728,
0 x18201c1d, 0 x172a1339, 0 x1635163d, 0 x0b560c28, 0 x0b330e3b, 0 xfc4ff947,
0 xfb45f746, 0 xf842f644, 0 xed49f445, 0 xf046f143, 0 xec3eed46, 0 xf042ea41,
0 xec3f09fe, 0 x1af721f7, 0 x27f929fe, 0 x2d033109, 0 x2d1b243b, 0 xfa42f923,
0 xf92af82d, 0 xfb30f438, 0 xfa3cfb3e, 0 xf842f84c, 0 xfb55fa51, 0 xf64df951,
0 xef50ee49, 0 xfc4af653, 0 xf747f743, 0 xff3df842, 0 xf242003b, 0 x023b15f3,
0 x21f227f9, 0 x2efe3302, 0 x3c063d11, 0 x37222a3e, 0 x14f10236, 0 x034a14f1,
0 x0236034a, 0 xe47fe968, 0 xfa35ff36, 0 x07331619, 0 x22001000, 0 xfe090429,
0 xe3760241, 0 xfa47f34f, 0 x05340932, 0 xfd460a36, 0 x1a221316, 0 x28003902,
0 x29241a45, 0 xd37ff165, 0 xfc4cfa47, 0 xf34f0534, 0 x0645f35a, 0 x0034082b,
0 xfe45fb52, 0 xf660023b, 0 x024bfd57, 0 xfd640138, 0 xfd4afa55, 0 x003bfd51,
0 xf956fb5f, 0 xff42ff4d, 0 x0146fe56, 0 xfb48003d, 0 x0029003f, 0 x003f003f,
0 xf7530456, 0 x0061f948, 0 x0d29033e, 0 x0d0f0733, 0 x0250d97f, 0 xee5bef60,
0 xe651dd62, 0 xe866e961, 0 xe577e863, 0 xeb6eee66, 0 xdc7f0050, 0 xfb59f95e,
0 xfc5c0027, 0 x0041f154, 0 xdd7ffe49, 0 xf468f75b, 0 xe17f0337, 0 x07380737,
0 x083dfd35, 0 x0044f94a, 0 xf758f367, 0 xf35bf759, 0 xf25cf84c, 0 xf457e96e,
0 xe869f64e, 0 xec70ef63, 0 xb27fba7f, 0 xce7fd27f, 0 xfc42fb4e, 0 xfc47f848,
0 x023bff37, 0 xf946fa4b, 0 xf859de77, 0 xfd4b2014, 0 x1e16d47f, 0 x0036fb3d,
0 x003aff3c, 0 xfd3df843, 0 xe754f24a, 0 xfb410534, 0 x0239003d, 0 xf745f546,
0 x1237fc47, 0 x003a073d, 0 x09291219, 0 x0920052b, 0 x092f002c, 0 x0033022e,
0 x1326fc42, 0 x0f260c2a, 0 x09220059, 0 x042d0a1c, 0 x0a1f21f5, 0 x34d5120f,
0 x1c0023ea, 0 x26e72200, 0 x27ee20f4, 0 x66a20000, 0 x38f121fc, 0 x1d0a25fb,
0 x33e327f7, 0 x34de45c6, 0 x43c12cfb, 0 x200737e3, 0 x20010000, 0 x1b2421e7,
0 x22e224e4, 0 x26e426e5, 0 x22ee23f0, 0 x22f220f8, 0 x25fa2300, 0 x1e0a1c12,
0 x1a191d29, 0 x004b0248, 0 x084d0e23, 0 x121f1123, 0 x151e112d, 0 x142a122d,
0 x1b1a1036, 0 x07421038, 0 x0b490a43, 0 xf674e970, 0 xf147f93d, 0 x0035fb42,
0 xf54df750, 0 xf754f657, 0 xde7feb65, 0 xfd27fb35, 0 xf93df54b, 0 xf14def5b,
0 xe76be76f, 0 xe47af54c, 0 xf62cf634, 0 xf639f73a, 0 xf048f945, 0 xfc45fb4a,
0 xf7560242, 0 xf7220120, 0 x0b1f0534, 0 xfe37fe43, 0 x0049f859, 0 x03340704,
0 x0a081108, 0 x10130325, 0 xff3dfb49, 0 xff46fc4e, 0 x0000eb7e, 0 xe97cec6e,
0 xe67ee77c, 0 xef69e579, 0 xe575ef66, 0 xe675e574, 0 xdf7af65f, 0 xf264f85f,
0 xef6fe472, 0 xfa59fe50, 0 xfc52f755, 0 xf851ff48, 0 x05400143, 0 x09380045,
0 x01450745, 0 xf945fa43, 0 xf04dfe40, 0 x023dfa43, 0 xfd400239, 0 xfd41fd42,
0 x003e0933, 0 xff42fe47, 0 xfe4bff46, 0 xf7480e3c, 0 x1025002f, 0 x12230b25,
0 x0c290a29, 0 x02300c29, 0 x0d29003b, 0 x03321328, 0 x03421232, 0 x13fa12fa,
0 x0e001af4, 0 x1ff021e7, 0 x21ea25e4, 0 x27e22ae2, 0 x2fd62ddc, 0 x31de29ef,
0 x200945b9, 0 x3fc142c0, 0 x4db636d9, 0 x34dd29f6, 0 x240028ff, 0 x1e0e1c1a,
0 x17250c37, 0 x0b4125df, 0 x27dc28db, 0 x26e22edf, 0 x2ae228e8, 0 x31e326f4,
0 x28f626fd, 0 x2efb1f14, 0 x1d1e192c, 0 x0c300b31, 0 x1a2d1616, 0 x17161b15,
0 x21141a1c, 0 x1e181b22, 0 x122a1927, 0 x12320c46, 0 x15360e47, 0 x0b531920,
0 x15311536, 0 xfb55fa51, 0 xf64df951, 0 xef50ee49, 0 xfc4af653, 0 xf747f743,
0 xff3df842, 0 xf242003b, 0 x023b11f6, 0 x20f32af7, 0 x31fb3500, 0 x4003440a,
0 x421b2f39, 0 xfb470018, 0 xff24fe2a, 0 xfe34f739, 0 xfa3ffc41, 0 xfc43f952,
0 xfd51fd4c, 0 xf948fa4e, 0 xf448f244, 0 xfd46fa4c, 0 xfb42fb3e, 0 x0039fc3d,
0 xf73c0136, 0 x023a11f6, 0 x20f32af7, 0 x31fb3500, 0 x4003440a, 0 x421b2f39,
0 x14f10236, 0 x034a14f1, 0 x0236034a, 0 xe47fe968, 0 xfa35ff36, 0 x07331d10,
0 x19000e00, 0 xf633fd3e, 0 xe5631a10, 0 xfc55e866, 0 x05390639, 0 xef490e39,
0 x1428140a, 0 x1d003600, 0 x252a0c61, 0 xe07fea75, 0 xfe4afc55, 0 xe8660539,
0 xfa5df258, 0 xfa2c0437, 0 xf559f167, 0 xeb741339, 0 x143a0454, 0 x0660013f,
0 xfb55f36a, 0 x053f064b, 0 xfd5aff65, 0 x0337fc4f, 0 xfe4bf461, 0 xf932013c,
0 x0029003f, 0 x003f003f, 0 xf7530456, 0 x0061f948, 0 x0d29033e, 0 x0722f758,
0 xec7fdc7f, 0 xef5bf25f, 0 xe754e756, 0 xf459ef5b, 0 xe17ff24c, 0 xee67f35a,
0 xdb7f0b50, 0 x054c0254, 0 x054efa37, 0 x043df253, 0 xdb7ffb4f, 0 xf568f55b,
0 xe27f0041, 0 xfe4f0048, 0 xfc5cfa38, 0 x0344f847, 0 xf362fc56, 0 xf458fb52,
0 xfd48fc43, 0 xf848f059, 0 xf745ff3b, 0 x05420439, 0 xfc47fe47, 0 x023aff4a,
0 xfc2cff45, 0 x003ef933, 0 xfc2ffa2a, 0 xfd29fa35, 0 x084cf74e, 0 xf5530934,
0 x0043fb5a, 0 x0143f148, 0 xfb4bf850, 0 xeb53eb40, 0 xf31fe740, 0 xe35e094b,
0 x113ff84a, 0 xfb23fe1b, 0 x0d5b0341, 0 xf945084d, 0 xf642033e, 0 xfd44ec51,
0 x001e0107, 0 xfd17eb4a, 0 x1042e97c, 0 x11252cee, 0 x32deea7f, 0 x0427002a,
0 x07220b1d, 0 x081f0625, 0 x072a0328, 0 x08210d2b, 0 x0d24042f, 0 x0337023a,
0 x063c082c, 0 x0b2c0e2a, 0 x07300438, 0 x04340d25, 0 x0931133a, 0 x0a300c2d,
0 x00451421, 0 x083f23ee, 0 x21e71cfd, 0 x180a1b00, 0 x22f234d4, 0 x27e81311,
0 x1f19241d, 0 x1821220f, 0 x1e141649, 0 x1422131f, 0 x1b2c1310, 0 x0f240f24,
0 x151c1915, 0 x1e141f0c, 0 x1b10182a, 0 x005d0e38, 0 x0f391a26, 0 xe87fe873,
0 xea52f73e, 0 x0035003b, 0 xf255f359, 0 xf35ef55c, 0 xe37feb64, 0 xf239f443,
0 xf547f64d, 0 xeb55f058, 0 xe968f162, 0 xdb7ff652, 0 xf830f83d, 0 xf842f946,
0 xf24bf64f, 0 xf753f45c, 0 xee6cfc4f, 0 xea45f04b, 0 xfe3a013a, 0 xf34ef753,
0 xfc51f363, 0 xf351fa26, 0 xf33efa3a, 0 xfe3bf049, 0 xf64cf356, 0 xf753f657,
0 x0000ea7f, 0 xe77fe778, 0 xe57fed72, 0 xe975e776, 0 xe675e871, 0 xe476e178,
0 xdb7cf65e, 0 xf166f663, 0 xf36ace7f, 0 xfb5c1139, 0 xfb56f35e, 0 xf45bfe4d,
0 x0047ff49, 0 x0440f951, 0 x05400f39, 0 x01430044, 0 xf6430144, 0 x004d0240,
0 x0044fb4e, 0 x0737053b, 0 x02410e36, 0 x0f2c053c, 0 x0246fe4c, 0 xee560c46,
0 x0540f446, 0 x0b370538, 0 x00450241, 0 xfa4a0536, 0 x0736fa4c, 0 xf552fe4d,
0 xfe4d192a, 0 x11f310f7, 0 x11f41beb, 0 x25e229d8, 0 x2ad730d1, 0 x27e02ed8,
0 x34cd2ed7, 0 x34d92bed, 0 x200b3dc9, 0 x38d23ece, 0 x51bd2dec, 0 x23fe1c0f,
0 x22012701, 0 x1e111426, 0 x122d0f36, 0 x004f24f0, 0 x25f225ef, 0 x2001220f,
0 x1d0f1819, 0 x22161f10, 0 x23121f1c, 0 x2129241c, 0 x1b2f153e, 0 x121f131a,
0 x24181817, 0 x1b10181e, 0 x1f1d1629, 0 x162a103c, 0 x0f340e3c, 0 x034ef07b,
0 x15351638, 0 x193d1521, 0 x1332113d, 0 xfd4ef84a, 0 xf748f648, 0 xee4bf447,
0 xf53ffb46, 0 xef4bf248, 0 xf043f835, 0 xf23bf734, 0 xf54409fe, 0 x1ef61ffc,
0 x21ff2107, 0 x1f0c2517, 0 x1f261440, 0 xf747f925, 0 xf82cf531, 0 xf638f43b,
0 xf83ff743, 0 xfa44f64f, 0 xfd4ef84a, 0 xf748f648, 0 xee4bf447, 0 xf53ffb46,
0 xef4bf248, 0 xf043f835, 0 xf23bf734, 0 xf54409fe, 0 x1ef61ffc, 0 x21ff2107,
0 x1f0c2517, 0 x1f261440
};
static void
assemble_scaling_list(struct hantro_ctx *ctx)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_scaling_matrix *scaling = ctrls->scaling;
const struct v4l2_ctrl_h264_pps *pps = ctrls->pps;
const size_t num_list_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4);
const size_t list_len_4x4 = ARRAY_SIZE(scaling->scaling_list_4x4[0 ]);
const size_t list_len_8x8 = ARRAY_SIZE(scaling->scaling_list_8x8[0 ]);
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
u32 *dst = (u32 *)tbl->scaling_list;
const u32 *src;
int i, j;
if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
return ;
for (i = 0 ; i < num_list_4x4; i++) {
src = (u32 *)&scaling->scaling_list_4x4[i];
for (j = 0 ; j < list_len_4x4 / 4 ; j++)
*dst++ = swab32(src[j]);
}
/* Only Intra/Inter Y lists */
for (i = 0 ; i < 2 ; i++) {
src = (u32 *)&scaling->scaling_list_8x8[i];
for (j = 0 ; j < list_len_8x8 / 4 ; j++)
*dst++ = swab32(src[j]);
}
}
static void prepare_table(struct hantro_ctx *ctx)
{
const struct hantro_h264_dec_ctrls *ctrls = &ctx->h264_dec.ctrls;
const struct v4l2_ctrl_h264_decode_params *dec_param = ctrls->decode;
const struct v4l2_ctrl_h264_sps *sps = ctrls->sps;
struct hantro_h264_dec_priv_tbl *tbl = ctx->h264_dec.priv.cpu;
const struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
u32 dpb_longterm = 0 ;
u32 dpb_valid = 0 ;
int i;
for (i = 0 ; i < HANTRO_H264_DPB_SIZE; ++i) {
tbl->poc[i * 2 ] = dpb[i].top_field_order_cnt;
tbl->poc[i * 2 + 1 ] = dpb[i].bottom_field_order_cnt;
if (!(dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
continue ;
/*
* Set up bit maps of valid and long term DPBs .
* NOTE : The bits are reversed , i . e . MSb is DPB 0 . For frame
* decoding , bit 31 to 15 are used , while for field decoding ,
* all bits are used , with bit 31 being a top field , 30 a bottom
* field and so on .
*/
if (dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) {
if (dpb[i].fields & V4L2_H264_TOP_FIELD_REF)
dpb_valid |= REF_BIT(i * 2 );
if (dpb[i].fields & V4L2_H264_BOTTOM_FIELD_REF)
dpb_valid |= REF_BIT(i * 2 + 1 );
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM) {
dpb_longterm |= REF_BIT(i * 2 );
dpb_longterm |= REF_BIT(i * 2 + 1 );
}
} else {
dpb_valid |= REF_BIT(i);
if (dpb[i].flags & V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM)
dpb_longterm |= REF_BIT(i);
}
}
ctx->h264_dec.dpb_valid = dpb_valid;
ctx->h264_dec.dpb_longterm = dpb_longterm;
if ((dec_param->flags & V4L2_H264_DECODE_PARAM_FLAG_FIELD_PIC) ||
!(sps->flags & V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD)) {
tbl->poc[32 ] = ctx->h264_dec.cur_poc;
tbl->poc[33 ] = 0 ;
} else {
tbl->poc[32 ] = dec_param->top_field_order_cnt;
tbl->poc[33 ] = dec_param->bottom_field_order_cnt;
}
assemble_scaling_list(ctx);
}
static bool dpb_entry_match(const struct v4l2_h264_dpb_entry *a,
const struct v4l2_h264_dpb_entry *b)
{
return a->reference_ts == b->reference_ts;
}
static void update_dpb(struct hantro_ctx *ctx)
{
const struct v4l2_ctrl_h264_decode_params *dec_param;
DECLARE_BITMAP(new , ARRAY_SIZE(dec_param->dpb)) = { 0 , };
DECLARE_BITMAP(used, ARRAY_SIZE(dec_param->dpb)) = { 0 , };
unsigned int i, j;
dec_param = ctx->h264_dec.ctrls.decode;
/* Disable all entries by default. */
for (i = 0 ; i < ARRAY_SIZE(ctx->h264_dec.dpb); i++)
ctx->h264_dec.dpb[i].flags = 0 ;
/* Try to match new DPB entries with existing ones by their POCs. */
for (i = 0 ; i < ARRAY_SIZE(dec_param->dpb); i++) {
const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i];
if (!(ndpb->flags & V4L2_H264_DPB_ENTRY_FLAG_VALID))
continue ;
/*
* To cut off some comparisons , iterate only on target DPB
* entries which are not used yet .
*/
for_each_clear_bit(j, used, ARRAY_SIZE(ctx->h264_dec.dpb)) {
struct v4l2_h264_dpb_entry *cdpb;
cdpb = &ctx->h264_dec.dpb[j];
if (!dpb_entry_match(cdpb, ndpb))
continue ;
*cdpb = *ndpb;
__set_bit(j, used);
break ;
}
if (j == ARRAY_SIZE(ctx->h264_dec.dpb))
__set_bit(i, new );
}
/* For entries that could not be matched, use remaining free slots. */
for_each_set_bit(i, new , ARRAY_SIZE(dec_param->dpb)) {
const struct v4l2_h264_dpb_entry *ndpb = &dec_param->dpb[i];
struct v4l2_h264_dpb_entry *cdpb;
/*
* Both arrays are of the same sizes , so there is no way
* we can end up with no space in target array , unless
* something is buggy .
*/
j = find_first_zero_bit(used, ARRAY_SIZE(ctx->h264_dec.dpb));
if (WARN_ON(j >= ARRAY_SIZE(ctx->h264_dec.dpb)))
return ;
cdpb = &ctx->h264_dec.dpb[j];
*cdpb = *ndpb;
__set_bit(j, used);
}
}
dma_addr_t hantro_h264_get_ref_buf(struct hantro_ctx *ctx,
unsigned int dpb_idx)
{
struct v4l2_h264_dpb_entry *dpb = ctx->h264_dec.dpb;
dma_addr_t dma_addr = 0 ;
s32 cur_poc = ctx->h264_dec.cur_poc;
u32 flags;
if (dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE)
dma_addr = hantro_get_ref(ctx, dpb[dpb_idx].reference_ts);
if (!dma_addr) {
struct vb2_v4l2_buffer *dst_buf;
struct vb2_buffer *buf;
/*
* If a DPB entry is unused or invalid , address of current
* destination buffer is returned .
*/
dst_buf = hantro_get_dst_buf(ctx);
buf = &dst_buf->vb2_buf;
dma_addr = hantro_get_dec_buf_addr(ctx, buf);
}
flags = dpb[dpb_idx].flags & V4L2_H264_DPB_ENTRY_FLAG_FIELD ? 0 x2 : 0 ;
flags |= abs(dpb[dpb_idx].top_field_order_cnt - cur_poc) <
abs(dpb[dpb_idx].bottom_field_order_cnt - cur_poc) ?
0 x1 : 0 ;
return dma_addr | flags;
}
u16 hantro_h264_get_ref_nbr(struct hantro_ctx *ctx, unsigned int dpb_idx)
{
const struct v4l2_h264_dpb_entry *dpb = &ctx->h264_dec.dpb[dpb_idx];
if (!(dpb->flags & V4L2_H264_DPB_ENTRY_FLAG_ACTIVE))
return 0 ;
return dpb->frame_num;
}
/*
* Removes all references with the same parity as the current picture from the
* reference list . The remaining list will have references with the opposite
* parity . This is effectively a deduplication of references since each buffer
* stores two fields . For this reason , each buffer is found twice in the
* reference list .
*
* This technique has been chosen through trial and error . This simple approach
* resulted in the highest conformance score . Note that this method may suffer
* worse quality in the case an opposite reference frame has been lost . If this
* becomes a problem in the future , it should be possible to add a preprocessing
* to identify un - paired fields and avoid removing them .
*/
static void deduplicate_reflist(struct v4l2_h264_reflist_builder *b,
struct v4l2_h264_reference *reflist)
{
int write_idx = 0 ;
int i;
if (b->cur_pic_fields == V4L2_H264_FRAME_REF) {
write_idx = b->num_valid;
goto done;
}
for (i = 0 ; i < b->num_valid; i++) {
if (!(b->cur_pic_fields == reflist[i].fields)) {
reflist[write_idx++] = reflist[i];
continue ;
}
}
done:
/* Should not happen unless we have a bug in the reflist builder. */
if (WARN_ON(write_idx > 16 ))
write_idx = 16 ;
/* Clear the remaining, some streams fails otherwise */
for (; write_idx < 16 ; write_idx++)
reflist[write_idx].index = 15 ;
}
int hantro_h264_dec_prepare_run(struct hantro_ctx *ctx)
{
struct hantro_h264_dec_hw_ctx *h264_ctx = &ctx->h264_dec;
struct hantro_h264_dec_ctrls *ctrls = &h264_ctx->ctrls;
struct v4l2_h264_reflist_builder reflist_builder;
hantro_start_prepare_run(ctx);
ctrls->scaling =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_SCALING_MATRIX);
if (WARN_ON(!ctrls->scaling))
return -EINVAL;
ctrls->decode =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_DECODE_PARAMS);
if (WARN_ON(!ctrls->decode))
return -EINVAL;
ctrls->sps =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_SPS);
if (WARN_ON(!ctrls->sps))
return -EINVAL;
ctrls->pps =
hantro_get_ctrl(ctx, V4L2_CID_STATELESS_H264_PPS);
if (WARN_ON(!ctrls->pps))
return -EINVAL;
/* Update the DPB with new refs. */
update_dpb(ctx);
/* Build the P/B{0,1} ref lists. */
v4l2_h264_init_reflist_builder(&reflist_builder, ctrls->decode,
ctrls->sps, ctx->h264_dec.dpb);
h264_ctx->cur_poc = reflist_builder.cur_pic_order_count;
/* Prepare data in memory. */
prepare_table(ctx);
v4l2_h264_build_p_ref_list(&reflist_builder, h264_ctx->reflists.p);
v4l2_h264_build_b_ref_lists(&reflist_builder, h264_ctx->reflists.b0,
h264_ctx->reflists.b1);
/*
* Reduce ref lists to at most 16 entries , Hantro hardware will deduce
* the actual picture lists in field through the dpb_valid ,
* dpb_longterm bitmap along with the current frame parity .
*/
if (reflist_builder.cur_pic_fields != V4L2_H264_FRAME_REF) {
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.p);
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b0);
deduplicate_reflist(&reflist_builder, h264_ctx->reflists.b1);
}
return 0 ;
}
void hantro_h264_dec_exit(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_h264_dec_hw_ctx *h264_dec = &ctx->h264_dec;
struct hantro_aux_buf *priv = &h264_dec->priv;
dma_free_coherent(vpu->dev, priv->size, priv->cpu, priv->dma);
}
int hantro_h264_dec_init(struct hantro_ctx *ctx)
{
struct hantro_dev *vpu = ctx->dev;
struct hantro_h264_dec_hw_ctx *h264_dec = &ctx->h264_dec;
struct hantro_aux_buf *priv = &h264_dec->priv;
struct hantro_h264_dec_priv_tbl *tbl;
priv->cpu = dma_alloc_coherent(vpu->dev, sizeof (*tbl), &priv->dma,
GFP_KERNEL);
if (!priv->cpu)
return -ENOMEM;
priv->size = sizeof (*tbl);
tbl = priv->cpu;
memcpy(tbl->cabac_table, h264_cabac_table, sizeof (tbl->cabac_table));
return 0 ;
}
Messung V0.5 in Prozent C=93 H=97 G=94
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-10-11)
¤
*© Formatika GbR, Deutschland