162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2019-2020 Pengutronix, Michael Tretter <kernel@pengutronix.de>
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Helper functions to generate a raw byte sequence payload from values.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/kernel.h>
962306a36Sopenharmony_ci#include <linux/types.h>
1062306a36Sopenharmony_ci#include <linux/string.h>
1162306a36Sopenharmony_ci#include <linux/v4l2-controls.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include <linux/device.h>
1462306a36Sopenharmony_ci#include <linux/export.h>
1562306a36Sopenharmony_ci#include <linux/log2.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include "nal-rbsp.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_civoid rbsp_init(struct rbsp *rbsp, void *addr, size_t size,
2062306a36Sopenharmony_ci	       struct nal_rbsp_ops *ops)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	if (!rbsp)
2362306a36Sopenharmony_ci		return;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	rbsp->data = addr;
2662306a36Sopenharmony_ci	rbsp->size = size;
2762306a36Sopenharmony_ci	rbsp->pos = 0;
2862306a36Sopenharmony_ci	rbsp->ops = ops;
2962306a36Sopenharmony_ci	rbsp->error = 0;
3062306a36Sopenharmony_ci}
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_civoid rbsp_unsupported(struct rbsp *rbsp)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	rbsp->error = -EINVAL;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic int rbsp_read_bits(struct rbsp *rbsp, int n, unsigned int *value);
3862306a36Sopenharmony_cistatic int rbsp_write_bits(struct rbsp *rbsp, int n, unsigned int value);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/*
4162306a36Sopenharmony_ci * When reading or writing, the emulation_prevention_three_byte is detected
4262306a36Sopenharmony_ci * only when the 2 one bits need to be inserted. Therefore, we are not
4362306a36Sopenharmony_ci * actually adding the 0x3 byte, but the 2 one bits and the six 0 bits of the
4462306a36Sopenharmony_ci * next byte.
4562306a36Sopenharmony_ci */
4662306a36Sopenharmony_ci#define EMULATION_PREVENTION_THREE_BYTE (0x3 << 6)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic int add_emulation_prevention_three_byte(struct rbsp *rbsp)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	rbsp->num_consecutive_zeros = 0;
5162306a36Sopenharmony_ci	rbsp_write_bits(rbsp, 8, EMULATION_PREVENTION_THREE_BYTE);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	return 0;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic int discard_emulation_prevention_three_byte(struct rbsp *rbsp)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	unsigned int tmp = 0;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	rbsp->num_consecutive_zeros = 0;
6162306a36Sopenharmony_ci	rbsp_read_bits(rbsp, 8, &tmp);
6262306a36Sopenharmony_ci	if (tmp != EMULATION_PREVENTION_THREE_BYTE)
6362306a36Sopenharmony_ci		return -EINVAL;
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	return 0;
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistatic inline int rbsp_read_bit(struct rbsp *rbsp)
6962306a36Sopenharmony_ci{
7062306a36Sopenharmony_ci	int shift;
7162306a36Sopenharmony_ci	int ofs;
7262306a36Sopenharmony_ci	int bit;
7362306a36Sopenharmony_ci	int err;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	if (rbsp->num_consecutive_zeros == 22) {
7662306a36Sopenharmony_ci		err = discard_emulation_prevention_three_byte(rbsp);
7762306a36Sopenharmony_ci		if (err)
7862306a36Sopenharmony_ci			return err;
7962306a36Sopenharmony_ci	}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	shift = 7 - (rbsp->pos % 8);
8262306a36Sopenharmony_ci	ofs = rbsp->pos / 8;
8362306a36Sopenharmony_ci	if (ofs >= rbsp->size)
8462306a36Sopenharmony_ci		return -EINVAL;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	bit = (rbsp->data[ofs] >> shift) & 1;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	rbsp->pos++;
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	if (bit == 1 ||
9162306a36Sopenharmony_ci	    (rbsp->num_consecutive_zeros < 7 && (rbsp->pos % 8 == 0)))
9262306a36Sopenharmony_ci		rbsp->num_consecutive_zeros = 0;
9362306a36Sopenharmony_ci	else
9462306a36Sopenharmony_ci		rbsp->num_consecutive_zeros++;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	return bit;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline int rbsp_write_bit(struct rbsp *rbsp, bool value)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	int shift;
10262306a36Sopenharmony_ci	int ofs;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	if (rbsp->num_consecutive_zeros == 22)
10562306a36Sopenharmony_ci		add_emulation_prevention_three_byte(rbsp);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	shift = 7 - (rbsp->pos % 8);
10862306a36Sopenharmony_ci	ofs = rbsp->pos / 8;
10962306a36Sopenharmony_ci	if (ofs >= rbsp->size)
11062306a36Sopenharmony_ci		return -EINVAL;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	rbsp->data[ofs] &= ~(1 << shift);
11362306a36Sopenharmony_ci	rbsp->data[ofs] |= value << shift;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	rbsp->pos++;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (value ||
11862306a36Sopenharmony_ci	    (rbsp->num_consecutive_zeros < 7 && (rbsp->pos % 8 == 0))) {
11962306a36Sopenharmony_ci		rbsp->num_consecutive_zeros = 0;
12062306a36Sopenharmony_ci	} else {
12162306a36Sopenharmony_ci		rbsp->num_consecutive_zeros++;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	return 0;
12562306a36Sopenharmony_ci}
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_cistatic inline int rbsp_read_bits(struct rbsp *rbsp, int n, unsigned int *value)
12862306a36Sopenharmony_ci{
12962306a36Sopenharmony_ci	int i;
13062306a36Sopenharmony_ci	int bit;
13162306a36Sopenharmony_ci	unsigned int tmp = 0;
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	if (n > 8 * sizeof(*value))
13462306a36Sopenharmony_ci		return -EINVAL;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	for (i = n; i > 0; i--) {
13762306a36Sopenharmony_ci		bit = rbsp_read_bit(rbsp);
13862306a36Sopenharmony_ci		if (bit < 0)
13962306a36Sopenharmony_ci			return bit;
14062306a36Sopenharmony_ci		tmp |= bit << (i - 1);
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	if (value)
14462306a36Sopenharmony_ci		*value = tmp;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return 0;
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_cistatic int rbsp_write_bits(struct rbsp *rbsp, int n, unsigned int value)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	int ret;
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	if (n > 8 * sizeof(value))
15462306a36Sopenharmony_ci		return -EINVAL;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	while (n--) {
15762306a36Sopenharmony_ci		ret = rbsp_write_bit(rbsp, (value >> n) & 1);
15862306a36Sopenharmony_ci		if (ret)
15962306a36Sopenharmony_ci			return ret;
16062306a36Sopenharmony_ci	}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	return 0;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int rbsp_read_uev(struct rbsp *rbsp, unsigned int *value)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	int leading_zero_bits = 0;
16862306a36Sopenharmony_ci	unsigned int tmp = 0;
16962306a36Sopenharmony_ci	int ret;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	while ((ret = rbsp_read_bit(rbsp)) == 0)
17262306a36Sopenharmony_ci		leading_zero_bits++;
17362306a36Sopenharmony_ci	if (ret < 0)
17462306a36Sopenharmony_ci		return ret;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	if (leading_zero_bits > 0) {
17762306a36Sopenharmony_ci		ret = rbsp_read_bits(rbsp, leading_zero_bits, &tmp);
17862306a36Sopenharmony_ci		if (ret)
17962306a36Sopenharmony_ci			return ret;
18062306a36Sopenharmony_ci	}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	if (value)
18362306a36Sopenharmony_ci		*value = (1 << leading_zero_bits) - 1 + tmp;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	return 0;
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cistatic int rbsp_write_uev(struct rbsp *rbsp, unsigned int *value)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	int ret;
19162306a36Sopenharmony_ci	int leading_zero_bits;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (!value)
19462306a36Sopenharmony_ci		return -EINVAL;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	leading_zero_bits = ilog2(*value + 1);
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	ret = rbsp_write_bits(rbsp, leading_zero_bits, 0);
19962306a36Sopenharmony_ci	if (ret)
20062306a36Sopenharmony_ci		return ret;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	return rbsp_write_bits(rbsp, leading_zero_bits + 1, *value + 1);
20362306a36Sopenharmony_ci}
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic int rbsp_read_sev(struct rbsp *rbsp, int *value)
20662306a36Sopenharmony_ci{
20762306a36Sopenharmony_ci	int ret;
20862306a36Sopenharmony_ci	unsigned int tmp;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	ret = rbsp_read_uev(rbsp, &tmp);
21162306a36Sopenharmony_ci	if (ret)
21262306a36Sopenharmony_ci		return ret;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (value) {
21562306a36Sopenharmony_ci		if (tmp & 1)
21662306a36Sopenharmony_ci			*value = (tmp + 1) / 2;
21762306a36Sopenharmony_ci		else
21862306a36Sopenharmony_ci			*value = -(tmp / 2);
21962306a36Sopenharmony_ci	}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	return 0;
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic int rbsp_write_sev(struct rbsp *rbsp, int *value)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	unsigned int tmp;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	if (!value)
22962306a36Sopenharmony_ci		return -EINVAL;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	if (*value > 0)
23262306a36Sopenharmony_ci		tmp = (2 * (*value)) | 1;
23362306a36Sopenharmony_ci	else
23462306a36Sopenharmony_ci		tmp = -2 * (*value);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ci	return rbsp_write_uev(rbsp, &tmp);
23762306a36Sopenharmony_ci}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_cistatic int __rbsp_write_bit(struct rbsp *rbsp, int *value)
24062306a36Sopenharmony_ci{
24162306a36Sopenharmony_ci	return rbsp_write_bit(rbsp, *value);
24262306a36Sopenharmony_ci}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_cistatic int __rbsp_write_bits(struct rbsp *rbsp, int n, unsigned int *value)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	return rbsp_write_bits(rbsp, n, *value);
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_cistruct nal_rbsp_ops write = {
25062306a36Sopenharmony_ci	.rbsp_bit = __rbsp_write_bit,
25162306a36Sopenharmony_ci	.rbsp_bits = __rbsp_write_bits,
25262306a36Sopenharmony_ci	.rbsp_uev = rbsp_write_uev,
25362306a36Sopenharmony_ci	.rbsp_sev = rbsp_write_sev,
25462306a36Sopenharmony_ci};
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic int __rbsp_read_bit(struct rbsp *rbsp, int *value)
25762306a36Sopenharmony_ci{
25862306a36Sopenharmony_ci	int tmp = rbsp_read_bit(rbsp);
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_ci	if (tmp < 0)
26162306a36Sopenharmony_ci		return tmp;
26262306a36Sopenharmony_ci	*value = tmp;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return 0;
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistruct nal_rbsp_ops read = {
26862306a36Sopenharmony_ci	.rbsp_bit = __rbsp_read_bit,
26962306a36Sopenharmony_ci	.rbsp_bits = rbsp_read_bits,
27062306a36Sopenharmony_ci	.rbsp_uev = rbsp_read_uev,
27162306a36Sopenharmony_ci	.rbsp_sev = rbsp_read_sev,
27262306a36Sopenharmony_ci};
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_civoid rbsp_bit(struct rbsp *rbsp, int *value)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	if (rbsp->error)
27762306a36Sopenharmony_ci		return;
27862306a36Sopenharmony_ci	rbsp->error = rbsp->ops->rbsp_bit(rbsp, value);
27962306a36Sopenharmony_ci}
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_civoid rbsp_bits(struct rbsp *rbsp, int n, int *value)
28262306a36Sopenharmony_ci{
28362306a36Sopenharmony_ci	if (rbsp->error)
28462306a36Sopenharmony_ci		return;
28562306a36Sopenharmony_ci	rbsp->error = rbsp->ops->rbsp_bits(rbsp, n, value);
28662306a36Sopenharmony_ci}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_civoid rbsp_uev(struct rbsp *rbsp, unsigned int *value)
28962306a36Sopenharmony_ci{
29062306a36Sopenharmony_ci	if (rbsp->error)
29162306a36Sopenharmony_ci		return;
29262306a36Sopenharmony_ci	rbsp->error = rbsp->ops->rbsp_uev(rbsp, value);
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_civoid rbsp_sev(struct rbsp *rbsp, int *value)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	if (rbsp->error)
29862306a36Sopenharmony_ci		return;
29962306a36Sopenharmony_ci	rbsp->error = rbsp->ops->rbsp_sev(rbsp, value);
30062306a36Sopenharmony_ci}
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_civoid rbsp_trailing_bits(struct rbsp *rbsp)
30362306a36Sopenharmony_ci{
30462306a36Sopenharmony_ci	unsigned int rbsp_stop_one_bit = 1;
30562306a36Sopenharmony_ci	unsigned int rbsp_alignment_zero_bit = 0;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	rbsp_bit(rbsp, &rbsp_stop_one_bit);
30862306a36Sopenharmony_ci	rbsp_bits(rbsp, round_up(rbsp->pos, 8) - rbsp->pos,
30962306a36Sopenharmony_ci		  &rbsp_alignment_zero_bit);
31062306a36Sopenharmony_ci}
311