Commit 85bdcb7e authored by Andrzej Pietrasiewicz's avatar Andrzej Pietrasiewicz Committed by Mauro Carvalho Chehab

media: hantro: Write the quantization tables in proper order

The quantization tables as defined in the file (luma_q_table,
chroma_q_table) are in fact in linear order. The JPEG file header, which is
not generated by the hardware, but must be programatically created with the
CPU, expects the table in zigzag order. On the other hand, the hardware
doesn't expect neither linear, nor zigzag order. Instead it expects the
quantization tables in vertical groups of four quantization parameters,
and the groups are organized in blocks of two vertically adjacent groups.
On top of that the blocks must be provided to the hardware in this order:
leftmost top block, leftmost bottom block, second leftmost top block,
second leftmost bottom block and so on. So, if this is the quantization
table in linear order:

0x10, 0x0b, 0x0a, 0x10, 0x18, 0x28, 0x33, 0x3d,
0x0c, 0x0c, 0x0e, 0x13, 0x1a, 0x3a, 0x3c, 0x37,
0x0e, 0x0d, 0x10, 0x18, 0x28, 0x39, 0x45, 0x38,
0x0e, 0x11, 0x16, 0x1d, 0x33, 0x57, 0x50, 0x3e,
0x12, 0x16, 0x25, 0x38, 0x44, 0x6d, 0x67, 0x4d,
0x18, 0x23, 0x37, 0x40, 0x51, 0x68, 0x71, 0x5c,
0x31, 0x40, 0x4e, 0x57, 0x67, 0x79, 0x78, 0x65,
0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63

then the hardware expects this in its consecutive registers:

0x100c0e0e,
0x0b0c0d11,
0x12183148,
0x1623405c,
0x0a0e1016,
0x1013181d,
0x25374e5f,
0x38405762,

and so on.

Consequently, the same area of memory cannot be used both for dumping it
into the JPEG file header and writing its contents to the hardware
registers. Instead, a separate pair of arrays is added for properly
reordered quantization tables, to be read with get_unaligned_be32()
and linearly written to the registers.

The "ctx" parameter is not needed any more for hantro_jpeg_get_qtable().
Signed-off-by: default avatarAndrzej Pietrasiewicz <andrzej.p@collabora.com>
Tested-by: default avatarEzequiel Garcia <ezequiel@collabora.com>
Signed-off-by: default avatarHans Verkuil <hverkuil-cisco@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+huawei@kernel.org>
parent 801fccf4
...@@ -108,8 +108,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx) ...@@ -108,8 +108,8 @@ void hantro_h1_jpeg_enc_run(struct hantro_ctx *ctx)
hantro_h1_set_src_img_ctrl(vpu, ctx); hantro_h1_set_src_img_ctrl(vpu, ctx);
hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf); hantro_h1_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
hantro_h1_jpeg_enc_set_qtable(vpu, hantro_h1_jpeg_enc_set_qtable(vpu,
hantro_jpeg_get_qtable(&jpeg_ctx, 0), hantro_jpeg_get_qtable(0),
hantro_jpeg_get_qtable(&jpeg_ctx, 1)); hantro_jpeg_get_qtable(1));
reg = H1_REG_AXI_CTRL_OUTPUT_SWAP16 reg = H1_REG_AXI_CTRL_OUTPUT_SWAP16
| H1_REG_AXI_CTRL_INPUT_SWAP16 | H1_REG_AXI_CTRL_INPUT_SWAP16
......
...@@ -36,6 +36,8 @@ static const unsigned char luma_q_table[] = { ...@@ -36,6 +36,8 @@ static const unsigned char luma_q_table[] = {
0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63 0x48, 0x5c, 0x5f, 0x62, 0x70, 0x64, 0x67, 0x63
}; };
static unsigned char luma_q_table_reordered[ARRAY_SIZE(luma_q_table)];
static const unsigned char chroma_q_table[] = { static const unsigned char chroma_q_table[] = {
0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63, 0x11, 0x12, 0x18, 0x2f, 0x63, 0x63, 0x63, 0x63,
0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63, 0x12, 0x15, 0x1a, 0x42, 0x63, 0x63, 0x63, 0x63,
...@@ -47,6 +49,30 @@ static const unsigned char chroma_q_table[] = { ...@@ -47,6 +49,30 @@ static const unsigned char chroma_q_table[] = {
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63
}; };
static unsigned char chroma_q_table_reordered[ARRAY_SIZE(chroma_q_table)];
static const unsigned char zigzag[64] = {
0, 1, 8, 16, 9, 2, 3, 10,
17, 24, 32, 25, 18, 11, 4, 5,
12, 19, 26, 33, 40, 48, 41, 34,
27, 20, 13, 6, 7, 14, 21, 28,
35, 42, 49, 56, 57, 50, 43, 36,
29, 22, 15, 23, 30, 37, 44, 51,
58, 59, 52, 45, 38, 31, 39, 46,
53, 60, 61, 54, 47, 55, 62, 63
};
static const u32 hw_reorder[64] = {
0, 8, 16, 24, 1, 9, 17, 25,
32, 40, 48, 56, 33, 41, 49, 57,
2, 10, 18, 26, 3, 11, 19, 27,
34, 42, 50, 58, 35, 43, 51, 59,
4, 12, 20, 28, 5, 13, 21, 29,
36, 44, 52, 60, 37, 45, 53, 61,
6, 14, 22, 30, 7, 15, 23, 31,
38, 46, 54, 62, 39, 47, 55, 63
};
/* Huffman tables are shared with CODA */ /* Huffman tables are shared with CODA */
static const unsigned char luma_dc_table[] = { static const unsigned char luma_dc_table[] = {
0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
...@@ -225,20 +251,29 @@ static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = { ...@@ -225,20 +251,29 @@ static const unsigned char hantro_jpeg_header[JPEG_HEADER_SIZE] = {
0x11, 0x03, 0x11, 0x00, 0x3f, 0x00, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00,
}; };
static unsigned char jpeg_scale_qp(const unsigned char qp, int scale)
{
unsigned int temp;
temp = DIV_ROUND_CLOSEST((unsigned int)qp * scale, 100);
if (temp <= 0)
temp = 1;
if (temp > 255)
temp = 255;
return (unsigned char)temp;
}
static void static void
jpeg_scale_quant_table(unsigned char *q_tab, jpeg_scale_quant_table(unsigned char *file_q_tab,
unsigned char *reordered_q_tab,
const unsigned char *tab, int scale) const unsigned char *tab, int scale)
{ {
unsigned int temp;
int i; int i;
for (i = 0; i < 64; i++) { for (i = 0; i < 64; i++) {
temp = DIV_ROUND_CLOSEST((unsigned int)tab[i] * scale, 100); file_q_tab[i] = jpeg_scale_qp(tab[zigzag[i]], scale);
if (temp <= 0) reordered_q_tab[i] = jpeg_scale_qp(tab[hw_reorder[i]], scale);
temp = 1;
if (temp > 255)
temp = 255;
q_tab[i] = (unsigned char)temp;
} }
} }
...@@ -256,17 +291,18 @@ static void jpeg_set_quality(unsigned char *buffer, int quality) ...@@ -256,17 +291,18 @@ static void jpeg_set_quality(unsigned char *buffer, int quality)
scale = 200 - 2 * quality; scale = 200 - 2 * quality;
jpeg_scale_quant_table(buffer + LUMA_QUANT_OFF, jpeg_scale_quant_table(buffer + LUMA_QUANT_OFF,
luma_q_table_reordered,
luma_q_table, scale); luma_q_table, scale);
jpeg_scale_quant_table(buffer + CHROMA_QUANT_OFF, jpeg_scale_quant_table(buffer + CHROMA_QUANT_OFF,
chroma_q_table_reordered,
chroma_q_table, scale); chroma_q_table, scale);
} }
unsigned char * unsigned char *hantro_jpeg_get_qtable(int index)
hantro_jpeg_get_qtable(struct hantro_jpeg_ctx *ctx, int index)
{ {
if (index == 0) if (index == 0)
return ctx->buffer + LUMA_QUANT_OFF; return luma_q_table_reordered;
return ctx->buffer + CHROMA_QUANT_OFF; return chroma_q_table_reordered;
} }
void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx) void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx)
......
...@@ -9,5 +9,5 @@ struct hantro_jpeg_ctx { ...@@ -9,5 +9,5 @@ struct hantro_jpeg_ctx {
unsigned char *buffer; unsigned char *buffer;
}; };
unsigned char *hantro_jpeg_get_qtable(struct hantro_jpeg_ctx *ctx, int index); unsigned char *hantro_jpeg_get_qtable(int index);
void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx); void hantro_jpeg_header_assemble(struct hantro_jpeg_ctx *ctx);
...@@ -18,9 +18,8 @@ ...@@ -18,9 +18,8 @@
* *
* Quantization luma table values are written to registers * Quantization luma table values are written to registers
* VEPU_swreg_0-VEPU_swreg_15, and chroma table values to * VEPU_swreg_0-VEPU_swreg_15, and chroma table values to
* VEPU_swreg_16-VEPU_swreg_31. * VEPU_swreg_16-VEPU_swreg_31. A special order is needed, neither
* * zigzag, nor linear.
* JPEG zigzag order is expected on the quantization tables.
*/ */
#include <asm/unaligned.h> #include <asm/unaligned.h>
...@@ -139,8 +138,8 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx) ...@@ -139,8 +138,8 @@ void rk3399_vpu_jpeg_enc_run(struct hantro_ctx *ctx)
rk3399_vpu_set_src_img_ctrl(vpu, ctx); rk3399_vpu_set_src_img_ctrl(vpu, ctx);
rk3399_vpu_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf); rk3399_vpu_jpeg_enc_set_buffers(vpu, ctx, &src_buf->vb2_buf);
rk3399_vpu_jpeg_enc_set_qtable(vpu, rk3399_vpu_jpeg_enc_set_qtable(vpu,
hantro_jpeg_get_qtable(&jpeg_ctx, 0), hantro_jpeg_get_qtable(0),
hantro_jpeg_get_qtable(&jpeg_ctx, 1)); hantro_jpeg_get_qtable(1));
reg = VEPU_REG_OUTPUT_SWAP32 reg = VEPU_REG_OUTPUT_SWAP32
| VEPU_REG_OUTPUT_SWAP16 | VEPU_REG_OUTPUT_SWAP16
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment