This source file includes following definitions.
- vdec_1_load_firmware
- vdec_1_stbuf_power_up
- vdec_1_conf_esparser
- vdec_1_vififo_level
- vdec_1_stop
- vdec_1_start
1
2
3
4
5
6
7
8
9
10 #include <linux/firmware.h>
11 #include <linux/clk.h>
12
13 #include "vdec_1.h"
14 #include "vdec_helpers.h"
15 #include "dos_regs.h"
16
17
18 #define AO_RTI_GEN_PWR_SLEEP0 0xe8
19 #define AO_RTI_GEN_PWR_ISO0 0xec
20 #define GEN_PWR_VDEC_1 (BIT(3) | BIT(2))
21
22 #define MC_SIZE (4096 * 4)
23
24 static int
25 vdec_1_load_firmware(struct amvdec_session *sess, const char *fwname)
26 {
27 const struct firmware *fw;
28 struct amvdec_core *core = sess->core;
29 struct device *dev = core->dev_dec;
30 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
31 static void *mc_addr;
32 static dma_addr_t mc_addr_map;
33 int ret;
34 u32 i = 1000;
35
36 ret = request_firmware(&fw, fwname, dev);
37 if (ret < 0)
38 return -EINVAL;
39
40 if (fw->size < MC_SIZE) {
41 dev_err(dev, "Firmware size %zu is too small. Expected %u.\n",
42 fw->size, MC_SIZE);
43 ret = -EINVAL;
44 goto release_firmware;
45 }
46
47 mc_addr = dma_alloc_coherent(core->dev, MC_SIZE,
48 &mc_addr_map, GFP_KERNEL);
49 if (!mc_addr) {
50 ret = -ENOMEM;
51 goto release_firmware;
52 }
53
54 memcpy(mc_addr, fw->data, MC_SIZE);
55
56 amvdec_write_dos(core, MPSR, 0);
57 amvdec_write_dos(core, CPSR, 0);
58
59 amvdec_clear_dos_bits(core, MDEC_PIC_DC_CTRL, BIT(31));
60
61 amvdec_write_dos(core, IMEM_DMA_ADR, mc_addr_map);
62 amvdec_write_dos(core, IMEM_DMA_COUNT, MC_SIZE / 4);
63 amvdec_write_dos(core, IMEM_DMA_CTRL, (0x8000 | (7 << 16)));
64
65 while (--i && amvdec_read_dos(core, IMEM_DMA_CTRL) & 0x8000);
66
67 if (i == 0) {
68 dev_err(dev, "Firmware load fail (DMA hang?)\n");
69 ret = -EINVAL;
70 goto free_mc;
71 }
72
73 if (codec_ops->load_extended_firmware)
74 ret = codec_ops->load_extended_firmware(sess,
75 fw->data + MC_SIZE,
76 fw->size - MC_SIZE);
77
78 free_mc:
79 dma_free_coherent(core->dev, MC_SIZE, mc_addr, mc_addr_map);
80 release_firmware:
81 release_firmware(fw);
82 return ret;
83 }
84
85 static int vdec_1_stbuf_power_up(struct amvdec_session *sess)
86 {
87 struct amvdec_core *core = sess->core;
88
89 amvdec_write_dos(core, VLD_MEM_VIFIFO_CONTROL, 0);
90 amvdec_write_dos(core, VLD_MEM_VIFIFO_WRAP_COUNT, 0);
91 amvdec_write_dos(core, POWER_CTL_VLD, BIT(4));
92
93 amvdec_write_dos(core, VLD_MEM_VIFIFO_START_PTR, sess->vififo_paddr);
94 amvdec_write_dos(core, VLD_MEM_VIFIFO_CURR_PTR, sess->vififo_paddr);
95 amvdec_write_dos(core, VLD_MEM_VIFIFO_END_PTR,
96 sess->vififo_paddr + sess->vififo_size - 8);
97
98 amvdec_write_dos_bits(core, VLD_MEM_VIFIFO_CONTROL, 1);
99 amvdec_clear_dos_bits(core, VLD_MEM_VIFIFO_CONTROL, 1);
100
101 amvdec_write_dos(core, VLD_MEM_VIFIFO_BUF_CNTL, MEM_BUFCTRL_MANUAL);
102 amvdec_write_dos(core, VLD_MEM_VIFIFO_WP, sess->vififo_paddr);
103
104 amvdec_write_dos_bits(core, VLD_MEM_VIFIFO_BUF_CNTL, 1);
105 amvdec_clear_dos_bits(core, VLD_MEM_VIFIFO_BUF_CNTL, 1);
106
107 amvdec_write_dos_bits(core, VLD_MEM_VIFIFO_CONTROL,
108 (0x11 << MEM_FIFO_CNT_BIT) | MEM_FILL_ON_LEVEL |
109 MEM_CTRL_FILL_EN | MEM_CTRL_EMPTY_EN);
110
111 return 0;
112 }
113
114 static void vdec_1_conf_esparser(struct amvdec_session *sess)
115 {
116 struct amvdec_core *core = sess->core;
117
118
119 amvdec_write_dos(core, DOS_GEN_CTRL0, 0);
120 amvdec_write_dos(core, VLD_MEM_VIFIFO_BUF_CNTL, 1);
121 amvdec_clear_dos_bits(core, VLD_MEM_VIFIFO_BUF_CNTL, 1);
122 }
123
124 static u32 vdec_1_vififo_level(struct amvdec_session *sess)
125 {
126 struct amvdec_core *core = sess->core;
127
128 return amvdec_read_dos(core, VLD_MEM_VIFIFO_LEVEL);
129 }
130
131 static int vdec_1_stop(struct amvdec_session *sess)
132 {
133 struct amvdec_core *core = sess->core;
134 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
135
136 amvdec_write_dos(core, MPSR, 0);
137 amvdec_write_dos(core, CPSR, 0);
138 amvdec_write_dos(core, ASSIST_MBOX1_MASK, 0);
139
140 amvdec_write_dos(core, DOS_SW_RESET0, BIT(12) | BIT(11));
141 amvdec_write_dos(core, DOS_SW_RESET0, 0);
142 amvdec_read_dos(core, DOS_SW_RESET0);
143
144
145 regmap_write(core->regmap_ao, AO_RTI_GEN_PWR_ISO0, 0xc0);
146
147 amvdec_write_dos(core, DOS_MEM_PD_VDEC, 0xffffffff);
148
149 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
150 GEN_PWR_VDEC_1, GEN_PWR_VDEC_1);
151
152 clk_disable_unprepare(core->vdec_1_clk);
153
154 if (sess->priv)
155 codec_ops->stop(sess);
156
157 return 0;
158 }
159
160 static int vdec_1_start(struct amvdec_session *sess)
161 {
162 int ret;
163 struct amvdec_core *core = sess->core;
164 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops;
165
166
167 clk_set_rate(core->vdec_1_clk, 666666666);
168 ret = clk_prepare_enable(core->vdec_1_clk);
169 if (ret)
170 return ret;
171
172
173 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0,
174 GEN_PWR_VDEC_1, 0);
175 usleep_range(10, 20);
176
177
178 amvdec_write_dos(core, DOS_SW_RESET0, 0xfffffffc);
179 amvdec_write_dos(core, DOS_SW_RESET0, 0x00000000);
180
181 amvdec_write_dos(core, DOS_GCLK_EN0, 0x3ff);
182
183
184 amvdec_write_dos(core, DOS_MEM_PD_VDEC, 0);
185
186 regmap_write(core->regmap_ao, AO_RTI_GEN_PWR_ISO0, 0);
187
188 amvdec_write_dos(core, DOS_VDEC_MCRCC_STALL_CTRL, 0);
189
190 amvdec_write_dos(core, GCLK_EN, 0x3ff);
191 amvdec_clear_dos_bits(core, MDEC_PIC_DC_CTRL, BIT(31));
192
193 vdec_1_stbuf_power_up(sess);
194
195 ret = vdec_1_load_firmware(sess, sess->fmt_out->firmware_path);
196 if (ret)
197 goto stop;
198
199 ret = codec_ops->start(sess);
200 if (ret)
201 goto stop;
202
203
204 amvdec_write_dos(core, ASSIST_MBOX1_CLR_REG, 1);
205 amvdec_write_dos(core, ASSIST_MBOX1_MASK, 1);
206
207
208 if (sess->pixfmt_cap == V4L2_PIX_FMT_NV12M)
209 amvdec_write_dos_bits(core, MDEC_PIC_DC_CTRL, BIT(17));
210 else
211 amvdec_clear_dos_bits(core, MDEC_PIC_DC_CTRL, BIT(17));
212
213
214 amvdec_write_dos(core, MPSR, 1);
215
216 usleep_range(10, 20);
217
218 return 0;
219
220 stop:
221 vdec_1_stop(sess);
222 return ret;
223 }
224
225 struct amvdec_ops vdec_1_ops = {
226 .start = vdec_1_start,
227 .stop = vdec_1_stop,
228 .conf_esparser = vdec_1_conf_esparser,
229 .vififo_level = vdec_1_vififo_level,
230 };