18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: LGPL-2.1+ */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2016 Tom aan de Wiel
48c2ecf20Sopenharmony_ci * Copyright 2018 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#ifndef CODEC_FWHT_H
88c2ecf20Sopenharmony_ci#define CODEC_FWHT_H
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/types.h>
118c2ecf20Sopenharmony_ci#include <linux/bitops.h>
128c2ecf20Sopenharmony_ci#include <asm/byteorder.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci/*
158c2ecf20Sopenharmony_ci * The compressed format consists of a fwht_cframe_hdr struct followed by the
168c2ecf20Sopenharmony_ci * compressed frame data. The header contains the size of that data.
178c2ecf20Sopenharmony_ci * Each Y, Cb and Cr plane is compressed separately. If the compressed
188c2ecf20Sopenharmony_ci * size of each plane becomes larger than the uncompressed size, then
198c2ecf20Sopenharmony_ci * that plane is stored uncompressed and the corresponding bit is set
208c2ecf20Sopenharmony_ci * in the flags field of the header.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * Each compressed plane consists of macroblocks and each macroblock
238c2ecf20Sopenharmony_ci * is run-length-encoded. Each macroblock starts with a 16 bit value.
248c2ecf20Sopenharmony_ci * Bit 15 indicates if this is a P-coded macroblock (1) or not (0).
258c2ecf20Sopenharmony_ci * P-coded macroblocks contain a delta against the previous frame.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * Bits 1-12 contain a number. If non-zero, then this same macroblock
288c2ecf20Sopenharmony_ci * repeats that number of times. This results in a high degree of
298c2ecf20Sopenharmony_ci * compression for generated images like colorbars.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci * Following this macroblock header the MB coefficients are run-length
328c2ecf20Sopenharmony_ci * encoded: the top 12 bits contain the coefficient, the bottom 4 bits
338c2ecf20Sopenharmony_ci * tell how many times this coefficient occurs. The value 0xf indicates
348c2ecf20Sopenharmony_ci * that the remainder of the macroblock should be filled with zeroes.
358c2ecf20Sopenharmony_ci *
368c2ecf20Sopenharmony_ci * All 16 and 32 bit values are stored in big-endian (network) order.
378c2ecf20Sopenharmony_ci *
388c2ecf20Sopenharmony_ci * Each fwht_cframe_hdr starts with an 8 byte magic header that is
398c2ecf20Sopenharmony_ci * guaranteed not to occur in the compressed frame data. This header
408c2ecf20Sopenharmony_ci * can be used to sync to the next frame.
418c2ecf20Sopenharmony_ci *
428c2ecf20Sopenharmony_ci * This codec uses the Fast Walsh Hadamard Transform. Tom aan de Wiel
438c2ecf20Sopenharmony_ci * developed this as part of a university project, specifically for use
448c2ecf20Sopenharmony_ci * with this driver. His project report can be found here:
458c2ecf20Sopenharmony_ci *
468c2ecf20Sopenharmony_ci * https://hverkuil.home.xs4all.nl/fwht.pdf
478c2ecf20Sopenharmony_ci */
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/*
508c2ecf20Sopenharmony_ci * This is a sequence of 8 bytes with the low 4 bits set to 0xf.
518c2ecf20Sopenharmony_ci *
528c2ecf20Sopenharmony_ci * This sequence cannot occur in the encoded data
538c2ecf20Sopenharmony_ci *
548c2ecf20Sopenharmony_ci * Note that these two magic values are symmetrical so endian issues here.
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_ci#define FWHT_MAGIC1 0x4f4f4f4f
578c2ecf20Sopenharmony_ci#define FWHT_MAGIC2 0xffffffff
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci#define FWHT_VERSION 3
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* Set if this is an interlaced format */
628c2ecf20Sopenharmony_ci#define FWHT_FL_IS_INTERLACED		BIT(0)
638c2ecf20Sopenharmony_ci/* Set if this is a bottom-first (NTSC) interlaced format */
648c2ecf20Sopenharmony_ci#define FWHT_FL_IS_BOTTOM_FIRST		BIT(1)
658c2ecf20Sopenharmony_ci/* Set if each 'frame' contains just one field */
668c2ecf20Sopenharmony_ci#define FWHT_FL_IS_ALTERNATE		BIT(2)
678c2ecf20Sopenharmony_ci/*
688c2ecf20Sopenharmony_ci * If FWHT_FL_IS_ALTERNATE was set, then this is set if this
698c2ecf20Sopenharmony_ci * 'frame' is the bottom field, else it is the top field.
708c2ecf20Sopenharmony_ci */
718c2ecf20Sopenharmony_ci#define FWHT_FL_IS_BOTTOM_FIELD		BIT(3)
728c2ecf20Sopenharmony_ci/* Set if this frame is uncompressed */
738c2ecf20Sopenharmony_ci#define FWHT_FL_LUMA_IS_UNCOMPRESSED	BIT(4)
748c2ecf20Sopenharmony_ci#define FWHT_FL_CB_IS_UNCOMPRESSED	BIT(5)
758c2ecf20Sopenharmony_ci#define FWHT_FL_CR_IS_UNCOMPRESSED	BIT(6)
768c2ecf20Sopenharmony_ci#define FWHT_FL_CHROMA_FULL_HEIGHT	BIT(7)
778c2ecf20Sopenharmony_ci#define FWHT_FL_CHROMA_FULL_WIDTH	BIT(8)
788c2ecf20Sopenharmony_ci#define FWHT_FL_ALPHA_IS_UNCOMPRESSED	BIT(9)
798c2ecf20Sopenharmony_ci#define FWHT_FL_I_FRAME			BIT(10)
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/* A 4-values flag - the number of components - 1 */
828c2ecf20Sopenharmony_ci#define FWHT_FL_COMPONENTS_NUM_MSK	GENMASK(18, 16)
838c2ecf20Sopenharmony_ci#define FWHT_FL_COMPONENTS_NUM_OFFSET	16
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define FWHT_FL_PIXENC_MSK	GENMASK(20, 19)
868c2ecf20Sopenharmony_ci#define FWHT_FL_PIXENC_OFFSET	19
878c2ecf20Sopenharmony_ci#define FWHT_FL_PIXENC_YUV	(1 << FWHT_FL_PIXENC_OFFSET)
888c2ecf20Sopenharmony_ci#define FWHT_FL_PIXENC_RGB	(2 << FWHT_FL_PIXENC_OFFSET)
898c2ecf20Sopenharmony_ci#define FWHT_FL_PIXENC_HSV	(3 << FWHT_FL_PIXENC_OFFSET)
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci/*
928c2ecf20Sopenharmony_ci * A macro to calculate the needed padding in order to make sure
938c2ecf20Sopenharmony_ci * both luma and chroma components resolutions are rounded up to
948c2ecf20Sopenharmony_ci * a multiple of 8
958c2ecf20Sopenharmony_ci */
968c2ecf20Sopenharmony_ci#define vic_round_dim(dim, div) (round_up((dim) / (div), 8) * (div))
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistruct fwht_cframe_hdr {
998c2ecf20Sopenharmony_ci	u32 magic1;
1008c2ecf20Sopenharmony_ci	u32 magic2;
1018c2ecf20Sopenharmony_ci	__be32 version;
1028c2ecf20Sopenharmony_ci	__be32 width, height;
1038c2ecf20Sopenharmony_ci	__be32 flags;
1048c2ecf20Sopenharmony_ci	__be32 colorspace;
1058c2ecf20Sopenharmony_ci	__be32 xfer_func;
1068c2ecf20Sopenharmony_ci	__be32 ycbcr_enc;
1078c2ecf20Sopenharmony_ci	__be32 quantization;
1088c2ecf20Sopenharmony_ci	__be32 size;
1098c2ecf20Sopenharmony_ci};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistruct fwht_cframe {
1128c2ecf20Sopenharmony_ci	u16 i_frame_qp;
1138c2ecf20Sopenharmony_ci	u16 p_frame_qp;
1148c2ecf20Sopenharmony_ci	__be16 *rlc_data;
1158c2ecf20Sopenharmony_ci	s16 coeffs[8 * 8];
1168c2ecf20Sopenharmony_ci	s16 de_coeffs[8 * 8];
1178c2ecf20Sopenharmony_ci	s16 de_fwht[8 * 8];
1188c2ecf20Sopenharmony_ci	u32 size;
1198c2ecf20Sopenharmony_ci};
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistruct fwht_raw_frame {
1228c2ecf20Sopenharmony_ci	unsigned int width_div;
1238c2ecf20Sopenharmony_ci	unsigned int height_div;
1248c2ecf20Sopenharmony_ci	unsigned int luma_alpha_step;
1258c2ecf20Sopenharmony_ci	unsigned int chroma_step;
1268c2ecf20Sopenharmony_ci	unsigned int components_num;
1278c2ecf20Sopenharmony_ci	u8 *buf;
1288c2ecf20Sopenharmony_ci	u8 *luma, *cb, *cr, *alpha;
1298c2ecf20Sopenharmony_ci};
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci#define FWHT_FRAME_PCODED	BIT(0)
1328c2ecf20Sopenharmony_ci#define FWHT_FRAME_UNENCODED	BIT(1)
1338c2ecf20Sopenharmony_ci#define FWHT_LUMA_UNENCODED	BIT(2)
1348c2ecf20Sopenharmony_ci#define FWHT_CB_UNENCODED	BIT(3)
1358c2ecf20Sopenharmony_ci#define FWHT_CR_UNENCODED	BIT(4)
1368c2ecf20Sopenharmony_ci#define FWHT_ALPHA_UNENCODED	BIT(5)
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ciu32 fwht_encode_frame(struct fwht_raw_frame *frm,
1398c2ecf20Sopenharmony_ci		      struct fwht_raw_frame *ref_frm,
1408c2ecf20Sopenharmony_ci		      struct fwht_cframe *cf,
1418c2ecf20Sopenharmony_ci		      bool is_intra, bool next_is_intra,
1428c2ecf20Sopenharmony_ci		      unsigned int width, unsigned int height,
1438c2ecf20Sopenharmony_ci		      unsigned int stride, unsigned int chroma_stride);
1448c2ecf20Sopenharmony_cibool fwht_decode_frame(struct fwht_cframe *cf, u32 hdr_flags,
1458c2ecf20Sopenharmony_ci		unsigned int components_num, unsigned int width,
1468c2ecf20Sopenharmony_ci		unsigned int height, const struct fwht_raw_frame *ref,
1478c2ecf20Sopenharmony_ci		unsigned int ref_stride, unsigned int ref_chroma_stride,
1488c2ecf20Sopenharmony_ci		struct fwht_raw_frame *dst, unsigned int dst_stride,
1498c2ecf20Sopenharmony_ci		unsigned int dst_chroma_stride);
1508c2ecf20Sopenharmony_ci#endif
151