162306a36Sopenharmony_ci/* SPDX-License-Identifier: LGPL-2.1+ */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2016 Tom aan de Wiel
462306a36Sopenharmony_ci * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef CODEC_FWHT_H
862306a36Sopenharmony_ci#define CODEC_FWHT_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/types.h>
1162306a36Sopenharmony_ci#include <linux/bitops.h>
1262306a36Sopenharmony_ci#include <asm/byteorder.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci/*
1562306a36Sopenharmony_ci * The compressed format consists of a fwht_cframe_hdr struct followed by the
1662306a36Sopenharmony_ci * compressed frame data. The header contains the size of that data.
1762306a36Sopenharmony_ci * Each Y, Cb and Cr plane is compressed separately. If the compressed
1862306a36Sopenharmony_ci * size of each plane becomes larger than the uncompressed size, then
1962306a36Sopenharmony_ci * that plane is stored uncompressed and the corresponding bit is set
2062306a36Sopenharmony_ci * in the flags field of the header.
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Each compressed plane consists of macroblocks and each macroblock
2362306a36Sopenharmony_ci * is run-length-encoded. Each macroblock starts with a 16 bit value.
2462306a36Sopenharmony_ci * Bit 15 indicates if this is a P-coded macroblock (1) or not (0).
2562306a36Sopenharmony_ci * P-coded macroblocks contain a delta against the previous frame.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * Bits 1-12 contain a number. If non-zero, then this same macroblock
2862306a36Sopenharmony_ci * repeats that number of times. This results in a high degree of
2962306a36Sopenharmony_ci * compression for generated images like colorbars.
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * Following this macroblock header the MB coefficients are run-length
3262306a36Sopenharmony_ci * encoded: the top 12 bits contain the coefficient, the bottom 4 bits
3362306a36Sopenharmony_ci * tell how many times this coefficient occurs. The value 0xf indicates
3462306a36Sopenharmony_ci * that the remainder of the macroblock should be filled with zeroes.
3562306a36Sopenharmony_ci *
3662306a36Sopenharmony_ci * All 16 and 32 bit values are stored in big-endian (network) order.
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * Each fwht_cframe_hdr starts with an 8 byte magic header that is
3962306a36Sopenharmony_ci * guaranteed not to occur in the compressed frame data. This header
4062306a36Sopenharmony_ci * can be used to sync to the next frame.
4162306a36Sopenharmony_ci *
4262306a36Sopenharmony_ci * This codec uses the Fast Walsh Hadamard Transform. Tom aan de Wiel
4362306a36Sopenharmony_ci * developed this as part of a university project, specifically for use
4462306a36Sopenharmony_ci * with this driver. His project report can be found here:
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * https://hverkuil.home.xs4all.nl/fwht.pdf
4762306a36Sopenharmony_ci */
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci/*
5062306a36Sopenharmony_ci * This is a sequence of 8 bytes with the low 4 bits set to 0xf.
5162306a36Sopenharmony_ci *
5262306a36Sopenharmony_ci * This sequence cannot occur in the encoded data
5362306a36Sopenharmony_ci *
5462306a36Sopenharmony_ci * Note that these two magic values are symmetrical so endian issues here.
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_ci#define FWHT_MAGIC1 0x4f4f4f4f
5762306a36Sopenharmony_ci#define FWHT_MAGIC2 0xffffffff
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/*
6062306a36Sopenharmony_ci * A macro to calculate the needed padding in order to make sure
6162306a36Sopenharmony_ci * both luma and chroma components resolutions are rounded up to
6262306a36Sopenharmony_ci * a multiple of 8
6362306a36Sopenharmony_ci */
6462306a36Sopenharmony_ci#define vic_round_dim(dim, div) (round_up((dim) / (div), 8) * (div))
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistruct fwht_cframe_hdr {
6762306a36Sopenharmony_ci	u32 magic1;
6862306a36Sopenharmony_ci	u32 magic2;
6962306a36Sopenharmony_ci	__be32 version;
7062306a36Sopenharmony_ci	__be32 width, height;
7162306a36Sopenharmony_ci	__be32 flags;
7262306a36Sopenharmony_ci	__be32 colorspace;
7362306a36Sopenharmony_ci	__be32 xfer_func;
7462306a36Sopenharmony_ci	__be32 ycbcr_enc;
7562306a36Sopenharmony_ci	__be32 quantization;
7662306a36Sopenharmony_ci	__be32 size;
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistruct fwht_cframe {
8062306a36Sopenharmony_ci	u16 i_frame_qp;
8162306a36Sopenharmony_ci	u16 p_frame_qp;
8262306a36Sopenharmony_ci	__be16 *rlc_data;
8362306a36Sopenharmony_ci	s16 coeffs[8 * 8];
8462306a36Sopenharmony_ci	s16 de_coeffs[8 * 8];
8562306a36Sopenharmony_ci	s16 de_fwht[8 * 8];
8662306a36Sopenharmony_ci	u32 size;
8762306a36Sopenharmony_ci};
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistruct fwht_raw_frame {
9062306a36Sopenharmony_ci	unsigned int width_div;
9162306a36Sopenharmony_ci	unsigned int height_div;
9262306a36Sopenharmony_ci	unsigned int luma_alpha_step;
9362306a36Sopenharmony_ci	unsigned int chroma_step;
9462306a36Sopenharmony_ci	unsigned int components_num;
9562306a36Sopenharmony_ci	u8 *buf;
9662306a36Sopenharmony_ci	u8 *luma, *cb, *cr, *alpha;
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci#define FWHT_FRAME_PCODED	BIT(0)
10062306a36Sopenharmony_ci#define FWHT_FRAME_UNENCODED	BIT(1)
10162306a36Sopenharmony_ci#define FWHT_LUMA_UNENCODED	BIT(2)
10262306a36Sopenharmony_ci#define FWHT_CB_UNENCODED	BIT(3)
10362306a36Sopenharmony_ci#define FWHT_CR_UNENCODED	BIT(4)
10462306a36Sopenharmony_ci#define FWHT_ALPHA_UNENCODED	BIT(5)
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ciu32 fwht_encode_frame(struct fwht_raw_frame *frm,
10762306a36Sopenharmony_ci		      struct fwht_raw_frame *ref_frm,
10862306a36Sopenharmony_ci		      struct fwht_cframe *cf,
10962306a36Sopenharmony_ci		      bool is_intra, bool next_is_intra,
11062306a36Sopenharmony_ci		      unsigned int width, unsigned int height,
11162306a36Sopenharmony_ci		      unsigned int stride, unsigned int chroma_stride);
11262306a36Sopenharmony_cibool fwht_decode_frame(struct fwht_cframe *cf, u32 hdr_flags,
11362306a36Sopenharmony_ci		unsigned int components_num, unsigned int width,
11462306a36Sopenharmony_ci		unsigned int height, const struct fwht_raw_frame *ref,
11562306a36Sopenharmony_ci		unsigned int ref_stride, unsigned int ref_chroma_stride,
11662306a36Sopenharmony_ci		struct fwht_raw_frame *dst, unsigned int dst_stride,
11762306a36Sopenharmony_ci		unsigned int dst_chroma_stride);
11862306a36Sopenharmony_ci#endif
119