1 /*
2  * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
3  *
4  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
5  *		http://www.samsung.com/
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  */
12 
13 #include "regs-mfc.h"
14 #include "s5p_mfc_cmd.h"
15 #include "s5p_mfc_common.h"
16 #include "s5p_mfc_debug.h"
17 
18 /* This function is used to send a command to the MFC */
s5p_mfc_cmd_host2risc(struct s5p_mfc_dev * dev,int cmd,struct s5p_mfc_cmd_args * args)19 static int s5p_mfc_cmd_host2risc(struct s5p_mfc_dev *dev, int cmd,
20 						struct s5p_mfc_cmd_args *args)
21 {
22 	int cur_cmd;
23 	unsigned long timeout;
24 
25 	timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
26 	/* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
27 	do {
28 		if (time_after(jiffies, timeout)) {
29 			mfc_err("Timeout while waiting for hardware\n");
30 			return -EIO;
31 		}
32 		cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
33 	} while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
34 	mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
35 	mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
36 	mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
37 	mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
38 	/* Issue the command */
39 	mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
40 	return 0;
41 }
42 
43 /* Initialize the MFC */
s5p_mfc_sys_init_cmd(struct s5p_mfc_dev * dev)44 int s5p_mfc_sys_init_cmd(struct s5p_mfc_dev *dev)
45 {
46 	struct s5p_mfc_cmd_args h2r_args;
47 
48 	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
49 	h2r_args.arg[0] = dev->fw_size;
50 	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SYS_INIT, &h2r_args);
51 }
52 
53 /* Suspend the MFC hardware */
s5p_mfc_sleep_cmd(struct s5p_mfc_dev * dev)54 int s5p_mfc_sleep_cmd(struct s5p_mfc_dev *dev)
55 {
56 	struct s5p_mfc_cmd_args h2r_args;
57 
58 	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
59 	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
60 }
61 
62 /* Wake up the MFC hardware */
s5p_mfc_wakeup_cmd(struct s5p_mfc_dev * dev)63 int s5p_mfc_wakeup_cmd(struct s5p_mfc_dev *dev)
64 {
65 	struct s5p_mfc_cmd_args h2r_args;
66 
67 	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
68 	return s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_WAKEUP, &h2r_args);
69 }
70 
71 
s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx * ctx)72 int s5p_mfc_open_inst_cmd(struct s5p_mfc_ctx *ctx)
73 {
74 	struct s5p_mfc_dev *dev = ctx->dev;
75 	struct s5p_mfc_cmd_args h2r_args;
76 	int ret;
77 
78 	/* Preparing decoding - getting instance number */
79 	mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
80 	dev->curr_ctx = ctx->num;
81 	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
82 	h2r_args.arg[0] = ctx->codec_mode;
83 	h2r_args.arg[1] = 0; /* no crc & no pixelcache */
84 	h2r_args.arg[2] = ctx->ctx_ofs;
85 	h2r_args.arg[3] = ctx->ctx_size;
86 	ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
87 								&h2r_args);
88 	if (ret) {
89 		mfc_err("Failed to create a new instance\n");
90 		ctx->state = MFCINST_ERROR;
91 	}
92 	return ret;
93 }
94 
s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx * ctx)95 int s5p_mfc_close_inst_cmd(struct s5p_mfc_ctx *ctx)
96 {
97 	struct s5p_mfc_dev *dev = ctx->dev;
98 	struct s5p_mfc_cmd_args h2r_args;
99 	int ret;
100 
101 	if (ctx->state == MFCINST_FREE) {
102 		mfc_err("Instance already returned\n");
103 		ctx->state = MFCINST_ERROR;
104 		return -EINVAL;
105 	}
106 	/* Closing decoding instance  */
107 	mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
108 	dev->curr_ctx = ctx->num;
109 	memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
110 	h2r_args.arg[0] = ctx->inst_no;
111 	ret = s5p_mfc_cmd_host2risc(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
112 								&h2r_args);
113 	if (ret) {
114 		mfc_err("Failed to return an instance\n");
115 		ctx->state = MFCINST_ERROR;
116 		return -EINVAL;
117 	}
118 	return 0;
119 }
120 
121