Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / staging / media / hantro / rk3288_vpu_hw.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Hantro VPU codec driver
4  *
5  * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
6  *      Jeffy Chen <jeffy.chen@rock-chips.com>
7  */
8
9 #include <linux/clk.h>
10
11 #include "hantro.h"
12 #include "hantro_jpeg.h"
13 #include "hantro_g1_regs.h"
14 #include "hantro_h1_regs.h"
15
16 #define RK3288_ACLK_MAX_FREQ (400 * 1000 * 1000)
17
18 /*
19  * Supported formats.
20  */
21
22 static const struct hantro_fmt rk3288_vpu_enc_fmts[] = {
23         {
24                 .fourcc = V4L2_PIX_FMT_YUV420M,
25                 .codec_mode = HANTRO_MODE_NONE,
26                 .enc_fmt = RK3288_VPU_ENC_FMT_YUV420P,
27         },
28         {
29                 .fourcc = V4L2_PIX_FMT_NV12M,
30                 .codec_mode = HANTRO_MODE_NONE,
31                 .enc_fmt = RK3288_VPU_ENC_FMT_YUV420SP,
32         },
33         {
34                 .fourcc = V4L2_PIX_FMT_YUYV,
35                 .codec_mode = HANTRO_MODE_NONE,
36                 .enc_fmt = RK3288_VPU_ENC_FMT_YUYV422,
37         },
38         {
39                 .fourcc = V4L2_PIX_FMT_UYVY,
40                 .codec_mode = HANTRO_MODE_NONE,
41                 .enc_fmt = RK3288_VPU_ENC_FMT_UYVY422,
42         },
43         {
44                 .fourcc = V4L2_PIX_FMT_JPEG,
45                 .codec_mode = HANTRO_MODE_JPEG_ENC,
46                 .max_depth = 2,
47                 .header_size = JPEG_HEADER_SIZE,
48                 .frmsize = {
49                         .min_width = 96,
50                         .max_width = 8192,
51                         .step_width = JPEG_MB_DIM,
52                         .min_height = 32,
53                         .max_height = 8192,
54                         .step_height = JPEG_MB_DIM,
55                 },
56         },
57 };
58
59 static const struct hantro_fmt rk3288_vpu_dec_fmts[] = {
60         {
61                 .fourcc = V4L2_PIX_FMT_NV12,
62                 .codec_mode = HANTRO_MODE_NONE,
63         },
64         {
65                 .fourcc = V4L2_PIX_FMT_MPEG2_SLICE,
66                 .codec_mode = HANTRO_MODE_MPEG2_DEC,
67                 .max_depth = 2,
68                 .frmsize = {
69                         .min_width = 48,
70                         .max_width = 1920,
71                         .step_width = MPEG2_MB_DIM,
72                         .min_height = 48,
73                         .max_height = 1088,
74                         .step_height = MPEG2_MB_DIM,
75                 },
76         },
77 };
78
79 static irqreturn_t rk3288_vepu_irq(int irq, void *dev_id)
80 {
81         struct hantro_dev *vpu = dev_id;
82         enum vb2_buffer_state state;
83         u32 status, bytesused;
84
85         status = vepu_read(vpu, H1_REG_INTERRUPT);
86         bytesused = vepu_read(vpu, H1_REG_STR_BUF_LIMIT) / 8;
87         state = (status & H1_REG_INTERRUPT_FRAME_RDY) ?
88                 VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
89
90         vepu_write(vpu, 0, H1_REG_INTERRUPT);
91         vepu_write(vpu, 0, H1_REG_AXI_CTRL);
92
93         hantro_irq_done(vpu, bytesused, state);
94
95         return IRQ_HANDLED;
96 }
97
98 static irqreturn_t rk3288_vdpu_irq(int irq, void *dev_id)
99 {
100         struct hantro_dev *vpu = dev_id;
101         enum vb2_buffer_state state;
102         u32 status;
103
104         status = vdpu_read(vpu, G1_REG_INTERRUPT);
105         state = (status & G1_REG_INTERRUPT_DEC_RDY_INT) ?
106                 VB2_BUF_STATE_DONE : VB2_BUF_STATE_ERROR;
107
108         vdpu_write(vpu, 0, G1_REG_INTERRUPT);
109         vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
110
111         hantro_irq_done(vpu, 0, state);
112
113         return IRQ_HANDLED;
114 }
115
116 static int rk3288_vpu_hw_init(struct hantro_dev *vpu)
117 {
118         /* Bump ACLK to max. possible freq. to improve performance. */
119         clk_set_rate(vpu->clocks[0].clk, RK3288_ACLK_MAX_FREQ);
120         return 0;
121 }
122
123 static void rk3288_vpu_enc_reset(struct hantro_ctx *ctx)
124 {
125         struct hantro_dev *vpu = ctx->dev;
126
127         vepu_write(vpu, H1_REG_INTERRUPT_DIS_BIT, H1_REG_INTERRUPT);
128         vepu_write(vpu, 0, H1_REG_ENC_CTRL);
129         vepu_write(vpu, 0, H1_REG_AXI_CTRL);
130 }
131
132 static void rk3288_vpu_dec_reset(struct hantro_ctx *ctx)
133 {
134         struct hantro_dev *vpu = ctx->dev;
135
136         vdpu_write(vpu, G1_REG_INTERRUPT_DEC_IRQ_DIS, G1_REG_INTERRUPT);
137         vdpu_write(vpu, G1_REG_CONFIG_DEC_CLK_GATE_E, G1_REG_CONFIG);
138         vdpu_write(vpu, 1, G1_REG_SOFT_RESET);
139 }
140
141 /*
142  * Supported codec ops.
143  */
144
145 static const struct hantro_codec_ops rk3288_vpu_codec_ops[] = {
146         [HANTRO_MODE_JPEG_ENC] = {
147                 .run = hantro_h1_jpeg_enc_run,
148                 .reset = rk3288_vpu_enc_reset,
149                 .init = hantro_jpeg_enc_init,
150                 .exit = hantro_jpeg_enc_exit,
151         },
152         [HANTRO_MODE_MPEG2_DEC] = {
153                 .run = hantro_g1_mpeg2_dec_run,
154                 .reset = rk3288_vpu_dec_reset,
155                 .init = hantro_mpeg2_dec_init,
156                 .exit = hantro_mpeg2_dec_exit,
157         },
158 };
159
160 /*
161  * VPU variant.
162  */
163
164 static const struct hantro_irq rk3288_irqs[] = {
165         { "vepu", rk3288_vepu_irq },
166         { "vdpu", rk3288_vdpu_irq },
167 };
168
169 static const char * const rk3288_clk_names[] = {
170         "aclk", "hclk"
171 };
172
173 const struct hantro_variant rk3288_vpu_variant = {
174         .enc_offset = 0x0,
175         .enc_fmts = rk3288_vpu_enc_fmts,
176         .num_enc_fmts = ARRAY_SIZE(rk3288_vpu_enc_fmts),
177         .dec_offset = 0x400,
178         .dec_fmts = rk3288_vpu_dec_fmts,
179         .num_dec_fmts = ARRAY_SIZE(rk3288_vpu_dec_fmts),
180         .codec = HANTRO_JPEG_ENCODER | HANTRO_MPEG2_DECODER,
181         .codec_ops = rk3288_vpu_codec_ops,
182         .irqs = rk3288_irqs,
183         .num_irqs = ARRAY_SIZE(rk3288_irqs),
184         .init = rk3288_vpu_hw_init,
185         .clk_names = rk3288_clk_names,
186         .num_clocks = ARRAY_SIZE(rk3288_clk_names)
187 };