blob: e200f6f04fc3266769adb53d90a745a4df9292e0 [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/slab.h>
14#include <linux/of.h>
15#include <linux/debugfs.h>
16#include <linux/videodev2.h>
17#include <linux/uaccess.h>
18#include <linux/platform_device.h>
19#include <linux/firmware.h>
20#include <linux/delay.h>
21#include <linux/timer.h>
22#include <linux/elf.h>
23#include <media/cam_icp.h>
24#include "cam_io_util.h"
25#include "cam_a5_hw_intf.h"
26#include "cam_hw.h"
27#include "cam_hw_intf.h"
28#include "a5_core.h"
29#include "a5_soc.h"
30#include "cam_soc_util.h"
31#include "cam_io_util.h"
32#include "hfi_intf.h"
33#include "hfi_sys_defs.h"
34#include "cam_icp_hw_mgr_intf.h"
35#include "cam_cpas_api.h"
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070036#include "cam_debug_util.h"
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070037
38static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info,
39 struct cam_icp_cpas_vote *cpas_vote)
40{
41 int rc = 0;
42
43 if (cpas_vote->ahb_vote_valid)
44 rc = cam_cpas_update_ahb_vote(core_info->cpas_handle,
45 &cpas_vote->ahb_vote);
46
47 if (cpas_vote->axi_vote_valid)
48 rc = cam_cpas_update_axi_vote(core_info->cpas_handle,
49 &cpas_vote->axi_vote);
50
51 if (rc)
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070052 CAM_ERR(CAM_ICP, "cpas vote is failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070053
54 return rc;
55}
56
57static int32_t cam_icp_validate_fw(const uint8_t *elf)
58{
59 struct elf32_hdr *elf_hdr;
60
61 if (!elf) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070062 CAM_ERR(CAM_ICP, "Invalid params");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070063 return -EINVAL;
64 }
65
66 elf_hdr = (struct elf32_hdr *)elf;
67
68 if (memcmp(elf_hdr->e_ident, ELFMAG, SELFMAG)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070069 CAM_ERR(CAM_ICP, "ICP elf identifier is failed");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070070 return -EINVAL;
71 }
72
73 /* check architecture */
74 if (elf_hdr->e_machine != EM_ARM) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070075 CAM_ERR(CAM_ICP, "unsupported arch");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070076 return -EINVAL;
77 }
78
79 /* check elf bit format */
80 if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070081 CAM_ERR(CAM_ICP, "elf doesn't support 32 bit format");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070082 return -EINVAL;
83 }
84
85 return 0;
86}
87
88static int32_t cam_icp_get_fw_size(const uint8_t *elf, uint32_t *fw_size)
89{
90 int32_t rc = 0;
91 int32_t i = 0;
92 uint32_t num_prg_hdrs;
93 unsigned char *icp_prg_hdr_tbl;
94 uint32_t seg_mem_size = 0;
95 struct elf32_hdr *elf_hdr;
96 struct elf32_phdr *prg_hdr;
97
98 if (!elf || !fw_size) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070099 CAM_ERR(CAM_ICP, "invalid args");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700100 return -EINVAL;
101 }
102
103 *fw_size = 0;
104
105 elf_hdr = (struct elf32_hdr *)elf;
106 num_prg_hdrs = elf_hdr->e_phnum;
107 icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
108 prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
109
110 if (!prg_hdr) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700111 CAM_ERR(CAM_ICP, "failed to get elf program header attr");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700112 return -EINVAL;
113 }
114
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700115 CAM_DBG(CAM_ICP, "num_prg_hdrs = %d", num_prg_hdrs);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700116 for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
117 if (prg_hdr->p_flags == 0)
118 continue;
119
120 seg_mem_size = (prg_hdr->p_memsz + prg_hdr->p_align - 1) &
121 ~(prg_hdr->p_align - 1);
122 seg_mem_size += prg_hdr->p_vaddr;
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700123 CAM_DBG(CAM_ICP, "memsz:%x align:%x addr:%x seg_mem_size:%x",
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700124 (int)prg_hdr->p_memsz, (int)prg_hdr->p_align,
125 (int)prg_hdr->p_vaddr, (int)seg_mem_size);
126 if (*fw_size < seg_mem_size)
127 *fw_size = seg_mem_size;
128
129 }
130
131 if (*fw_size == 0) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700132 CAM_ERR(CAM_ICP, "invalid elf fw file");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700133 return -EINVAL;
134 }
135
136 return rc;
137}
138
139static int32_t cam_icp_program_fw(const uint8_t *elf,
140 struct cam_a5_device_core_info *core_info)
141{
142 int32_t rc = 0;
143 uint32_t num_prg_hdrs;
144 unsigned char *icp_prg_hdr_tbl;
145 int32_t i = 0;
146 u8 *dest;
147 u8 *src;
148 struct elf32_hdr *elf_hdr;
149 struct elf32_phdr *prg_hdr;
150
151 elf_hdr = (struct elf32_hdr *)elf;
152 num_prg_hdrs = elf_hdr->e_phnum;
153 icp_prg_hdr_tbl = (unsigned char *)elf + elf_hdr->e_phoff;
154 prg_hdr = (struct elf32_phdr *)&icp_prg_hdr_tbl[0];
155
156 if (!prg_hdr) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700157 CAM_ERR(CAM_ICP, "failed to get elf program header attr");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700158 return -EINVAL;
159 }
160
161 for (i = 0; i < num_prg_hdrs; i++, prg_hdr++) {
162 if (prg_hdr->p_flags == 0)
163 continue;
164
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700165 CAM_DBG(CAM_ICP, "Loading FW header size: %u",
166 prg_hdr->p_filesz);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700167 if (prg_hdr->p_filesz != 0) {
168 src = (u8 *)((u8 *)elf + prg_hdr->p_offset);
169 dest = (u8 *)(((u8 *)core_info->fw_kva_addr) +
170 prg_hdr->p_vaddr);
171
172 memcpy_toio(dest, src, prg_hdr->p_filesz);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700173 }
174 }
175
176 return rc;
177}
178
179static int32_t cam_a5_download_fw(void *device_priv)
180{
181 int32_t rc = 0;
182 uint32_t fw_size;
183 const uint8_t *fw_start = NULL;
184 struct cam_hw_info *a5_dev = device_priv;
185 struct cam_hw_soc_info *soc_info = NULL;
186 struct cam_a5_device_core_info *core_info = NULL;
187 struct cam_a5_device_hw_info *hw_info = NULL;
188 struct platform_device *pdev = NULL;
189 struct a5_soc_info *cam_a5_soc_info = NULL;
190
191 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700192 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700193 return -EINVAL;
194 }
195
196 soc_info = &a5_dev->soc_info;
197 core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
198 hw_info = core_info->a5_hw_info;
199 pdev = soc_info->pdev;
200 cam_a5_soc_info = soc_info->soc_private;
201
202 rc = request_firmware(&core_info->fw_elf, "CAMERA_ICP.elf", &pdev->dev);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700203 if (rc) {
204 CAM_ERR(CAM_ICP, "Failed to locate fw: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700205 return rc;
206 }
207
208 if (!core_info->fw_elf) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700209 CAM_ERR(CAM_ICP, "Invalid elf size");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700210 return -EINVAL;
211 }
212
213 fw_start = core_info->fw_elf->data;
214 rc = cam_icp_validate_fw(fw_start);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700215 if (rc) {
216 CAM_ERR(CAM_ICP, "fw elf validation failed");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700217 return -EINVAL;
218 }
219
220 rc = cam_icp_get_fw_size(fw_start, &fw_size);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700221 if (rc) {
222 CAM_ERR(CAM_ICP, "unable to get fw size");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700223 return rc;
224 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700225
226 if (core_info->fw_buf_len < fw_size) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700227 CAM_ERR(CAM_ICP, "mismatch in fw size: %u %llu",
228 fw_size, core_info->fw_buf_len);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700229 goto fw_alloc_failed;
230 }
231
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700232 rc = cam_icp_program_fw(fw_start, core_info);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700233 if (rc) {
234 CAM_ERR(CAM_ICP, "fw program is failed");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700235 goto fw_program_failed;
236 }
237
238 return 0;
239fw_program_failed:
240fw_alloc_failed:
241 return rc;
242}
243
244int cam_a5_init_hw(void *device_priv,
245 void *init_hw_args, uint32_t arg_size)
246{
247 struct cam_hw_info *a5_dev = device_priv;
248 struct cam_hw_soc_info *soc_info = NULL;
249 struct cam_a5_device_core_info *core_info = NULL;
250 struct cam_icp_cpas_vote cpas_vote;
251 int rc = 0;
252
253 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700254 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700255 return -EINVAL;
256 }
257
258 soc_info = &a5_dev->soc_info;
259 core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
260
261 if ((!soc_info) || (!core_info)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700262 CAM_ERR(CAM_ICP, "soc_info: %pK core_info: %pK",
263 soc_info, core_info);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700264 return -EINVAL;
265 }
266
267 cpas_vote.ahb_vote.type = CAM_VOTE_ABSOLUTE;
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700268 cpas_vote.ahb_vote.vote.level = CAM_SVS_VOTE;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700269 cpas_vote.axi_vote.compressed_bw = ICP_TURBO_VOTE;
270 cpas_vote.axi_vote.uncompressed_bw = ICP_TURBO_VOTE;
271
272 rc = cam_cpas_start(core_info->cpas_handle,
273 &cpas_vote.ahb_vote, &cpas_vote.axi_vote);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700274 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700275 CAM_ERR(CAM_ICP, "cpass start failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700276 return rc;
277 }
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700278 core_info->cpas_start = true;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700279
280 rc = cam_a5_enable_soc_resources(soc_info);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700281 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700282 CAM_ERR(CAM_ICP, "soc enable is failed: %d", rc);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700283 if (cam_cpas_stop(core_info->cpas_handle))
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700284 CAM_ERR(CAM_ICP, "cpas stop is failed");
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700285 else
286 core_info->cpas_start = false;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700287 }
288
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700289 return rc;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700290}
291
292int cam_a5_deinit_hw(void *device_priv,
293 void *init_hw_args, uint32_t arg_size)
294{
295 struct cam_hw_info *a5_dev = device_priv;
296 struct cam_hw_soc_info *soc_info = NULL;
297 struct cam_a5_device_core_info *core_info = NULL;
298 int rc = 0;
299
300 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700301 CAM_ERR(CAM_ICP, "Invalid cam_dev_info");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700302 return -EINVAL;
303 }
304
305 soc_info = &a5_dev->soc_info;
306 core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
307 if ((!soc_info) || (!core_info)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700308 CAM_ERR(CAM_ICP, "soc_info = %pK core_info = %pK",
309 soc_info, core_info);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700310 return -EINVAL;
311 }
312
313 rc = cam_a5_disable_soc_resources(soc_info);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700314 if (rc)
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700315 CAM_ERR(CAM_ICP, "soc disable is failed: %d", rc);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700316
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700317 if (core_info->cpas_start) {
318 if (cam_cpas_stop(core_info->cpas_handle))
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700319 CAM_ERR(CAM_ICP, "cpas stop is failed");
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700320 else
321 core_info->cpas_start = false;
322 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700323
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700324 return rc;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700325}
326
327irqreturn_t cam_a5_irq(int irq_num, void *data)
328{
329 struct cam_hw_info *a5_dev = data;
330 struct cam_hw_soc_info *soc_info = NULL;
331 struct cam_a5_device_core_info *core_info = NULL;
332 struct cam_a5_device_hw_info *hw_info = NULL;
333 uint32_t irq_status = 0;
334
335 if (!data) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700336 CAM_ERR(CAM_ICP, "Invalid cam_dev_info or query_cap args");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700337 return IRQ_HANDLED;
338 }
339
340 soc_info = &a5_dev->soc_info;
341 core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
342 hw_info = core_info->a5_hw_info;
343
344 irq_status = cam_io_r_mb(soc_info->reg_map[A5_SIERRA_BASE].mem_base +
345 core_info->a5_hw_info->a5_host_int_status);
346
347 cam_io_w_mb(irq_status,
348 soc_info->reg_map[A5_SIERRA_BASE].mem_base +
349 core_info->a5_hw_info->a5_host_int_clr);
350
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700351 if ((irq_status & A5_WDT_0) ||
352 (irq_status & A5_WDT_1)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700353 CAM_ERR_RATE_LIMIT(CAM_ICP, "watch dog interrupt from A5");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700354 }
355
356 if (core_info->irq_cb.icp_hw_mgr_cb)
357 core_info->irq_cb.icp_hw_mgr_cb(irq_status,
358 core_info->irq_cb.data);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700359
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700360 return IRQ_HANDLED;
361}
362
363int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
364 void *cmd_args, uint32_t arg_size)
365{
366 struct cam_hw_info *a5_dev = device_priv;
367 struct cam_hw_soc_info *soc_info = NULL;
368 struct cam_a5_device_core_info *core_info = NULL;
369 struct cam_a5_device_hw_info *hw_info = NULL;
370 int rc = 0;
371
372 if (!device_priv) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700373 CAM_ERR(CAM_ICP, "Invalid arguments");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700374 return -EINVAL;
375 }
376
377 if (cmd_type >= CAM_ICP_A5_CMD_MAX) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700378 CAM_ERR(CAM_ICP, "Invalid command : %x", cmd_type);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700379 return -EINVAL;
380 }
381
382 soc_info = &a5_dev->soc_info;
383 core_info = (struct cam_a5_device_core_info *)a5_dev->core_info;
384 hw_info = core_info->a5_hw_info;
385
386 switch (cmd_type) {
387 case CAM_ICP_A5_CMD_FW_DOWNLOAD:
388 rc = cam_a5_download_fw(device_priv);
389
390 break;
391 case CAM_ICP_A5_CMD_SET_FW_BUF: {
392 struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args;
393
394 if (!cmd_args) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700395 CAM_ERR(CAM_ICP, "cmd args NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700396 return -EINVAL;
397 }
398
399 core_info->fw_buf = fw_buf_info->iova;
400 core_info->fw_kva_addr = fw_buf_info->kva;
401 core_info->fw_buf_len = fw_buf_info->len;
402
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700403 CAM_DBG(CAM_ICP, "fw buf info = %x %llx %lld",
404 core_info->fw_buf, core_info->fw_kva_addr,
405 core_info->fw_buf_len);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700406 break;
407 }
408 case CAM_ICP_A5_SET_IRQ_CB: {
409 struct cam_icp_a5_set_irq_cb *irq_cb = cmd_args;
410
411 if (!cmd_args) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700412 CAM_ERR(CAM_ICP, "cmd args NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700413 return -EINVAL;
414 }
415
416 core_info->irq_cb.icp_hw_mgr_cb = irq_cb->icp_hw_mgr_cb;
417 core_info->irq_cb.data = irq_cb->data;
418 break;
419 }
420
421 case CAM_ICP_A5_SEND_INIT:
422 hfi_send_system_cmd(HFI_CMD_SYS_INIT, 0, 0);
423 break;
424 case CAM_ICP_A5_CMD_VOTE_CPAS: {
425 struct cam_icp_cpas_vote *cpas_vote = cmd_args;
426
427 if (!cmd_args) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700428 CAM_ERR(CAM_ICP, "cmd args NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700429 return -EINVAL;
430 }
431
432 cam_a5_cpas_vote(core_info, cpas_vote);
433 break;
434 }
435
436 case CAM_ICP_A5_CMD_CPAS_START: {
437 struct cam_icp_cpas_vote *cpas_vote = cmd_args;
438
439 if (!cmd_args) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700440 CAM_ERR(CAM_ICP, "cmd args NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700441 return -EINVAL;
442 }
443
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700444 if (!core_info->cpas_start) {
445 rc = cam_cpas_start(core_info->cpas_handle,
446 &cpas_vote->ahb_vote,
447 &cpas_vote->axi_vote);
448 core_info->cpas_start = true;
449 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700450 break;
451 }
452
453 case CAM_ICP_A5_CMD_CPAS_STOP:
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700454 if (core_info->cpas_start) {
455 cam_cpas_stop(core_info->cpas_handle);
456 core_info->cpas_start = false;
457 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700458 break;
459 default:
460 break;
461 }
462
463 return rc;
464}