xref: /linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * linux/drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c
4  *
5  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
6  *		http://www.samsung.com/
7  */
8 
9 #include <linux/delay.h>
10 #include <linux/err.h>
11 #include <linux/firmware.h>
12 #include <linux/jiffies.h>
13 #include <linux/sched.h>
14 #include "s5p_mfc_cmd.h"
15 #include "s5p_mfc_common.h"
16 #include "s5p_mfc_debug.h"
17 #include "s5p_mfc_intr.h"
18 #include "s5p_mfc_opr.h"
19 #include "s5p_mfc_pm.h"
20 #include "s5p_mfc_ctrl.h"
21 
22 /* Allocate memory for firmware */
s5p_mfc_alloc_firmware(struct s5p_mfc_dev * dev)23 int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
24 {
25 	struct s5p_mfc_priv_buf *fw_buf = &dev->fw_buf;
26 	int err;
27 
28 	fw_buf->size = dev->variant->buf_size->fw;
29 
30 	if (fw_buf->virt) {
31 		mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
32 		return -ENOMEM;
33 	}
34 
35 	err = s5p_mfc_alloc_priv_buf(dev, BANK_L_CTX, &dev->fw_buf);
36 	if (err) {
37 		mfc_err("Allocating bitprocessor buffer failed\n");
38 		return err;
39 	}
40 
41 	return 0;
42 }
43 
44 /* Load firmware */
s5p_mfc_load_firmware(struct s5p_mfc_dev * dev)45 int s5p_mfc_load_firmware(struct s5p_mfc_dev *dev)
46 {
47 	struct firmware *fw_blob;
48 	int i, err = -EINVAL;
49 
50 	/* Firmware has to be present as a separate file or compiled
51 	 * into kernel. */
52 	mfc_debug_enter();
53 
54 	/* In case of MFC v12, RET_SYS_INIT response from hardware fails due to
55 	 * incorrect firmware transfer and therefore it is not able to initialize
56 	 * the hardware. This causes failed response for SYS_INIT command when
57 	 * MFC runs for second time. So, load the MFC v12 firmware for each run.
58 	 */
59 	if (!IS_MFCV12(dev))
60 		if (dev->fw_get_done)
61 			return 0;
62 
63 	for (i = MFC_FW_MAX_VERSIONS - 1; i >= 0; i--) {
64 		if (!dev->variant->fw_name[i])
65 			continue;
66 		err = request_firmware((const struct firmware **)&fw_blob,
67 				dev->variant->fw_name[i], &dev->plat_dev->dev);
68 		if (!err) {
69 			dev->fw_ver = (enum s5p_mfc_fw_ver) i;
70 			break;
71 		}
72 	}
73 
74 	if (err != 0) {
75 		mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
76 		return -EINVAL;
77 	}
78 	if (fw_blob->size > dev->fw_buf.size) {
79 		mfc_err("MFC firmware is too big to be loaded\n");
80 		release_firmware(fw_blob);
81 		return -ENOMEM;
82 	}
83 	memcpy(dev->fw_buf.virt, fw_blob->data, fw_blob->size);
84 	wmb();
85 	dev->fw_get_done = true;
86 	release_firmware(fw_blob);
87 	mfc_debug_leave();
88 	return 0;
89 }
90 
91 /* Release firmware memory */
s5p_mfc_release_firmware(struct s5p_mfc_dev * dev)92 int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
93 {
94 	/* Before calling this function one has to make sure
95 	 * that MFC is no longer processing */
96 	s5p_mfc_release_priv_buf(dev, &dev->fw_buf);
97 	dev->fw_get_done = false;
98 	return 0;
99 }
100 
s5p_mfc_bus_reset(struct s5p_mfc_dev * dev)101 static int s5p_mfc_bus_reset(struct s5p_mfc_dev *dev)
102 {
103 	unsigned int status;
104 	unsigned long timeout;
105 
106 	/* Reset */
107 	mfc_write(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL);
108 	timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
109 	/* Check bus status */
110 	do {
111 		if (time_after(jiffies, timeout)) {
112 			mfc_err("Timeout while resetting MFC.\n");
113 			return -EIO;
114 		}
115 		status = mfc_read(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
116 	} while ((status & 0x2) == 0);
117 	return 0;
118 }
119 
120 /* Reset the device */
s5p_mfc_reset(struct s5p_mfc_dev * dev)121 int s5p_mfc_reset(struct s5p_mfc_dev *dev)
122 {
123 	unsigned int mc_status;
124 	unsigned long timeout;
125 	int i;
126 
127 	mfc_debug_enter();
128 
129 	if (IS_MFCV6_PLUS(dev)) {
130 		/* Zero Initialization of MFC registers */
131 		mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
132 		mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
133 		mfc_write(dev, 0, S5P_FIMV_FW_VERSION_V6);
134 
135 		for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
136 			mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
137 
138 		/* check bus reset control before reset */
139 		if (dev->risc_on && !IS_MFCV12(dev))
140 			if (s5p_mfc_bus_reset(dev))
141 				return -EIO;
142 		/* Reset
143 		 * set RISC_ON to 0 during power_on & wake_up.
144 		 * V6 needs RISC_ON set to 0 during reset also.
145 		 */
146 		if ((!dev->risc_on) || (!IS_MFCV7_PLUS(dev)))
147 			mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
148 
149 		mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
150 		mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
151 	} else {
152 		/* Stop procedure */
153 		/*  reset RISC */
154 		mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
155 		/*  All reset except for MC */
156 		mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
157 		mdelay(10);
158 
159 		timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
160 		/* Check MC status */
161 		do {
162 			if (time_after(jiffies, timeout)) {
163 				mfc_err("Timeout while resetting MFC\n");
164 				return -EIO;
165 			}
166 
167 			mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
168 
169 		} while (mc_status & 0x3);
170 
171 		mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
172 		mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
173 	}
174 
175 	mfc_debug_leave();
176 	return 0;
177 }
178 
s5p_mfc_init_memctrl(struct s5p_mfc_dev * dev)179 static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
180 {
181 	if (IS_MFCV6_PLUS(dev)) {
182 		mfc_write(dev, dev->dma_base[BANK_L_CTX],
183 			  S5P_FIMV_RISC_BASE_ADDRESS_V6);
184 		mfc_debug(2, "Base Address : %pad\n",
185 			  &dev->dma_base[BANK_L_CTX]);
186 	} else {
187 		mfc_write(dev, dev->dma_base[BANK_L_CTX],
188 			  S5P_FIMV_MC_DRAMBASE_ADR_A);
189 		mfc_write(dev, dev->dma_base[BANK_R_CTX],
190 			  S5P_FIMV_MC_DRAMBASE_ADR_B);
191 		mfc_debug(2, "Bank1: %pad, Bank2: %pad\n",
192 			  &dev->dma_base[BANK_L_CTX],
193 			  &dev->dma_base[BANK_R_CTX]);
194 	}
195 }
196 
s5p_mfc_clear_cmds(struct s5p_mfc_dev * dev)197 static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
198 {
199 	if (IS_MFCV6_PLUS(dev)) {
200 		/* Zero initialization should be done before RESET.
201 		 * Nothing to do here. */
202 	} else {
203 		mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
204 		mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
205 		mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
206 		mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
207 	}
208 }
209 
210 /* Initialize hardware */
s5p_mfc_init_hw(struct s5p_mfc_dev * dev)211 int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
212 {
213 	unsigned int ver;
214 	int ret;
215 
216 	mfc_debug_enter();
217 	if (!dev->fw_buf.virt) {
218 		mfc_err("Firmware memory is not allocated.\n");
219 		return -EINVAL;
220 	}
221 
222 	/* 0. MFC reset */
223 	mfc_debug(2, "MFC reset..\n");
224 	s5p_mfc_clock_on(dev);
225 	dev->risc_on = 0;
226 	ret = s5p_mfc_reset(dev);
227 	if (ret) {
228 		mfc_err("Failed to reset MFC - timeout\n");
229 		return ret;
230 	}
231 	mfc_debug(2, "Done MFC reset..\n");
232 	/* 1. Set DRAM base Addr */
233 	s5p_mfc_init_memctrl(dev);
234 	/* 2. Initialize registers of channel I/F */
235 	s5p_mfc_clear_cmds(dev);
236 	/* 3. Release reset signal to the RISC */
237 	s5p_mfc_clean_dev_int_flags(dev);
238 	if (IS_MFCV6_PLUS(dev)) {
239 		dev->risc_on = 1;
240 		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
241 	}
242 	else
243 		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
244 
245 	if (IS_MFCV10_PLUS(dev))
246 		mfc_write(dev, 0x0, S5P_FIMV_MFC_CLOCK_OFF_V10);
247 
248 	mfc_debug(2, "Will now wait for completion of firmware transfer\n");
249 	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
250 		mfc_err("Failed to load firmware\n");
251 		s5p_mfc_reset(dev);
252 		s5p_mfc_clock_off(dev);
253 		return -EIO;
254 	}
255 	s5p_mfc_clean_dev_int_flags(dev);
256 	/* 4. Initialize firmware */
257 	ret = s5p_mfc_hw_call(dev->mfc_cmds, sys_init_cmd, dev);
258 	if (ret) {
259 		mfc_err("Failed to send command to MFC - timeout\n");
260 		s5p_mfc_reset(dev);
261 		s5p_mfc_clock_off(dev);
262 		return ret;
263 	}
264 	mfc_debug(2, "Ok, now will wait for completion of hardware init\n");
265 	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SYS_INIT_RET)) {
266 		mfc_err("Failed to init hardware\n");
267 		s5p_mfc_reset(dev);
268 		s5p_mfc_clock_off(dev);
269 		return -EIO;
270 	}
271 	dev->int_cond = 0;
272 	if (dev->int_err != 0 || dev->int_type !=
273 					S5P_MFC_R2H_CMD_SYS_INIT_RET) {
274 		/* Failure. */
275 		mfc_err("Failed to init firmware - error: %d int: %d\n",
276 						dev->int_err, dev->int_type);
277 		s5p_mfc_reset(dev);
278 		s5p_mfc_clock_off(dev);
279 		return -EIO;
280 	}
281 	if (IS_MFCV6_PLUS(dev))
282 		ver = mfc_read(dev, S5P_FIMV_FW_VERSION_V6);
283 	else
284 		ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
285 
286 	mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
287 		(ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
288 	s5p_mfc_clock_off(dev);
289 	mfc_debug_leave();
290 	return 0;
291 }
292 
293 
294 /* Deinitialize hardware */
s5p_mfc_deinit_hw(struct s5p_mfc_dev * dev)295 void s5p_mfc_deinit_hw(struct s5p_mfc_dev *dev)
296 {
297 	s5p_mfc_clock_on(dev);
298 
299 	s5p_mfc_reset(dev);
300 	s5p_mfc_hw_call(dev->mfc_ops, release_dev_context_buffer, dev);
301 
302 	s5p_mfc_clock_off(dev);
303 }
304 
s5p_mfc_sleep(struct s5p_mfc_dev * dev)305 int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
306 {
307 	int ret;
308 
309 	mfc_debug_enter();
310 	s5p_mfc_clock_on(dev);
311 	s5p_mfc_clean_dev_int_flags(dev);
312 	ret = s5p_mfc_hw_call(dev->mfc_cmds, sleep_cmd, dev);
313 	if (ret) {
314 		mfc_err("Failed to send command to MFC - timeout\n");
315 		return ret;
316 	}
317 	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_SLEEP_RET)) {
318 		mfc_err("Failed to sleep\n");
319 		return -EIO;
320 	}
321 	s5p_mfc_clock_off(dev);
322 	dev->int_cond = 0;
323 	if (dev->int_err != 0 || dev->int_type !=
324 						S5P_MFC_R2H_CMD_SLEEP_RET) {
325 		/* Failure. */
326 		mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
327 								dev->int_type);
328 		return -EIO;
329 	}
330 	mfc_debug_leave();
331 	return ret;
332 }
333 
s5p_mfc_v8_wait_wakeup(struct s5p_mfc_dev * dev)334 static int s5p_mfc_v8_wait_wakeup(struct s5p_mfc_dev *dev)
335 {
336 	int ret;
337 
338 	/* Release reset signal to the RISC */
339 	dev->risc_on = 1;
340 	mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
341 
342 	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
343 		mfc_err("Failed to reset MFCV8\n");
344 		return -EIO;
345 	}
346 	mfc_debug(2, "Write command to wakeup MFCV8\n");
347 	ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
348 	if (ret) {
349 		mfc_err("Failed to send command to MFCV8 - timeout\n");
350 		return ret;
351 	}
352 
353 	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
354 		mfc_err("Failed to wakeup MFC\n");
355 		return -EIO;
356 	}
357 	return ret;
358 }
359 
s5p_mfc_wait_wakeup(struct s5p_mfc_dev * dev)360 static int s5p_mfc_wait_wakeup(struct s5p_mfc_dev *dev)
361 {
362 	int ret;
363 
364 	/* Send MFC wakeup command */
365 	ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
366 	if (ret) {
367 		mfc_err("Failed to send command to MFC - timeout\n");
368 		return ret;
369 	}
370 
371 	/* Release reset signal to the RISC */
372 	if (IS_MFCV6_PLUS(dev)) {
373 		dev->risc_on = 1;
374 		mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
375 	} else {
376 		mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
377 	}
378 
379 	if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
380 		mfc_err("Failed to wakeup MFC\n");
381 		return -EIO;
382 	}
383 	return ret;
384 }
385 
s5p_mfc_wakeup(struct s5p_mfc_dev * dev)386 int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
387 {
388 	int ret;
389 
390 	mfc_debug_enter();
391 	/* 0. MFC reset */
392 	mfc_debug(2, "MFC reset..\n");
393 	s5p_mfc_clock_on(dev);
394 	dev->risc_on = 0;
395 	ret = s5p_mfc_reset(dev);
396 	if (ret) {
397 		mfc_err("Failed to reset MFC - timeout\n");
398 		s5p_mfc_clock_off(dev);
399 		return ret;
400 	}
401 	mfc_debug(2, "Done MFC reset..\n");
402 	/* 1. Set DRAM base Addr */
403 	s5p_mfc_init_memctrl(dev);
404 	/* 2. Initialize registers of channel I/F */
405 	s5p_mfc_clear_cmds(dev);
406 	s5p_mfc_clean_dev_int_flags(dev);
407 	/* 3. Send MFC wakeup command and wait for completion*/
408 	if (IS_MFCV8_PLUS(dev))
409 		ret = s5p_mfc_v8_wait_wakeup(dev);
410 	else
411 		ret = s5p_mfc_wait_wakeup(dev);
412 
413 	s5p_mfc_clock_off(dev);
414 	if (ret)
415 		return ret;
416 
417 	dev->int_cond = 0;
418 	if (dev->int_err != 0 || dev->int_type !=
419 						S5P_MFC_R2H_CMD_WAKEUP_RET) {
420 		/* Failure. */
421 		mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
422 								dev->int_type);
423 		return -EIO;
424 	}
425 	mfc_debug_leave();
426 	return 0;
427 }
428 
s5p_mfc_open_mfc_inst(struct s5p_mfc_dev * dev,struct s5p_mfc_ctx * ctx)429 int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
430 {
431 	int ret = 0;
432 
433 	ret = s5p_mfc_hw_call(dev->mfc_ops, alloc_instance_buffer, ctx);
434 	if (ret) {
435 		mfc_err("Failed allocating instance buffer\n");
436 		goto err;
437 	}
438 
439 	if (ctx->type == MFCINST_DECODER) {
440 		ret = s5p_mfc_hw_call(dev->mfc_ops,
441 					alloc_dec_temp_buffers, ctx);
442 		if (ret) {
443 			mfc_err("Failed allocating temporary buffers\n");
444 			goto err_free_inst_buf;
445 		}
446 	}
447 
448 	set_work_bit_irqsave(ctx);
449 	s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
450 	if (s5p_mfc_wait_for_done_ctx(ctx,
451 		S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
452 		/* Error or timeout */
453 		mfc_err("Error getting instance from hardware\n");
454 		ret = -EIO;
455 		goto err_free_desc_buf;
456 	}
457 
458 	mfc_debug(2, "Got instance number: %d\n", ctx->inst_no);
459 	return ret;
460 
461 err_free_desc_buf:
462 	if (ctx->type == MFCINST_DECODER)
463 		s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
464 err_free_inst_buf:
465 	s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
466 err:
467 	return ret;
468 }
469 
s5p_mfc_close_mfc_inst(struct s5p_mfc_dev * dev,struct s5p_mfc_ctx * ctx)470 void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
471 {
472 	ctx->state = MFCINST_RETURN_INST;
473 	set_work_bit_irqsave(ctx);
474 	s5p_mfc_hw_call(dev->mfc_ops, try_run, dev);
475 	/* Wait until instance is returned or timeout occurred */
476 	if (s5p_mfc_wait_for_done_ctx(ctx,
477 				S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET, 0)){
478 		clear_work_bit_irqsave(ctx);
479 		mfc_err("Err returning instance\n");
480 	}
481 
482 	/* Free resources */
483 	s5p_mfc_hw_call(dev->mfc_ops, release_codec_buffers, ctx);
484 	s5p_mfc_hw_call(dev->mfc_ops, release_instance_buffer, ctx);
485 	if (ctx->type == MFCINST_DECODER)
486 		s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
487 
488 	ctx->inst_no = MFC_NO_INSTANCE_SET;
489 	ctx->state = MFCINST_FREE;
490 }
491