blob: 8630e34782e22d150be57aaec277dc8d0427f2c2 [file] [log] [blame]
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -07001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070013#include <linux/of.h>
14#include <linux/debugfs.h>
15#include <linux/videodev2.h>
16#include <linux/uaccess.h>
17#include <linux/platform_device.h>
18#include <linux/firmware.h>
19#include <linux/delay.h>
20#include <linux/timer.h>
21#include "cam_io_util.h"
22#include "cam_hw.h"
23#include "cam_hw_intf.h"
24#include "ipe_core.h"
25#include "ipe_soc.h"
26#include "cam_soc_util.h"
27#include "cam_io_util.h"
28#include "cam_ipe_hw_intf.h"
29#include "cam_icp_hw_mgr_intf.h"
30#include "cam_cpas_api.h"
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070031#include "cam_debug_util.h"
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070032
33static int cam_ipe_caps_vote(struct cam_ipe_device_core_info *core_info,
34 struct cam_icp_cpas_vote *cpas_vote)
35{
36 int rc = 0;
37
38 if (cpas_vote->ahb_vote_valid)
39 rc = cam_cpas_update_ahb_vote(core_info->cpas_handle,
40 &cpas_vote->ahb_vote);
41 if (cpas_vote->axi_vote_valid)
42 rc = cam_cpas_update_axi_vote(core_info->cpas_handle,
43 &cpas_vote->axi_vote);
44
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070045 if (rc)
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070046 CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070047
48 return rc;
49}
50
51int cam_ipe_init_hw(void *device_priv,
52 void *init_hw_args, uint32_t arg_size)
53{
54 struct cam_hw_info *ipe_dev = device_priv;
55 struct cam_hw_soc_info *soc_info = NULL;
56 struct cam_ipe_device_core_info *core_info = NULL;
57 struct cam_icp_cpas_vote cpas_vote;
58 int rc = 0;
59
60 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070061 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070062 return -EINVAL;
63 }
64
65 soc_info = &ipe_dev->soc_info;
66 core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
67
68 if ((!soc_info) || (!core_info)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070069 CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
70 soc_info, core_info);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070071 return -EINVAL;
72 }
73
74 cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070075 cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
Suresh Vankadara34494fc2017-08-12 18:18:09 +053076 cpas_vote.axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
77 cpas_vote.axi_vote.uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070078
79 rc = cam_cpas_start(core_info->cpas_handle,
80 &cpas_vote.ahb_vote, &cpas_vote.axi_vote);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070081 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070082 CAM_ERR(CAM_ICP, "cpass start failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070083 return rc;
84 }
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070085 core_info->cpas_start = true;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070086
87 rc = cam_ipe_enable_soc_resources(soc_info);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070088 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070089 CAM_ERR(CAM_ICP, "soc enable is failed : %d", rc);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070090 if (cam_cpas_stop(core_info->cpas_handle))
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070091 CAM_ERR(CAM_ICP, "cpas stop is failed");
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070092 else
93 core_info->cpas_start = false;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070094 }
95
96 return rc;
97}
98
99int cam_ipe_deinit_hw(void *device_priv,
100 void *init_hw_args, uint32_t arg_size)
101{
102 struct cam_hw_info *ipe_dev = device_priv;
103 struct cam_hw_soc_info *soc_info = NULL;
104 struct cam_ipe_device_core_info *core_info = NULL;
105 int rc = 0;
106
107 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700108 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700109 return -EINVAL;
110 }
111
112 soc_info = &ipe_dev->soc_info;
113 core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
114 if ((!soc_info) || (!core_info)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700115 CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
116 soc_info, core_info);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700117 return -EINVAL;
118 }
119
120 rc = cam_ipe_disable_soc_resources(soc_info);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700121 if (rc)
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700122 CAM_ERR(CAM_ICP, "soc disable is failed : %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700123
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700124 if (core_info->cpas_start) {
125 if (cam_cpas_stop(core_info->cpas_handle))
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700126 CAM_ERR(CAM_ICP, "cpas stop is failed");
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700127 else
128 core_info->cpas_start = false;
129 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700130
131 return rc;
132}
133
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530134static int cam_ipe_handle_pc(struct cam_hw_info *ipe_dev)
135{
136 struct cam_hw_soc_info *soc_info = NULL;
137 struct cam_ipe_device_core_info *core_info = NULL;
138 struct cam_ipe_device_hw_info *hw_info = NULL;
139 int pwr_ctrl;
140 int pwr_status;
141
142 soc_info = &ipe_dev->soc_info;
143 core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
144 hw_info = core_info->ipe_hw_info;
145
146 cam_cpas_reg_read(core_info->cpas_handle,
147 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl,
148 true, &pwr_ctrl);
149 if (!(pwr_ctrl & IPE_COLLAPSE_MASK)) {
150 cam_cpas_reg_read(core_info->cpas_handle,
151 CAM_CPAS_REG_CPASTOP, hw_info->pwr_status,
152 true, &pwr_status);
153 cam_cpas_reg_write(core_info->cpas_handle,
154 CAM_CPAS_REG_CPASTOP,
155 hw_info->pwr_ctrl, true, 0x1);
156
157 if (pwr_status >> IPE_PWR_ON_MASK)
158 return -EINVAL;
159
160 }
161 cam_ipe_get_gdsc_control(soc_info);
162 cam_cpas_reg_read(core_info->cpas_handle,
163 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl,
164 true, &pwr_ctrl);
165 cam_cpas_reg_read(core_info->cpas_handle,
166 CAM_CPAS_REG_CPASTOP, hw_info->pwr_status,
167 true, &pwr_status);
168 CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x",
169 pwr_ctrl, pwr_status);
170
171 return 0;
172}
173
174static int cam_ipe_handle_resume(struct cam_hw_info *ipe_dev)
175{
176 struct cam_hw_soc_info *soc_info = NULL;
177 struct cam_ipe_device_core_info *core_info = NULL;
178 struct cam_ipe_device_hw_info *hw_info = NULL;
179 int pwr_ctrl;
180 int pwr_status;
181 int rc = 0;
182
183 soc_info = &ipe_dev->soc_info;
184 core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
185 hw_info = core_info->ipe_hw_info;
186
187 cam_cpas_reg_read(core_info->cpas_handle,
188 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl,
189 true, &pwr_ctrl);
190 if (pwr_ctrl & IPE_COLLAPSE_MASK) {
191 CAM_ERR(CAM_ICP, "IPE: resume failed : %d", pwr_ctrl);
192 return -EINVAL;
193 }
194 rc = cam_ipe_transfer_gdsc_control(soc_info);
195 cam_cpas_reg_read(core_info->cpas_handle,
196 CAM_CPAS_REG_CPASTOP, hw_info->pwr_ctrl, true, &pwr_ctrl);
197 cam_cpas_reg_read(core_info->cpas_handle,
198 CAM_CPAS_REG_CPASTOP, hw_info->pwr_status,
199 true, &pwr_status);
200 CAM_DBG(CAM_ICP, "pwr_ctrl = %x pwr_status = %x",
201 pwr_ctrl, pwr_status);
202
203 return rc;
204}
205
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700206int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type,
207 void *cmd_args, uint32_t arg_size)
208{
209 struct cam_hw_info *ipe_dev = device_priv;
210 struct cam_hw_soc_info *soc_info = NULL;
211 struct cam_ipe_device_core_info *core_info = NULL;
212 struct cam_ipe_device_hw_info *hw_info = NULL;
213 int rc = 0;
214
215 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700216 CAM_ERR(CAM_ICP, "Invalid arguments");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700217 return -EINVAL;
218 }
219
220 if (cmd_type >= CAM_ICP_IPE_CMD_MAX) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700221 CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700222 return -EINVAL;
223 }
224
225 soc_info = &ipe_dev->soc_info;
226 core_info = (struct cam_ipe_device_core_info *)ipe_dev->core_info;
227 hw_info = core_info->ipe_hw_info;
228
229 switch (cmd_type) {
230 case CAM_ICP_IPE_CMD_VOTE_CPAS: {
231 struct cam_icp_cpas_vote *cpas_vote = cmd_args;
232
233 if (!cmd_args)
234 return -EINVAL;
235
236 cam_ipe_caps_vote(core_info, cpas_vote);
237 break;
238 }
239
240 case CAM_ICP_IPE_CMD_CPAS_START: {
241 struct cam_icp_cpas_vote *cpas_vote = cmd_args;
242
243 if (!cmd_args)
244 return -EINVAL;
245
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700246 if (!core_info->cpas_start) {
247 rc = cam_cpas_start(core_info->cpas_handle,
248 &cpas_vote->ahb_vote, &cpas_vote->axi_vote);
249 core_info->cpas_start = true;
250 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700251 break;
252 }
253
254 case CAM_ICP_IPE_CMD_CPAS_STOP:
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700255 if (core_info->cpas_start) {
256 cam_cpas_stop(core_info->cpas_handle);
257 core_info->cpas_start = false;
258 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700259 break;
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530260 case CAM_ICP_IPE_CMD_POWER_COLLAPSE:
261 rc = cam_ipe_handle_pc(ipe_dev);
262 break;
263 case CAM_ICP_IPE_CMD_POWER_RESUME:
264 rc = cam_ipe_handle_resume(ipe_dev);
265 break;
Suresh Vankadara34494fc2017-08-12 18:18:09 +0530266 case CAM_ICP_IPE_CMD_UPDATE_CLK: {
267 uint32_t clk_rate = *(uint32_t *)cmd_args;
268
269 CAM_DBG(CAM_ICP, "ipe_src_clk rate = %d", (int)clk_rate);
270 rc = cam_ipe_update_clk_rate(soc_info, clk_rate);
271 }
272 break;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700273 default:
274 break;
275 }
276 return rc;
277}
278
279irqreturn_t cam_ipe_irq(int irq_num, void *data)
280{
281 return IRQ_HANDLED;
282}