[media] s5p-mfc: Prepare driver for callback based re-architecture
[jlayton/linux.git] / drivers / media / platform / s5p-mfc / s5p_mfc_ctrl.c
1 /*
2  * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
3  *
4  * Copyright (c) 2010 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 <linux/delay.h>
14 #include <linux/err.h>
15 #include <linux/firmware.h>
16 #include <linux/jiffies.h>
17 #include <linux/sched.h>
18 #include "regs-mfc.h"
19 #include "s5p_mfc_cmd_v5.h"
20 #include "s5p_mfc_common.h"
21 #include "s5p_mfc_debug.h"
22 #include "s5p_mfc_intr.h"
23 #include "s5p_mfc_pm.h"
24
25 static void *s5p_mfc_bitproc_buf;
26 static size_t s5p_mfc_bitproc_phys;
27 static unsigned char *s5p_mfc_bitproc_virt;
28
29 /* Allocate and load firmware */
30 int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
31 {
32         struct firmware *fw_blob;
33         size_t bank2_base_phys;
34         void *b_base;
35         int err;
36
37         /* Firmare has to be present as a separate file or compiled
38          * into kernel. */
39         mfc_debug_enter();
40         err = request_firmware((const struct firmware **)&fw_blob,
41                                      "s5p-mfc.fw", dev->v4l2_dev.dev);
42         if (err != 0) {
43                 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
44                 return -EINVAL;
45         }
46         dev->fw_size = ALIGN(fw_blob->size, FIRMWARE_ALIGN);
47         if (s5p_mfc_bitproc_buf) {
48                 mfc_err("Attempting to allocate firmware when it seems that it is already loaded\n");
49                 release_firmware(fw_blob);
50                 return -ENOMEM;
51         }
52         s5p_mfc_bitproc_buf = vb2_dma_contig_memops.alloc(
53                 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], dev->fw_size);
54         if (IS_ERR(s5p_mfc_bitproc_buf)) {
55                 s5p_mfc_bitproc_buf = NULL;
56                 mfc_err("Allocating bitprocessor buffer failed\n");
57                 release_firmware(fw_blob);
58                 return -ENOMEM;
59         }
60         s5p_mfc_bitproc_phys = s5p_mfc_mem_cookie(
61                 dev->alloc_ctx[MFC_BANK1_ALLOC_CTX], s5p_mfc_bitproc_buf);
62         if (s5p_mfc_bitproc_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
63                 mfc_err("The base memory for bank 1 is not aligned to 128KB\n");
64                 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
65                 s5p_mfc_bitproc_phys = 0;
66                 s5p_mfc_bitproc_buf = NULL;
67                 release_firmware(fw_blob);
68                 return -EIO;
69         }
70         s5p_mfc_bitproc_virt = vb2_dma_contig_memops.vaddr(s5p_mfc_bitproc_buf);
71         if (!s5p_mfc_bitproc_virt) {
72                 mfc_err("Bitprocessor memory remap failed\n");
73                 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
74                 s5p_mfc_bitproc_phys = 0;
75                 s5p_mfc_bitproc_buf = NULL;
76                 release_firmware(fw_blob);
77                 return -EIO;
78         }
79         dev->bank1 = s5p_mfc_bitproc_phys;
80         b_base = vb2_dma_contig_memops.alloc(
81                 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER);
82         if (IS_ERR(b_base)) {
83                 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
84                 s5p_mfc_bitproc_phys = 0;
85                 s5p_mfc_bitproc_buf = NULL;
86                 mfc_err("Allocating bank2 base failed\n");
87         release_firmware(fw_blob);
88                 return -ENOMEM;
89         }
90         bank2_base_phys = s5p_mfc_mem_cookie(
91                 dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], b_base);
92         vb2_dma_contig_memops.put(b_base);
93         if (bank2_base_phys & ((1 << MFC_BASE_ALIGN_ORDER) - 1)) {
94                 mfc_err("The base memory for bank 2 is not aligned to 128KB\n");
95                 vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
96                 s5p_mfc_bitproc_phys = 0;
97                 s5p_mfc_bitproc_buf = NULL;
98                 release_firmware(fw_blob);
99                 return -EIO;
100         }
101         /* Valid buffers passed to MFC encoder with LAST_FRAME command
102          * should not have address of bank2 - MFC will treat it as a null frame.
103          * To avoid such situation we set bank2 address below the pool address.
104          */
105         dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
106         memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
107         wmb();
108         release_firmware(fw_blob);
109         mfc_debug_leave();
110         return 0;
111 }
112
113 /* Reload firmware to MFC */
114 int s5p_mfc_reload_firmware(struct s5p_mfc_dev *dev)
115 {
116         struct firmware *fw_blob;
117         int err;
118
119         /* Firmare has to be present as a separate file or compiled
120          * into kernel. */
121         mfc_debug_enter();
122         err = request_firmware((const struct firmware **)&fw_blob,
123                                      "s5p-mfc.fw", dev->v4l2_dev.dev);
124         if (err != 0) {
125                 mfc_err("Firmware is not present in the /lib/firmware directory nor compiled in kernel\n");
126                 return -EINVAL;
127         }
128         if (fw_blob->size > dev->fw_size) {
129                 mfc_err("MFC firmware is too big to be loaded\n");
130                 release_firmware(fw_blob);
131                 return -ENOMEM;
132         }
133         if (s5p_mfc_bitproc_buf == NULL || s5p_mfc_bitproc_phys == 0) {
134                 mfc_err("MFC firmware is not allocated or was not mapped correctly\n");
135                 release_firmware(fw_blob);
136                 return -EINVAL;
137         }
138         memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
139         wmb();
140         release_firmware(fw_blob);
141         mfc_debug_leave();
142         return 0;
143 }
144
145 /* Release firmware memory */
146 int s5p_mfc_release_firmware(struct s5p_mfc_dev *dev)
147 {
148         /* Before calling this function one has to make sure
149          * that MFC is no longer processing */
150         if (!s5p_mfc_bitproc_buf)
151                 return -EINVAL;
152         vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
153         s5p_mfc_bitproc_virt = NULL;
154         s5p_mfc_bitproc_phys = 0;
155         s5p_mfc_bitproc_buf = NULL;
156         return 0;
157 }
158
159 /* Reset the device */
160 int s5p_mfc_reset(struct s5p_mfc_dev *dev)
161 {
162         unsigned int mc_status;
163         unsigned long timeout;
164
165         mfc_debug_enter();
166         /* Stop procedure */
167         /*  reset RISC */
168         mfc_write(dev, 0x3f6, S5P_FIMV_SW_RESET);
169         /*  All reset except for MC */
170         mfc_write(dev, 0x3e2, S5P_FIMV_SW_RESET);
171         mdelay(10);
172
173         timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
174         /* Check MC status */
175         do {
176                 if (time_after(jiffies, timeout)) {
177                         mfc_err("Timeout while resetting MFC\n");
178                         return -EIO;
179                 }
180
181                 mc_status = mfc_read(dev, S5P_FIMV_MC_STATUS);
182
183         } while (mc_status & 0x3);
184
185         mfc_write(dev, 0x0, S5P_FIMV_SW_RESET);
186         mfc_write(dev, 0x3fe, S5P_FIMV_SW_RESET);
187         mfc_debug_leave();
188         return 0;
189 }
190
191 static inline void s5p_mfc_init_memctrl(struct s5p_mfc_dev *dev)
192 {
193         mfc_write(dev, dev->bank1, S5P_FIMV_MC_DRAMBASE_ADR_A);
194         mfc_write(dev, dev->bank2, S5P_FIMV_MC_DRAMBASE_ADR_B);
195         mfc_debug(2, "Bank1: %08x, Bank2: %08x\n", dev->bank1, dev->bank2);
196 }
197
198 static inline void s5p_mfc_clear_cmds(struct s5p_mfc_dev *dev)
199 {
200         mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH0_INST_ID);
201         mfc_write(dev, 0xffffffff, S5P_FIMV_SI_CH1_INST_ID);
202         mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD);
203         mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD);
204 }
205
206 /* Initialize hardware */
207 int s5p_mfc_init_hw(struct s5p_mfc_dev *dev)
208 {
209         unsigned int ver;
210         int ret;
211
212         mfc_debug_enter();
213         if (!s5p_mfc_bitproc_buf)
214                 return -EINVAL;
215
216         /* 0. MFC reset */
217         mfc_debug(2, "MFC reset..\n");
218         s5p_mfc_clock_on();
219         ret = s5p_mfc_reset(dev);
220         if (ret) {
221                 mfc_err("Failed to reset MFC - timeout\n");
222                 return ret;
223         }
224         mfc_debug(2, "Done MFC reset..\n");
225         /* 1. Set DRAM base Addr */
226         s5p_mfc_init_memctrl(dev);
227         /* 2. Initialize registers of channel I/F */
228         s5p_mfc_clear_cmds(dev);
229         /* 3. Release reset signal to the RISC */
230         s5p_mfc_clean_dev_int_flags(dev);
231         mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
232         mfc_debug(2, "Will now wait for completion of firmware transfer\n");
233         if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_FW_STATUS_RET)) {
234                 mfc_err("Failed to load firmware\n");
235                 s5p_mfc_reset(dev);
236                 s5p_mfc_clock_off();
237                 return -EIO;
238         }
239         s5p_mfc_clean_dev_int_flags(dev);
240         /* 4. Initialize firmware */
241         ret = s5p_mfc_sys_init_cmd(dev);
242         if (ret) {
243                 mfc_err("Failed to send command to MFC - timeout\n");
244                 s5p_mfc_reset(dev);
245                 s5p_mfc_clock_off();
246                 return ret;
247         }
248         mfc_debug(2, "Ok, now will write a command to init the system\n");
249         if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SYS_INIT_RET)) {
250                 mfc_err("Failed to load firmware\n");
251                 s5p_mfc_reset(dev);
252                 s5p_mfc_clock_off();
253                 return -EIO;
254         }
255         dev->int_cond = 0;
256         if (dev->int_err != 0 || dev->int_type !=
257                                         S5P_FIMV_R2H_CMD_SYS_INIT_RET) {
258                 /* Failure. */
259                 mfc_err("Failed to init firmware - error: %d int: %d\n",
260                                                 dev->int_err, dev->int_type);
261                 s5p_mfc_reset(dev);
262                 s5p_mfc_clock_off();
263                 return -EIO;
264         }
265         ver = mfc_read(dev, S5P_FIMV_FW_VERSION);
266         mfc_debug(2, "MFC F/W version : %02xyy, %02xmm, %02xdd\n",
267                 (ver >> 16) & 0xFF, (ver >> 8) & 0xFF, ver & 0xFF);
268         s5p_mfc_clock_off();
269         mfc_debug_leave();
270         return 0;
271 }
272
273
274 int s5p_mfc_sleep(struct s5p_mfc_dev *dev)
275 {
276         int ret;
277
278         mfc_debug_enter();
279         s5p_mfc_clock_on();
280         s5p_mfc_clean_dev_int_flags(dev);
281         ret = s5p_mfc_sleep_cmd(dev);
282         if (ret) {
283                 mfc_err("Failed to send command to MFC - timeout\n");
284                 return ret;
285         }
286         if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_SLEEP_RET)) {
287                 mfc_err("Failed to sleep\n");
288                 return -EIO;
289         }
290         s5p_mfc_clock_off();
291         dev->int_cond = 0;
292         if (dev->int_err != 0 || dev->int_type !=
293                                                 S5P_FIMV_R2H_CMD_SLEEP_RET) {
294                 /* Failure. */
295                 mfc_err("Failed to sleep - error: %d int: %d\n", dev->int_err,
296                                                                 dev->int_type);
297                 return -EIO;
298         }
299         mfc_debug_leave();
300         return ret;
301 }
302
303 int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
304 {
305         int ret;
306
307         mfc_debug_enter();
308         /* 0. MFC reset */
309         mfc_debug(2, "MFC reset..\n");
310         s5p_mfc_clock_on();
311         ret = s5p_mfc_reset(dev);
312         if (ret) {
313                 mfc_err("Failed to reset MFC - timeout\n");
314                 return ret;
315         }
316         mfc_debug(2, "Done MFC reset..\n");
317         /* 1. Set DRAM base Addr */
318         s5p_mfc_init_memctrl(dev);
319         /* 2. Initialize registers of channel I/F */
320         s5p_mfc_clear_cmds(dev);
321         s5p_mfc_clean_dev_int_flags(dev);
322         /* 3. Initialize firmware */
323         ret = s5p_mfc_wakeup_cmd(dev);
324         if (ret) {
325                 mfc_err("Failed to send command to MFC - timeout\n");
326                 return ret;
327         }
328         /* 4. Release reset signal to the RISC */
329         mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
330         mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
331         if (s5p_mfc_wait_for_done_dev(dev, S5P_FIMV_R2H_CMD_WAKEUP_RET)) {
332                 mfc_err("Failed to load firmware\n");
333                 return -EIO;
334         }
335         s5p_mfc_clock_off();
336         dev->int_cond = 0;
337         if (dev->int_err != 0 || dev->int_type !=
338                                                 S5P_FIMV_R2H_CMD_WAKEUP_RET) {
339                 /* Failure. */
340                 mfc_err("Failed to wakeup - error: %d int: %d\n", dev->int_err,
341                                                                 dev->int_type);
342                 return -EIO;
343         }
344         mfc_debug_leave();
345         return 0;
346 }
347