upload tizen1.0 source
[kernel/linux-2.6.36.git] / drivers / media / video / samsung / mfc5x / mfc_ctrl.c
1 /*
2  * linux/drivers/media/video/samsung/mfc5x/mfc_ctrl.c
3  *
4  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
5  *              http://www.samsung.com/
6  *
7  * Control interface for Samsung MFC (Multi Function Codec - FIMV) driver
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License version 2 as
11  * published by the Free Software Foundation.
12  */
13
14 #include <linux/types.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <linux/delay.h>
18 #include <linux/sched.h>
19
20 #if defined(CONFIG_CPU_S5PV310)
21 #include <mach/regs-mfc.h>
22 #elif defined(CONFIG_ARCH_S5PV210)
23 #include <plat/regs-mfc.h>
24 #endif
25
26
27 #include "mfc.h"
28 #include "mfc_mem.h"
29 #include "mfc_reg.h"
30 #include "mfc_log.h"
31 #include "mfc_cmd.h"
32 #include "mfc_dev.h"
33 #include "mfc_errno.h"
34 #include "mfc_pm.h"
35
36 #define MC_STATUS_TIMEOUT       1000    /* ms */
37
38 static bool mfc_reset(void)
39 {
40         unsigned int mc_status;
41         unsigned long timeo = jiffies;
42
43         timeo += msecs_to_jiffies(MC_STATUS_TIMEOUT);
44
45         /* Stop procedure */
46         /* FIXME: F/W can be access invalid address */
47         /* Reset VI */
48         /*
49         write_reg(0x3F7, MFC_SW_RESET);
50         */
51         write_reg(0x3F6, MFC_SW_RESET); /* Reset RISC */
52         write_reg(0x3E2, MFC_SW_RESET); /* All reset except for MC */
53         mdelay(10);
54
55         /* Check MC status */
56         do {
57                 mc_status = (read_reg(MFC_MC_STATUS) & 0x3);
58
59                 if (mc_status == 0)
60                         break;
61
62                 schedule_timeout_uninterruptible(1);
63                 /* FiXME: cpu_relax() */
64         } while (time_before(jiffies, timeo));
65
66         if (mc_status != 0)
67                 return false;
68
69         write_reg(0x0, MFC_SW_RESET);
70         write_reg(0x3FE, MFC_SW_RESET);
71
72         return true;
73 }
74
75 static void mfc_init_memctrl(void)
76 {
77         /* Channel A, Port 0 */
78         write_reg(mfc_mem_base(0), MFC_MC_DRAMBASE_ADR_A);
79 #if CONFIG_VIDEO_MFC_MEM_PORT_COUNT == 1
80         /* Channel B, Port 0 */
81         write_reg(mfc_mem_base(0), MFC_MC_DRAMBASE_ADR_B);
82 #else
83         /* Channel B, Port 1 */
84         write_reg(mfc_mem_base(1), MFC_MC_DRAMBASE_ADR_B);
85 #endif
86         mfc_dbg("Master A - 0x%08x\n",
87                   read_reg(MFC_MC_DRAMBASE_ADR_A));
88         mfc_dbg("Master B - 0x%08x\n",
89                   read_reg(MFC_MC_DRAMBASE_ADR_B));
90 }
91
92 static void mfc_clear_cmds(void)
93 {
94         write_reg(0xFFFFFFFF, MFC_SI_CH1_INST_ID);
95         write_reg(0xFFFFFFFF, MFC_SI_CH2_INST_ID);
96
97         write_reg(H2R_NOP, MFC_RISC2HOST_CMD);
98         write_reg(R2H_NOP, MFC_HOST2RISC_CMD);
99 }
100
101 int mfc_load_firmware(const unsigned char *data, size_t size)
102 {
103         volatile unsigned char *fw;
104
105         if (!data || size == 0)
106                 return 0;
107
108         /* MFC F/W area already 128KB aligned */
109         fw = mfc_mem_addr(0);
110
111         memcpy((void *)fw, data, size);
112
113         mfc_mem_cache_clean((void *)fw, size);
114
115         return 1;
116 }
117
118 int mfc_start(struct mfc_dev *dev)
119 {
120         int ret;
121
122         /* FIXME: when MFC start, load firmware again */
123         /*
124         dev->fw.state = mfc_load_firmware(dev->fw.info->data, dev->fw.info->size);
125         */
126
127         mfc_clock_on();
128
129         if (mfc_reset() == false) {
130                 mfc_clock_off();
131                 return MFC_FAIL;
132         }
133
134         mfc_init_memctrl();
135         mfc_clear_cmds();
136
137         ret = mfc_cmd_fw_start(dev);
138         if (ret < 0) {
139                 mfc_clock_off();
140                 return ret;
141         }
142
143         ret = mfc_cmd_sys_init(dev);
144
145         mfc_clock_off();
146
147         return ret;
148 }
149
150 int mfc_sleep(struct mfc_dev *dev)
151 {
152         int ret;
153
154         mfc_clock_on();
155
156         /* FIXME: add SFR backup? */
157
158         ret = mfc_cmd_sys_sleep(dev);
159
160         mfc_clock_off();
161
162         /* FIXME: add mfc_power_off()? */
163
164         /* FIXME: ret = 0 */
165         return ret;
166 }
167
168 int mfc_wakeup(struct mfc_dev *dev)
169 {
170         int ret;
171
172         /* FIXME: add mfc_power_on()? */
173
174         mfc_clock_on();
175
176         if (mfc_reset() == false) {
177                 mfc_clock_off();
178                 return MFC_FAIL;
179         }
180
181         mfc_init_memctrl();
182         mfc_clear_cmds();
183
184         ret = mfc_cmd_sys_wakeup(dev);
185
186         mfc_clock_off();
187
188         /* FIXME: ret = 0 */
189         return ret;
190 }
191