Merge "msm : ais : diagnostic feature"

This commit is contained in:
Linux Build Service Account 2018-06-12 10:36:43 -07:00 committed by Gerrit - the friendly Code Review server
commit ead1dfc47b
26 changed files with 1242 additions and 43 deletions

View file

@ -0,0 +1,164 @@
* Qualcomm Technologies, Inc. MSM Camera diag
[Root level node]
==================
Required properties:
- compatible: Must be "qcom,diag-cam".
[Subnode]
==========
Required properties:
- mmagic-supply: should contain mmagic regulator used for mmagic clocks.
- gdscr-supply: should contain gdsr regulator used for cci clocks.
- vfe0-vdd-supply: phandle to vfe0 regulator.
- qcom,cam-vreg-name: name of the voltage regulators required for the device.
- clocks: List of clock handles. The parent clocks of the input clocks to the
devices in this power domain are set to oscclk before power gating
and restored back after powering on a domain. This is required for
all domains which are powered on and off and not required for unused
domains.
- clock-names: name of the clock used by the driver.
- qcom,clock-rates: clock rate in Hz.
- qcom,clock-control: The valid fields are "NO_SET_RATE", "INIT_RATE" and
"SET_RATE". "NO_SET_RATE" the corresponding clock is enabled without setting
the rate assuming some other driver has already set it to appropriate rate.
"INIT_RATE" clock rate is not queried assuming some other driver has set
the clock rate and ispif will set the the clock to this rate.
"SET_RATE" clock is enabled and the rate is set to the value specified
in the property qcom,clock-rates.
Example:
qcom,diag-cam {
cell-index = <0>;
compatible = "qcom,diag-cam";
status = "ok";
mmagic-supply = <&gdsc_mmagic_camss>;
gdscr-supply = <&gdsc_camss_top>;
vfe0-vdd-supply = <&gdsc_vfe0>;
vfe1-vdd-supply = <&gdsc_vfe1>;
qcom,cam-vreg-name = "mmagic", "gdscr",
"vfe0-vdd", "vfe1-vdd";
clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
<&clock_mmss clk_camss_top_ahb_clk>,
<&clock_mmss clk_camss_ispif_ahb_clk>,
<&clock_mmss clk_csi0phytimer_clk_src>,
<&clock_mmss clk_camss_csi0phytimer_clk>,
<&clock_mmss clk_camss_ahb_clk>,
<&clock_mmss clk_csi1phytimer_clk_src>,
<&clock_mmss clk_camss_csi1phytimer_clk>,
<&clock_mmss clk_csi2phytimer_clk_src>,
<&clock_mmss clk_camss_csi2phytimer_clk>,
<&clock_mmss clk_csi0_clk_src>,
<&clock_mmss clk_camss_csi0_clk>,
<&clock_mmss clk_camss_csi0phy_clk>,
<&clock_mmss clk_camss_csi0_ahb_clk>,
<&clock_mmss clk_camss_csi0rdi_clk>,
<&clock_mmss clk_camss_csi0pix_clk>,
<&clock_mmss clk_csi1_clk_src>,
<&clock_mmss clk_camss_csi1_clk>,
<&clock_mmss clk_camss_csi1phy_clk>,
<&clock_mmss clk_camss_csi1_ahb_clk>,
<&clock_mmss clk_camss_csi1rdi_clk>,
<&clock_mmss clk_camss_csi1pix_clk>,
<&clock_mmss clk_csi2_clk_src>,
<&clock_mmss clk_camss_csi2_clk>,
<&clock_mmss clk_camss_csi2phy_clk>,
<&clock_mmss clk_camss_csi2_ahb_clk>,
<&clock_mmss clk_camss_csi2rdi_clk>,
<&clock_mmss clk_camss_csi2pix_clk>,
<&clock_mmss clk_csi3_clk_src>,
<&clock_mmss clk_camss_csi3_clk>,
<&clock_mmss clk_camss_csi3phy_clk>,
<&clock_mmss clk_camss_csi3_ahb_clk>,
<&clock_mmss clk_camss_csi3rdi_clk>,
<&clock_mmss clk_camss_csi3pix_clk>,
<&clock_mmss clk_vfe0_clk_src>,
<&clock_mmss clk_camss_vfe0_clk>,
<&clock_mmss clk_camss_csi_vfe0_clk>,
<&clock_mmss clk_vfe1_clk_src>,
<&clock_mmss clk_camss_vfe1_clk>,
<&clock_mmss clk_camss_csi_vfe1_clk>,
<&clock_mmss clk_mmagic_camss_axi_clk>,
<&clock_mmss clk_camss_vfe_ahb_clk>,
<&clock_mmss clk_camss_vfe0_ahb_clk>,
<&clock_mmss clk_camss_vfe_axi_clk>,
<&clock_mmss clk_camss_vfe0_stream_clk>,
<&clock_mmss clk_smmu_vfe_axi_clk>,
<&clock_mmss clk_camss_vfe1_ahb_clk>,
<&clock_mmss clk_camss_vfe1_stream_clk>;
clock-names =
"clk_mmss_mmagic_ahb_clk",
"clk_camss_top_ahb_clk",
"clk_camss_ispif_ahb_clk",
"clk_csi0phytimer_clk_src",
"clk_camss_csi0phytimer_clk",
"clk_camss_ahb_clk",
"clk_csi1phytimer_clk_src",
"clk_camss_csi1phytimer_clk",
"clk_csi2phytimer_clk_src",
"clk_camss_csi2phytimer_clk",
"clk_csi0_clk_src",
"clk_camss_csi0_clk",
"clk_camss_csi0phy_clk",
"clk_camss_csi0_ahb_clk",
"clk_camss_csi0rdi_clk",
"clk_camss_csi0pix_clk",
"clk_csi1_clk_src",
"clk_camss_csi1_clk",
"clk_camss_csi1phy_clk",
"clk_camss_csi1_ahb_clk",
"clk_camss_csi1rdi_clk",
"clk_camss_csi1pix_clk",
"clk_csi2_clk_src",
"clk_camss_csi2_clk",
"clk_camss_csi2phy_clk",
"clk_camss_csi2_ahb_clk",
"clk_camss_csi2rdi_clk",
"clk_camss_csi2pix_clk",
"clk_csi3_clk_src",
"clk_camss_csi3_clk",
"clk_camss_csi3phy_clk",
"clk_camss_csi3_ahb_clk",
"clk_camss_csi3rdi_clk",
"clk_camss_csi3pix_clk",
"clk_vfe0_clk_src",
"clk_camss_vfe0_clk",
"clk_camss_csi_vfe0_clk",
"clk_vfe1_clk_src",
"clk_camss_vfe1_clk",
"clk_camss_csi_vfe1_clk",
"clk_mmagic_camss_axi_clk",
"clk_camss_vfe_ahb_clk",
"clk_camss_vfe0_ahb_clk",
"clk_camss_vfe_axi_clk",
"clk_camss_vfe0_stream_clk",
"clk_smmu_vfe_axi_clk",
"clk_camss_vfe1_ahb_clk",
"clk_camss_vfe1_stream_clk";
qcom,clock-rates = <0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
>;
qcom,clock-cntl-support;
qcom,clock-control = "NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE",
"INIT_RATE","NO_SET_RATE","NO_SET_RATE",
"INIT_RATE","NO_SET_RATE","INIT_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE",
"NO_SET_RATE","NO_SET_RATE","NO_SET_RATE";
};

View file

@ -22,4 +22,5 @@ obj-$(CONFIG_MSM_AIS_JPEG) += jpeg_10/
obj-$(CONFIG_MSM_AIS_JPEGDMA) += jpeg_dma/ obj-$(CONFIG_MSM_AIS_JPEGDMA) += jpeg_dma/
obj-$(CONFIG_MSM_AIS) += msm_buf_mgr/ obj-$(CONFIG_MSM_AIS) += msm_buf_mgr/
obj-$(CONFIG_MSM_AIS) += msm_ais_mgr/ obj-$(CONFIG_MSM_AIS) += msm_ais_mgr/
obj-$(CONFIG_MSM_AIS) += msm_ais_diag/
obj-$(CONFIG_MSM_AIS_FD) += fd/ obj-$(CONFIG_MSM_AIS_FD) += fd/

View file

@ -1,2 +1,2 @@
ccflags-y += -Idrivers/media/platform/msm/ais/ ccflags-y += -Idrivers/media/platform/msm/ais/
obj-$(CONFIG_MSM_AIS) += msm_camera_io_util.o cam_smmu_api.o cam_hw_ops.o cam_soc_api.o obj-$(CONFIG_MSM_AIS) += msm_camera_io_util.o cam_smmu_api.o cam_hw_ops.o cam_soc_api.o msm_camera_diag_util.o

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -19,6 +19,7 @@
#include <linux/pm_opp.h> #include <linux/pm_opp.h>
#include <linux/regulator/rpm-smd-regulator.h> #include <linux/regulator/rpm-smd-regulator.h>
#include "cam_hw_ops.h" #include "cam_hw_ops.h"
#include "msm_camera_diag_util.h"
#ifdef CONFIG_CAM_AHB_DBG #ifdef CONFIG_CAM_AHB_DBG
#define CDBG(fmt, args...) pr_err(fmt, ##args) #define CDBG(fmt, args...) pr_err(fmt, ##args)
@ -242,6 +243,8 @@ static int cam_consolidate_ahb_vote(enum cam_ahb_clk_client id,
data.ahb_clk_state = max; data.ahb_clk_state = max;
CDBG("dbg: state : %u, vector : %d\n", CDBG("dbg: state : %u, vector : %d\n",
data.ahb_clk_state, max); data.ahb_clk_state, max);
msm_camera_diag_update_ahb_state(data.ahb_clk_state);
} }
} else { } else {
pr_err("err: no bus vector found\n"); pr_err("err: no bus vector found\n");

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -12,16 +12,7 @@
#ifndef _CAM_HW_OPS_H_ #ifndef _CAM_HW_OPS_H_
#define _CAM_HW_OPS_H_ #define _CAM_HW_OPS_H_
enum cam_ahb_clk_vote { #include <media/ais/msm_ais_mgr.h>
/* need to update the voting requests
* according to dtsi entries.
*/
CAM_AHB_SUSPEND_VOTE = 0x0,
CAM_AHB_SVS_VOTE = 0x01,
CAM_AHB_NOMINAL_VOTE = 0x02,
CAM_AHB_TURBO_VOTE = 0x03,
CAM_AHB_DYNAMIC_VOTE = 0xFF,
};
enum cam_ahb_clk_client { enum cam_ahb_clk_client {
CAM_AHB_CLIENT_CSIPHY, CAM_AHB_CLIENT_CSIPHY,

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -25,6 +25,7 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <linux/msm-bus.h> #include <linux/msm-bus.h>
#include "cam_soc_api.h" #include "cam_soc_api.h"
#include "msm_camera_diag_util.h"
struct msm_cam_bus_pscale_data { struct msm_cam_bus_pscale_data {
struct msm_bus_scale_pdata *pdata; struct msm_bus_scale_pdata *pdata;
@ -374,6 +375,8 @@ int msm_camera_clk_enable(struct device *dev,
if (clk_rate == 0) { if (clk_rate == 0) {
clk_rate = clk_rate =
clk_round_rate(clk_ptr[i], 0); clk_round_rate(clk_ptr[i], 0);
if (clk_rate < 0) { if (clk_rate < 0) {
pr_err("%s round rate failed\n", pr_err("%s round rate failed\n",
clk_info[i].clk_name); clk_info[i].clk_name);
@ -410,6 +413,8 @@ int msm_camera_clk_enable(struct device *dev,
} }
} }
} }
msm_camera_diag_update_clklist(clk_info, clk_ptr, num_clk, enable);
return rc; return rc;
cam_clk_enable_err: cam_clk_enable_err:

View file

@ -0,0 +1,364 @@
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "msm_camera_diag_util.h"
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of.h>
#include <linux/irqreturn.h>
#include <linux/mutex.h>
#include <linux/io.h>
#include <media/v4l2-subdev.h>
#include <linux/ratelimit.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include "msm_camera_io_util.h"
#include "msm.h"
#define MAX_CLK_NUM 100
struct camera_diag_clk_list {
struct msm_ais_diag_clk_info_t *clk_infolist;
struct clk **ppclk;
uint32_t clk_num;
uint32_t clk_capacity;
struct mutex lock;
};
struct camera_diag_ddrbw {
struct msm_ais_diag_bus_info_t bus_info;
struct mutex lock;
};
static struct camera_diag_clk_list s_diag_clk_list;
static struct camera_diag_ddrbw s_ddrbw;
int msm_camera_get_reg_list(void __iomem *base,
struct msm_camera_reg_list_cmd *reg_list)
{
int rc = 0;
uint32_t i;
uint32_t *reg_values = NULL;
uint32_t addrs_size = sizeof(uint32_t) * reg_list->reg_num;
uint32_t *reg_addrs = kzalloc(addrs_size, GFP_KERNEL);
if (!reg_addrs) {
rc = -ENOMEM;
goto alloc_addr_failed;
}
if (copy_from_user(reg_addrs,
(void __user *)(reg_list->regaddr_list),
sizeof(uint32_t) * reg_list->reg_num)) {
rc = -EFAULT;
pr_err("%s copy_from_user fail\n", __func__);
goto copy_addr_failed;
}
reg_values = kzalloc(addrs_size, GFP_KERNEL);
if (!reg_values) {
rc = -ENOMEM;
goto copy_addr_failed;
}
for (i = 0 ; i < reg_list->reg_num; ++i) {
reg_values[i] = msm_camera_io_r(base + reg_addrs[i]);
pr_debug("reg 0x%x 0x%x\n",
reg_addrs[i],
reg_values[i]);
}
if (copy_to_user(reg_list->value_list, reg_values,
sizeof(uint32_t) * reg_list->reg_num)) {
rc = -EFAULT;
pr_err("%s copy_to_user fail %u\n",
__func__,
reg_list->reg_num);
goto copy_value_failed;
}
copy_value_failed:
kfree(reg_values);
copy_addr_failed:
kfree(reg_addrs);
alloc_addr_failed:
return rc;
}
int msm_camera_diag_init(void)
{
s_diag_clk_list.clk_num = 0;
s_diag_clk_list.clk_capacity = MAX_CLK_NUM;
s_diag_clk_list.clk_infolist = kzalloc(
sizeof(struct msm_ais_diag_clk_info_t) *
s_diag_clk_list.clk_capacity,
GFP_KERNEL);
if (!s_diag_clk_list.clk_infolist)
return -ENOMEM;
s_diag_clk_list.ppclk = kzalloc(sizeof(struct clk *) *
s_diag_clk_list.clk_capacity,
GFP_KERNEL);
if (!s_diag_clk_list.ppclk) {
kfree(s_diag_clk_list.clk_infolist);
return -ENOMEM;
}
mutex_init(&s_diag_clk_list.lock);
mutex_init(&s_ddrbw.lock);
return 0;
}
int msm_camera_diag_uninit(void)
{
mutex_destroy(&s_ddrbw.lock);
mutex_destroy(&s_diag_clk_list.lock);
kfree(s_diag_clk_list.clk_infolist);
s_diag_clk_list.clk_infolist = NULL;
kfree(s_diag_clk_list.ppclk);
s_diag_clk_list.ppclk = NULL;
return 0;
}
static uint32_t msm_camera_diag_find_clk_idx(
struct msm_cam_clk_info *clk_info,
struct clk *clk_ptr)
{
uint32_t i = 0;
for (; i < s_diag_clk_list.clk_num; ++i) {
if (clk_ptr == s_diag_clk_list.ppclk[i])
return i;
}
return s_diag_clk_list.clk_capacity;
}
int msm_camera_diag_update_clklist(
struct msm_cam_clk_info *clk_info,
struct clk **clk_ptr, int num_clk, int enable)
{
uint32_t i = 0;
uint32_t idx = 0;
uint32_t actual_idx = 0;
struct msm_ais_diag_clk_info_t *pclk_info = NULL;
mutex_lock(&s_diag_clk_list.lock);
for (; i < num_clk; ++i) {
idx = msm_camera_diag_find_clk_idx(&clk_info[i], clk_ptr[i]);
if (idx < s_diag_clk_list.clk_num) {
actual_idx = idx;
pclk_info =
&s_diag_clk_list.clk_infolist[actual_idx];
} else if (s_diag_clk_list.clk_num <
s_diag_clk_list.clk_capacity) {
actual_idx = s_diag_clk_list.clk_num++;
memset(&s_diag_clk_list.clk_infolist[actual_idx],
0,
sizeof(struct msm_ais_diag_clk_info_t));
pclk_info =
&s_diag_clk_list.clk_infolist[actual_idx];
memcpy(pclk_info->clk_name,
clk_info[i].clk_name,
sizeof(pclk_info->clk_name));
s_diag_clk_list.ppclk[actual_idx] = clk_ptr[i];
pr_debug("%s new clk %s clk_num %u\n",
__func__,
clk_info[i].clk_name,
s_diag_clk_list.clk_num);
} else {
pr_err("%s too many clks\n", __func__);
continue;
}
pclk_info->clk_rate = clk_get_rate(clk_ptr[i]);
if (enable) {
++pclk_info->enable;
} else {
int cnt = pclk_info->enable;
if (cnt > 0)
--pclk_info->enable;
}
}
mutex_unlock(&s_diag_clk_list.lock);
return 0;
}
int msm_camera_diag_get_clk_list(
struct msm_ais_diag_clk_list_t *clk_infolist)
{
int rc = 0;
mutex_lock(&s_diag_clk_list.lock);
clk_infolist->clk_num = s_diag_clk_list.clk_num;
if (copy_to_user(clk_infolist->clk_info,
s_diag_clk_list.clk_infolist,
sizeof(struct msm_ais_diag_clk_info_t) *
s_diag_clk_list.clk_num)) {
rc = -EFAULT;
}
mutex_unlock(&s_diag_clk_list.lock);
return rc;
}
int msm_camera_diag_get_gpio_list(
struct msm_ais_diag_gpio_list_t *gpio_list)
{
int rc = 0;
uint32_t gpio_num = gpio_list->gpio_num;
uint32_t i = 0;
int32_t *vals = NULL;
uint32_t idxs_size = sizeof(uint32_t) * gpio_num;
uint32_t vals_size = sizeof(int32_t) * gpio_num;
uint32_t *idxs = kzalloc(idxs_size, GFP_KERNEL);
if (!idxs) {
rc = -ENOMEM;
goto alloc_idxs_failed;
}
if (copy_from_user(idxs,
(void __user *)(gpio_list->gpio_idx_list),
idxs_size)) {
rc = -EFAULT;
pr_err("%s copy_from_user fail\n", __func__);
goto copy_idxs_failed;
}
vals = kzalloc(vals_size, GFP_KERNEL);
if (!vals) {
rc = -ENOMEM;
goto copy_idxs_failed;
}
for (; i < gpio_num; ++i)
vals[i] =
gpio_get_value(idxs[i]);
if (copy_to_user(gpio_list->gpio_val_list, vals,
vals_size)) {
rc = -EFAULT;
pr_err("%s copy_to_user fail %u\n",
__func__,
gpio_num);
}
kfree(vals);
copy_idxs_failed:
kfree(idxs);
alloc_idxs_failed:
return rc;
}
int msm_camera_diag_set_gpio_list(
struct msm_ais_diag_gpio_list_t *gpio_list)
{
int rc = 0;
uint32_t gpio_num = gpio_list->gpio_num;
uint32_t i = 0;
int32_t val;
int32_t *vals = NULL;
uint32_t idxs_size = sizeof(uint32_t) * gpio_num;
uint32_t vals_size = sizeof(int32_t) * gpio_num;
uint32_t *idxs = kzalloc(idxs_size, GFP_KERNEL);
if (!idxs) {
rc = -ENOMEM;
goto alloc_idxs_failed;
}
if (copy_from_user(idxs,
(void __user *)(gpio_list->gpio_idx_list),
idxs_size)) {
rc = -EFAULT;
pr_err("%s copy_from_user fail\n", __func__);
goto copy_idxs_failed;
}
vals = kzalloc(vals_size, GFP_KERNEL);
if (!vals) {
rc = -ENOMEM;
goto copy_idxs_failed;
}
if (copy_from_user(vals,
(void __user *)(gpio_list->gpio_val_list),
vals_size)) {
rc = -EFAULT;
pr_err("%s copy_from_user fail\n", __func__);
goto copy_vals_failed;
}
for (; i < gpio_num; ++i) {
gpio_set_value(idxs[i], vals[i]);
val = gpio_get_value(idxs[i]);
pr_debug("val set %d after %d\n", vals[i], val);
}
copy_vals_failed:
kfree(vals);
copy_idxs_failed:
kfree(idxs);
alloc_idxs_failed:
return rc;
}
int msm_camera_diag_update_ahb_state(enum cam_ahb_clk_vote vote)
{
mutex_lock(&s_ddrbw.lock);
s_ddrbw.bus_info.ahb_clk_vote_state = vote;
mutex_unlock(&s_ddrbw.lock);
return 0;
}
int msm_camera_diag_update_isp_state(
uint32_t isp_bus_vector_idx,
uint64_t isp_ab, uint64_t isp_ib)
{
mutex_lock(&s_ddrbw.lock);
s_ddrbw.bus_info.isp_bus_vector_idx = isp_bus_vector_idx;
s_ddrbw.bus_info.isp_ab = isp_ab;
s_ddrbw.bus_info.isp_ib = isp_ib;
mutex_unlock(&s_ddrbw.lock);
return 0;
}
int msm_camera_diag_get_ddrbw(struct msm_ais_diag_bus_info_t *info)
{
int rc = 0;
mutex_lock(&s_ddrbw.lock);
info->ahb_clk_vote_state = s_ddrbw.bus_info.ahb_clk_vote_state;
info->isp_bus_vector_idx = s_ddrbw.bus_info.isp_bus_vector_idx;
info->isp_ab = s_ddrbw.bus_info.isp_ab;
info->isp_ib = s_ddrbw.bus_info.isp_ib;
mutex_unlock(&s_ddrbw.lock);
return rc;
}

View file

@ -0,0 +1,47 @@
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef __MSM_CAMERA_DIAG_UTIL_H
#define __MSM_CAMERA_DIAG_UTIL_H
#include <media/ais/msm_ais_mgr.h>
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/msm-bus.h>
#include <linux/mutex.h>
#include <linux/clk.h>
#include <linux/regulator/consumer.h>
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <soc/qcom/ais.h>
int msm_camera_get_reg_list(void __iomem *base,
struct msm_camera_reg_list_cmd *reg_list);
int msm_camera_diag_init(void);
int msm_camera_diag_uninit(void);
int msm_camera_diag_update_clklist(struct msm_cam_clk_info *clk_info,
struct clk **clk_ptr, int num_clk, int enable);
int msm_camera_diag_get_clk_list(
struct msm_ais_diag_clk_list_t *clk_infolist);
int msm_camera_diag_update_ahb_state(enum cam_ahb_clk_vote vote);
int msm_camera_diag_update_isp_state(uint32_t isp_bus_vector_idx,
uint64_t isp_ab, uint64_t isp_ib);
int msm_camera_diag_get_ddrbw(struct msm_ais_diag_bus_info_t *info);
int msm_camera_diag_get_gpio_list(
struct msm_ais_diag_gpio_list_t *gpio_list);
int msm_camera_diag_set_gpio_list(
struct msm_ais_diag_gpio_list_t *gpio_list);
#endif

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -19,6 +19,7 @@
#include <soc/qcom/ais.h> #include <soc/qcom/ais.h>
#include <linux/msm-bus.h> #include <linux/msm-bus.h>
#include "msm_camera_io_util.h" #include "msm_camera_io_util.h"
#include "msm_camera_diag_util.h"
#define BUFF_SIZE_128 128 #define BUFF_SIZE_128 128
@ -365,6 +366,8 @@ int msm_cam_clk_enable(struct device *dev, struct msm_cam_clk_info *clk_info,
} }
} }
} }
msm_camera_diag_update_clklist(clk_info, clk_ptr, num_clk, enable);
return rc; return rc;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -1144,6 +1144,43 @@ static void msm_isp_release_all_bufq(
} }
} }
static int msm_isp_get_bufq_state(struct msm_isp_buf_mgr *buf_mgr,
struct msm_vfe_bufq_state *bufq_state)
{
int rc = 0;
struct msm_isp_bufq *bufq = NULL;
uint32_t i = 0;
int32_t *k_bufq_states = NULL;
uint32_t size = 0;
bufq = msm_isp_get_bufq(buf_mgr, bufq_state->handle);
if (bufq) {
bufq_state->nbufs = bufq->num_bufs;
size = bufq->num_bufs*sizeof(int32_t);
k_bufq_states = kzalloc(size, GFP_KERNEL);
if (!k_bufq_states) {
rc = -ENOMEM;
goto alloc_states_failed;
}
for (i = 0; i < bufq_state->nbufs; ++i)
k_bufq_states[i] = bufq->bufs[i].state;
if (copy_to_user(bufq_state->buf_state,
k_bufq_states,
sizeof(int32_t) * bufq->num_bufs)) {
rc = -EFAULT;
pr_err("%s copy_to_user fail\n", __func__);
goto copy_failed;
}
copy_failed:
kfree(k_bufq_states);
}
alloc_states_failed:
return rc;
}
/** /**
* msm_isp_buf_put_scratch() - Release scratch buffers * msm_isp_buf_put_scratch() - Release scratch buffers
@ -1357,6 +1394,14 @@ int msm_isp_proc_buf_cmd(struct msm_isp_buf_mgr *buf_mgr,
rc = buf_mgr->ops->unmap_buf(buf_mgr, unmap_req->fd); rc = buf_mgr->ops->unmap_buf(buf_mgr, unmap_req->fd);
break; break;
} }
case VIDIOC_MSM_ISP_CMD_EXT: {
struct msm_vfe_cmd_ext *cmd_ext = (struct msm_vfe_cmd_ext *)arg;
if (cmd_ext->type == VFE_GET_BUFQ_STATE)
rc = buf_mgr->ops->get_bufq_state(buf_mgr,
&cmd_ext->data.bufq_state);
break;
}
} }
return rc; return rc;
} }
@ -1507,6 +1552,7 @@ static struct msm_isp_buf_ops isp_buf_ops = {
.buf_mgr_debug = msm_isp_buf_mgr_debug, .buf_mgr_debug = msm_isp_buf_mgr_debug,
.get_bufq = msm_isp_get_bufq, .get_bufq = msm_isp_get_bufq,
.update_put_buf_cnt = msm_isp_update_put_buf_cnt, .update_put_buf_cnt = msm_isp_update_put_buf_cnt,
.get_bufq_state = msm_isp_get_bufq_state,
}; };
int msm_isp_create_isp_buf_mgr( int msm_isp_create_isp_buf_mgr(

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -44,16 +44,6 @@ enum msm_isp_buffer_src_t {
MSM_ISP_BUFFER_SRC_MAX, MSM_ISP_BUFFER_SRC_MAX,
}; };
enum msm_isp_buffer_state {
MSM_ISP_BUFFER_STATE_UNUSED, /* not used */
MSM_ISP_BUFFER_STATE_INITIALIZED, /* REQBUF done */
MSM_ISP_BUFFER_STATE_PREPARED, /* BUF mapped */
MSM_ISP_BUFFER_STATE_QUEUED, /* buf queued */
MSM_ISP_BUFFER_STATE_DEQUEUED, /* in use in VFE */
MSM_ISP_BUFFER_STATE_DIVERTED, /* Sent to other hardware*/
MSM_ISP_BUFFER_STATE_DISPATCHED, /* Sent to HAL*/
};
enum msm_isp_buffer_put_state { enum msm_isp_buffer_put_state {
MSM_ISP_BUFFER_STATE_PUT_PREPARED, /* on init */ MSM_ISP_BUFFER_STATE_PUT_PREPARED, /* on init */
MSM_ISP_BUFFER_STATE_PUT_BUF, /* on rotation */ MSM_ISP_BUFFER_STATE_PUT_BUF, /* on rotation */
@ -182,6 +172,9 @@ struct msm_isp_buf_ops {
int (*update_put_buf_cnt)(struct msm_isp_buf_mgr *buf_mgr, int (*update_put_buf_cnt)(struct msm_isp_buf_mgr *buf_mgr,
uint32_t id, uint32_t bufq_handle, int32_t buf_index, uint32_t id, uint32_t bufq_handle, int32_t buf_index,
struct timeval *tv, uint32_t frame_id, uint32_t pingpong_bit); struct timeval *tv, uint32_t frame_id, uint32_t pingpong_bit);
int (*get_bufq_state)(struct msm_isp_buf_mgr *buf_mgr,
struct msm_vfe_bufq_state *bufq_state);
}; };
struct msm_isp_buf_mgr { struct msm_isp_buf_mgr {

View file

@ -22,6 +22,7 @@
#include "cam_hw_ops.h" #include "cam_hw_ops.h"
#include "msm_isp47.h" #include "msm_isp47.h"
#include "cam_soc_api.h" #include "cam_soc_api.h"
#include "msm_camera_diag_util.h"
#undef CDBG #undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args) #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@ -2396,6 +2397,8 @@ int msm_vfe47_update_bandwidth(
ab, ib, ab, ib,
isp_bandwidth_mgr->client_info, isp_bandwidth_mgr->client_info,
sched_clock()); sched_clock());
msm_camera_diag_update_isp_state(
isp_bandwidth_mgr->bus_vector_active_idx, ab, ib);
return 0; return 0;
} }

View file

@ -847,6 +847,24 @@ static int msm_isp_proc_cmd_list(struct vfe_device *vfe_dev, void *arg)
} }
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
static int process_isp_cmd_ext(struct vfe_device *vfe_dev, void *arg)
{
int rc = 0;
struct msm_vfe_cmd_ext *cmd = (struct msm_vfe_cmd_ext *)arg;
switch (cmd->type) {
case VFE_GET_BUFQ_STATE: {
mutex_lock(&vfe_dev->buf_mgr->lock);
rc = msm_isp_proc_buf_cmd(vfe_dev->buf_mgr,
VIDIOC_MSM_ISP_CMD_EXT, arg);
mutex_unlock(&vfe_dev->buf_mgr->lock);
break;
}
}
return rc;
}
static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd, static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
unsigned int cmd, void *arg) unsigned int cmd, void *arg)
{ {
@ -983,12 +1001,14 @@ static long msm_isp_ioctl_unlocked(struct v4l2_subdev *sd,
mutex_unlock(&vfe_dev->core_mutex); mutex_unlock(&vfe_dev->core_mutex);
break; break;
case VIDIOC_MSM_ISP_FETCH_ENG_START: case VIDIOC_MSM_ISP_FETCH_ENG_START:
case VIDIOC_MSM_ISP_MAP_BUF_START_FE:
mutex_lock(&vfe_dev->core_mutex); mutex_lock(&vfe_dev->core_mutex);
rc = msm_isp_start_fetch_engine(vfe_dev, arg); rc = msm_isp_start_fetch_engine(vfe_dev, arg);
mutex_unlock(&vfe_dev->core_mutex); mutex_unlock(&vfe_dev->core_mutex);
break; break;
case VIDIOC_MSM_ISP_CMD_EXT:
process_isp_cmd_ext(vfe_dev, arg);
break;
case VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START: case VIDIOC_MSM_ISP_FETCH_ENG_MULTI_PASS_START:
case VIDIOC_MSM_ISP_MAP_BUF_START_MULTI_PASS_FE: case VIDIOC_MSM_ISP_MAP_BUF_START_MULTI_PASS_FE:
mutex_lock(&vfe_dev->core_mutex); mutex_lock(&vfe_dev->core_mutex);
@ -2350,16 +2370,6 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_lock(&vfe_dev->realtime_mutex); mutex_lock(&vfe_dev->realtime_mutex);
mutex_lock(&vfe_dev->core_mutex); mutex_lock(&vfe_dev->core_mutex);
/* Enable vfe clks to wake up from XO shutdown mode */
if (vfe_dev->pdev->id == 0)
id = CAM_AHB_CLIENT_VFE0;
else
id = CAM_AHB_CLIENT_VFE1;
if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SVS_VOTE) < 0)
pr_err("%s: failed to vote for AHB\n", __func__);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_clks(vfe_dev, 1);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_regulators(vfe_dev, 1);
if (!vfe_dev->vfe_open_cnt) { if (!vfe_dev->vfe_open_cnt) {
pr_err("%s invalid state open cnt %d\n", __func__, pr_err("%s invalid state open cnt %d\n", __func__,
vfe_dev->vfe_open_cnt); vfe_dev->vfe_open_cnt);
@ -2374,6 +2384,17 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
mutex_unlock(&vfe_dev->realtime_mutex); mutex_unlock(&vfe_dev->realtime_mutex);
return 0; return 0;
} }
/* Enable vfe clks to wake up from XO shutdown mode */
if (vfe_dev->pdev->id == 0)
id = CAM_AHB_CLIENT_VFE0;
else
id = CAM_AHB_CLIENT_VFE1;
if (cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SVS_VOTE) < 0)
pr_err("%s: failed to vote for AHB\n", __func__);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_clks(vfe_dev, 1);
vfe_dev->hw_info->vfe_ops.platform_ops.enable_regulators(vfe_dev, 1);
/* Unregister page fault handler */ /* Unregister page fault handler */
cam_smmu_reg_client_page_fault_handler( cam_smmu_reg_client_page_fault_handler(
vfe_dev->buf_mgr->iommu_hdl, vfe_dev->buf_mgr->iommu_hdl,

View file

@ -29,6 +29,7 @@
#include "msm_camera_io_util.h" #include "msm_camera_io_util.h"
#include "cam_hw_ops.h" #include "cam_hw_ops.h"
#include "cam_soc_api.h" #include "cam_soc_api.h"
#include "msm_camera_diag_util.h"
#ifdef CONFIG_AIS_MSM_ISPIF_V1 #ifdef CONFIG_AIS_MSM_ISPIF_V1
#include "msm_ispif_hwreg_v1.h" #include "msm_ispif_hwreg_v1.h"
@ -1526,6 +1527,22 @@ static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
case ISPIF_SET_VFE_INFO: case ISPIF_SET_VFE_INFO:
rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info); rc = msm_ispif_set_vfe_info(ispif, &pcdata->vfe_info);
break; break;
case ISPIF_READ_REG_LIST_CMD:
{
struct msm_camera_reg_list_cmd reg_list_cmd;
if (copy_from_user(&reg_list_cmd,
(void __user *)pcdata->reg_list,
sizeof(struct msm_camera_reg_list_cmd))) {
pr_err("%s: %d failed\n", __func__, __LINE__);
rc = -EFAULT;
break;
}
rc = msm_camera_get_reg_list(ispif->base, &reg_list_cmd);
break;
}
case ISPIF_WRITE_REG_LIST_CMD:
break;
default: default:
pr_err("%s: invalid cfg_type\n", __func__); pr_err("%s: invalid cfg_type\n", __func__);
rc = -EINVAL; rc = -EINVAL;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -31,6 +31,7 @@
#include "msm_sd.h" #include "msm_sd.h"
#include "cam_hw_ops.h" #include "cam_hw_ops.h"
#include <media/ais/msm_ais_buf_mgr.h> #include <media/ais/msm_ais_buf_mgr.h>
#include "msm_camera_diag_util.h"
static struct v4l2_device *msm_v4l2_dev; static struct v4l2_device *msm_v4l2_dev;
@ -1384,6 +1385,12 @@ static int msm_probe(struct platform_device *pdev)
goto v4l2_fail; goto v4l2_fail;
} }
rc = msm_camera_diag_init();
if (rc < 0) {
pr_err("%s: failed to init diag clk list\n", __func__);
goto v4l2_fail;
}
goto probe_end; goto probe_end;
v4l2_fail: v4l2_fail:
@ -1428,6 +1435,7 @@ static int __init msm_init(void)
static void __exit msm_exit(void) static void __exit msm_exit(void)
{ {
msm_camera_diag_uninit();
platform_driver_unregister(&msm_driver); platform_driver_unregister(&msm_driver);
} }

View file

@ -0,0 +1,4 @@
ccflags-y += -Idrivers/media/platform/msm/ais
ccflags-y += -Idrivers/media/platform/msm/ais/common
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io
obj-$(CONFIG_MSM_AIS) += msm_diag_cam.o

View file

@ -0,0 +1,267 @@
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/regulator/consumer.h>
#include "msm_sd.h"
#include "msm_diag_cam.h"
#include "msm_camera_io_util.h"
#include "msm_camera_dt_util.h"
#include "cam_hw_ops.h"
#include "msm_camera_diag_util.h"
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
#undef DIAG_CAM_DBG
#ifdef MSM_DIAG_CAM_DEBUG
#define DIAG_CAM_DBG(fmt, args...) pr_err(fmt, ##args)
#else
#define DIAG_CAM_DBG(fmt, args...) pr_debug(fmt, ##args)
#endif
#define MSM_DIAG_CAM_DRV_NAME "msm_diag_cam"
static struct platform_driver msm_diag_camera_driver;
static struct diag_cam_device *new_diag_cam_dev;
int msm_ais_enable_allclocks(void)
{
int rc = 0;
CDBG("%s:\n", __func__);
/* Vote ON for clocks */
if (new_diag_cam_dev == NULL) {
rc = -EINVAL;
pr_err("%s: clock structure uninitialised %d\n", __func__,
rc);
return rc;
}
rc = msm_camera_enable_vreg(&new_diag_cam_dev->pdev->dev,
new_diag_cam_dev->diag_cam_vreg,
new_diag_cam_dev->regulator_count,
NULL,
0,
&new_diag_cam_dev->diag_cam_reg_ptr[0], 1);
if (rc < 0)
pr_err("%s:%d diag_cam enable_vreg failed\n", __func__,
__LINE__);
rc = msm_camera_clk_enable(&new_diag_cam_dev->pdev->dev,
new_diag_cam_dev->diag_cam_clk_info,
new_diag_cam_dev->diag_cam_clk,
new_diag_cam_dev->num_clk, true);
if (rc < 0) {
pr_err("%s: clk enable failed %d\n", __func__, rc);
rc = 0;
return rc;
}
pr_debug("Turned ON camera clocks\n");
return 0;
}
int msm_ais_disable_allclocks(void)
{
int rc = 0;
CDBG("%s:\n", __func__);
/* Vote OFF for clocks */
if (new_diag_cam_dev == NULL) {
rc = -EINVAL;
pr_err("%s: clock structure uninitialised %d\n", __func__,
rc);
return rc;
}
if ((new_diag_cam_dev->pdev == NULL) ||
(new_diag_cam_dev->diag_cam_clk_info == NULL) ||
(new_diag_cam_dev->diag_cam_clk == NULL) ||
(new_diag_cam_dev->num_clk == 0)) {
rc = -EINVAL;
pr_err("%s: Clock details uninitialised %d\n", __func__,
rc);
return rc;
}
rc = msm_camera_clk_enable(&new_diag_cam_dev->pdev->dev,
new_diag_cam_dev->diag_cam_clk_info,
new_diag_cam_dev->diag_cam_clk,
new_diag_cam_dev->num_clk, false);
if (rc < 0) {
pr_err("%s: clk disable failed %d\n", __func__, rc);
return rc;
}
rc = msm_camera_enable_vreg(&new_diag_cam_dev->pdev->dev,
new_diag_cam_dev->diag_cam_vreg,
new_diag_cam_dev->regulator_count,
NULL,
0,
&new_diag_cam_dev->diag_cam_reg_ptr[0], 0);
if (rc < 0)
pr_err("%s:%d diag_cam disable_vreg failed\n", __func__,
__LINE__);
pr_debug("Turned OFF camera clocks\n");
return 0;
}
int msm_diag_camera_get_vreginfo_list(
struct msm_ais_diag_regulator_info_list_t *p_vreglist)
{
int rc = 0;
uint32_t i = 0;
uint32_t len = 0;
uint32_t len1 = 0;
struct regulator *vreg = NULL;
char *vreg_name_inuser = NULL;
p_vreglist->regulator_num = new_diag_cam_dev->regulator_count;
pr_debug("ais diag regulator_count %u\n",
new_diag_cam_dev->regulator_count);
for (; i < p_vreglist->regulator_num ; ++i) {
vreg = new_diag_cam_dev->diag_cam_reg_ptr[i];
p_vreglist->infolist[i].enable =
regulator_is_enabled(vreg);
len = strlen(new_diag_cam_dev->diag_cam_vreg[i].reg_name);
len1 = sizeof(p_vreglist->infolist[i].regulatorname);
len = (len >= len1) ? len1 : (len+1);
vreg_name_inuser =
p_vreglist->infolist[i].regulatorname;
if (copy_to_user((void __user *)vreg_name_inuser,
(void *)new_diag_cam_dev->diag_cam_vreg[i].reg_name,
len)) {
rc = -EFAULT;
pr_err("%s copy_to_user fail\n", __func__);
break;
}
}
pr_debug("msm_diag_camera_get_vreginfo_list exit\n");
return rc;
}
static int msm_diag_cam_probe(struct platform_device *pdev)
{
int rc = 0;
CDBG("%s: pdev %pK device id = %d\n", __func__, pdev, pdev->id);
new_diag_cam_dev = kzalloc(sizeof(struct diag_cam_device),
GFP_KERNEL);
if (!new_diag_cam_dev)
return -ENOMEM;
if (pdev->dev.of_node)
of_property_read_u32((&pdev->dev)->of_node,
"cell-index", &pdev->id);
rc = msm_camera_get_clk_info(pdev,
&new_diag_cam_dev->diag_cam_clk_info,
&new_diag_cam_dev->diag_cam_clk,
&new_diag_cam_dev->num_clk);
if (rc < 0) {
pr_err("%s: msm_diag_cam_get_clk_info() failed", __func__);
kfree(new_diag_cam_dev);
return -EFAULT;
}
new_diag_cam_dev->ref_count = 0;
new_diag_cam_dev->pdev = pdev;
rc = msm_camera_get_dt_vreg_data(
new_diag_cam_dev->pdev->dev.of_node,
&(new_diag_cam_dev->diag_cam_vreg),
&(new_diag_cam_dev->regulator_count));
if (rc < 0) {
pr_err("%s: msm_camera_get_dt_vreg_data fail\n", __func__);
rc = -EFAULT;
goto diag_cam_release_mem;
}
if ((new_diag_cam_dev->regulator_count < 0) ||
(new_diag_cam_dev->regulator_count > MAX_REGULATOR)) {
pr_err("%s: invalid reg count = %d, max is %d\n", __func__,
new_diag_cam_dev->regulator_count, MAX_REGULATOR);
rc = -EFAULT;
goto diag_cam_invalid_vreg_data;
}
rc = msm_camera_config_vreg(&new_diag_cam_dev->pdev->dev,
new_diag_cam_dev->diag_cam_vreg,
new_diag_cam_dev->regulator_count,
NULL,
0,
&new_diag_cam_dev->diag_cam_reg_ptr[0], 1);
if (rc < 0)
pr_err("%s:%d diag_cam config_vreg failed\n", __func__,
__LINE__);
platform_set_drvdata(pdev, new_diag_cam_dev);
return 0;
diag_cam_invalid_vreg_data:
kfree(new_diag_cam_dev->diag_cam_vreg);
diag_cam_release_mem:
kfree(new_diag_cam_dev);
new_diag_cam_dev = NULL;
return rc;
}
static int msm_diag_cam_exit(struct platform_device *pdev)
{
return 0;
}
static int __init msm_diag_cam_init_module(void)
{
return platform_driver_register(&msm_diag_camera_driver);
}
static void __exit msm_diag_cam_exit_module(void)
{
kfree(new_diag_cam_dev);
platform_driver_unregister(&msm_diag_camera_driver);
}
static const struct of_device_id msm_diag_camera_match_table[] = {
{ .compatible = "qcom,diag-cam" },
{},
};
static struct platform_driver msm_diag_camera_driver = {
.probe = msm_diag_cam_probe,
.remove = msm_diag_cam_exit,
.driver = {
.name = MSM_DIAG_CAM_DRV_NAME,
.owner = THIS_MODULE,
.of_match_table = msm_diag_camera_match_table,
},
};
MODULE_DEVICE_TABLE(of, msm_diag_camera_match_table);
module_init(msm_diag_cam_init_module);
module_exit(msm_diag_cam_exit_module);
MODULE_DESCRIPTION("MSM diag camera driver");
MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,57 @@
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef MSM_DIAG_CAM_H
#define MSM_DIAG_CAM_H
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <media/v4l2-subdev.h>
#include <linux/workqueue.h>
#include <media/ais/msm_ais_sensor.h>
#include <soc/qcom/ais.h>
#include <media/ais/msm_ais.h>
#include "msm_sd.h"
#include "cam_soc_api.h"
#define NUM_MASTERS 2
#define NUM_QUEUES 2
#define TRUE 1
#define FALSE 0
enum msm_diag_cam_state_t {
AIS_DIAG_STATE_DISABLED,
AIS_DIAG_STATE_ENABLED,
};
struct diag_cam_device {
struct platform_device *pdev;
uint8_t ref_count;
enum msm_diag_cam_state_t diag_cam_state;
size_t num_clk;
size_t num_clk_cases;
struct clk **diag_cam_clk;
uint32_t **diag_cam_clk_rates;
struct msm_cam_clk_info *diag_cam_clk_info;
struct camera_vreg_t *diag_cam_vreg;
struct regulator *diag_cam_reg_ptr[MAX_REGULATOR];
int32_t regulator_count;
};
int msm_ais_enable_allclocks(void);
int msm_ais_disable_allclocks(void);
int msm_diag_camera_get_vreginfo_list(
struct msm_ais_diag_regulator_info_list_t *p_vreglist);
#endif

View file

@ -2,4 +2,5 @@ ccflags-y += -Idrivers/media/platform/msm/ais
ccflags-y += -Idrivers/media/platform/msm/ais/common ccflags-y += -Idrivers/media/platform/msm/ais/common
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/cci ccflags-y += -Idrivers/media/platform/msm/ais/sensor/cci
ccflags-y += -Idrivers/media/platform/msm/ais/msm_ais_diag
obj-$(CONFIG_MSM_AIS) += msm_ais_mgr.o obj-$(CONFIG_MSM_AIS) += msm_ais_mgr.o

View file

@ -15,6 +15,8 @@
#include <media/ais/msm_ais_mgr.h> #include <media/ais/msm_ais_mgr.h>
#include "msm_ais_mngr.h" #include "msm_ais_mngr.h"
#include "msm_early_cam.h" #include "msm_early_cam.h"
#include "msm_camera_diag_util.h"
#include "msm_diag_cam.h"
#undef CDBG #undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args) #define CDBG(fmt, args...) pr_debug(fmt, ##args)
@ -42,7 +44,56 @@ static long msm_ais_hndl_ioctl(struct v4l2_subdev *sd, void *arg)
case AIS_CLK_DISABLE: case AIS_CLK_DISABLE:
rc = msm_ais_disable_clocks(); rc = msm_ais_disable_clocks();
break; break;
case AIS_CLK_ENABLE_ALLCLK:
rc = msm_ais_enable_allclocks();
break;
case AIS_CLK_DISABLE_ALLCLK:
rc = msm_ais_disable_allclocks();
break;
default:
pr_err("invalid cfg_type\n");
rc = -EINVAL;
}
if (rc)
pr_err("msm_ais_hndl_ioctl failed %ld\n", rc);
mutex_unlock(&clk_mngr_dev->cont_mutex);
return rc;
}
static long msm_ais_hndl_ext_ioctl(struct v4l2_subdev *sd, void *arg)
{
long rc = 0;
struct clk_mgr_cfg_data_ext *pcdata =
(struct clk_mgr_cfg_data_ext *)arg;
struct msm_ais_mngr_device *clk_mngr_dev =
(struct msm_ais_mngr_device *)v4l2_get_subdevdata(sd);
if (WARN_ON(!clk_mngr_dev) || WARN_ON(!pcdata)) {
rc = -EINVAL;
return rc;
}
mutex_lock(&clk_mngr_dev->cont_mutex);
CDBG(pr_fmt("cfg_type = %d\n"), pcdata->cfg_type);
switch (pcdata->cfg_type) {
case AIS_DIAG_GET_REGULATOR_INFO_LIST:
rc = msm_diag_camera_get_vreginfo_list(
&pcdata->data.vreg_infolist);
break;
case AIS_DIAG_GET_BUS_INFO_STATE:
rc = msm_camera_diag_get_ddrbw(&pcdata->data.bus_info);
break;
case AIS_DIAG_GET_CLK_INFO_LIST:
rc = msm_camera_diag_get_clk_list(&pcdata->data.clk_infolist);
break;
case AIS_DIAG_GET_GPIO_LIST:
rc = msm_camera_diag_get_gpio_list(&pcdata->data.gpio_list);
break;
case AIS_DIAG_SET_GPIO_LIST:
rc = msm_camera_diag_set_gpio_list(&pcdata->data.gpio_list);
break;
default: default:
pr_err("invalid cfg_type\n"); pr_err("invalid cfg_type\n");
rc = -EINVAL; rc = -EINVAL;
@ -63,6 +114,11 @@ static long msm_ais_mngr_subdev_ioctl(struct v4l2_subdev *sd,
if (rc) if (rc)
pr_err("msm_ais_mngr_subdev_ioctl failed\n"); pr_err("msm_ais_mngr_subdev_ioctl failed\n");
break; break;
case VIDIOC_MSM_AIS_CLK_CFG_EXT:
rc = msm_ais_hndl_ext_ioctl(sd, arg);
if (rc)
pr_err("msm_ais_hndl_ext_ioctl failed\n");
break;
default: default:
rc = -ENOIOCTLCMD; rc = -ENOIOCTLCMD;
} }
@ -136,6 +192,7 @@ static int32_t __init msm_ais_mngr_init(void)
static void __exit msm_ais_mngr_exit(void) static void __exit msm_ais_mngr_exit(void)
{ {
msm_sd_unregister(&msm_ais_mngr_dev->subdev); msm_sd_unregister(&msm_ais_mngr_dev->subdev);
mutex_destroy(&msm_ais_mngr_dev->cont_mutex); mutex_destroy(&msm_ais_mngr_dev->cont_mutex);
kfree(msm_ais_mngr_dev); kfree(msm_ais_mngr_dev);

View file

@ -36,6 +36,7 @@
#include "include/msm_csid_3_6_0_hwreg.h" #include "include/msm_csid_3_6_0_hwreg.h"
#include "include/msm_csid_3_5_1_hwreg.h" #include "include/msm_csid_3_5_1_hwreg.h"
#include "cam_hw_ops.h" #include "cam_hw_ops.h"
#include "msm_camera_diag_util.h"
#define V4L2_IDENT_CSID 50002 #define V4L2_IDENT_CSID 50002
#define CSID_VERSION_V20 0x02000011 #define CSID_VERSION_V20 0x02000011
@ -870,6 +871,20 @@ static int32_t msm_csid_cmd(struct csid_device *csid_dev, void *arg)
case CSID_STOP: case CSID_STOP:
rc = msm_csid_stop(csid_dev, cdata->cfg.csid_cidmask); rc = msm_csid_stop(csid_dev, cdata->cfg.csid_cidmask);
break; break;
case CSID_READ_REG_LIST_CMD:
{
struct msm_camera_reg_list_cmd reg_list_cmd;
if (copy_from_user(&reg_list_cmd,
(void __user *)cdata->cfg.csid_reg_list_cmd,
sizeof(struct msm_camera_reg_list_cmd))) {
pr_err("%s: %d failed\n", __func__, __LINE__);
rc = -EFAULT;
break;
}
rc = msm_camera_get_reg_list(csid_dev->base, &reg_list_cmd);
break;
}
default: default:
pr_err("%s: %d failed\n", __func__, __LINE__); pr_err("%s: %d failed\n", __func__, __LINE__);
rc = -ENOIOCTLCMD; rc = -ENOIOCTLCMD;

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and * it under the terms of the GNU General Public License version 2 and
@ -27,6 +27,7 @@
#include "include/msm_csiphy_3_4_2_1_hwreg.h" #include "include/msm_csiphy_3_4_2_1_hwreg.h"
#include "include/msm_csiphy_3_5_hwreg.h" #include "include/msm_csiphy_3_5_hwreg.h"
#include "cam_hw_ops.h" #include "cam_hw_ops.h"
#include "msm_camera_diag_util.h"
#define DBG_CSIPHY 0 #define DBG_CSIPHY 0
#define SOF_DEBUG_ENABLE 1 #define SOF_DEBUG_ENABLE 1
@ -1264,6 +1265,20 @@ static int32_t msm_csiphy_cmd(struct csiphy_device *csiphy_dev, void *arg)
} }
break; break;
case CSIPHY_READ_REG_LIST_CMD:
{
struct msm_camera_reg_list_cmd reg_list_cmd;
if (copy_from_user(&reg_list_cmd,
(void __user *)cdata->cfg.csiphy_reg_list_cmd,
sizeof(struct msm_camera_reg_list_cmd))) {
pr_err("%s: %d failed\n", __func__, __LINE__);
rc = -EFAULT;
break;
}
rc = msm_camera_get_reg_list(csiphy_dev->base, &reg_list_cmd);
break;
}
default: default:
pr_err("%s: %d failed\n", __func__, __LINE__); pr_err("%s: %d failed\n", __func__, __LINE__);
rc = -ENOIOCTLCMD; rc = -ENOIOCTLCMD;

View file

@ -619,6 +619,33 @@ struct msm_vfe_axi_src_state {
uint32_t src_frame_id; uint32_t src_frame_id;
}; };
enum msm_vfe_cmd_ext_type_t {
VFE_GET_BUFQ_STATE,
};
enum msm_isp_buffer_state {
MSM_ISP_BUFFER_STATE_UNUSED, /* not used */
MSM_ISP_BUFFER_STATE_INITIALIZED, /* REQBUF done */
MSM_ISP_BUFFER_STATE_PREPARED, /* BUF mapped */
MSM_ISP_BUFFER_STATE_QUEUED, /* buf queued */
MSM_ISP_BUFFER_STATE_DEQUEUED, /* in use in VFE */
MSM_ISP_BUFFER_STATE_DIVERTED, /* Sent to other hardware*/
MSM_ISP_BUFFER_STATE_DISPATCHED, /* Sent to HAL*/
};
struct msm_vfe_bufq_state {
uint32_t handle;
uint32_t nbufs;
int32_t __user *buf_state;
};
struct msm_vfe_cmd_ext {
enum msm_vfe_cmd_ext_type_t type;
union {
struct msm_vfe_bufq_state bufq_state;
} data;
};
enum msm_isp_event_mask_index { enum msm_isp_event_mask_index {
ISP_EVENT_MASK_INDEX_STATS_NOTIFY = 0, ISP_EVENT_MASK_INDEX_STATS_NOTIFY = 0,
ISP_EVENT_MASK_INDEX_ERROR = 1, ISP_EVENT_MASK_INDEX_ERROR = 1,
@ -975,6 +1002,7 @@ enum msm_isp_ioctl_cmd_code {
MSM_ISP_STOP, MSM_ISP_STOP,
MSM_ISP_SET_CLK_STATUS, MSM_ISP_SET_CLK_STATUS,
MSM_ISP_CMD_EXT,
}; };
@ -1110,4 +1138,8 @@ enum msm_isp_ioctl_cmd_code {
_IOWR('V', MSM_ISP_SET_CLK_STATUS, \ _IOWR('V', MSM_ISP_SET_CLK_STATUS, \
unsigned int) unsigned int)
#define VIDIOC_MSM_ISP_CMD_EXT \
_IOWR('V', MSM_ISP_CMD_EXT, \
struct msm_vfe_cmd_ext)
#endif /* __UAPI_MSM_AIS_ISP__ */ #endif /* __UAPI_MSM_AIS_ISP__ */

View file

@ -4,6 +4,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/ais/msm_ais_mgr.h>
#define CSID_VERSION_V20 0x02000011 #define CSID_VERSION_V20 0x02000011
#define CSID_VERSION_V22 0x02001000 #define CSID_VERSION_V22 0x02001000
@ -141,10 +142,13 @@ enum ispif_cfg_type_t {
ISPIF_STOP, ISPIF_STOP,
ISPIF_ENABLE_REG_DUMP, ISPIF_ENABLE_REG_DUMP,
ISPIF_SET_VFE_INFO, ISPIF_SET_VFE_INFO,
ISPIF_CFG2 ISPIF_CFG2,
ISPIF_READ_REG_LIST_CMD,
ISPIF_WRITE_REG_LIST_CMD,
}; };
struct ispif_cfg_data_ext { struct ispif_cfg_data_ext {
enum ispif_cfg_type_t cfg_type; enum ispif_cfg_type_t cfg_type;
void __user *data; void __user *data;
@ -158,10 +162,12 @@ struct ispif_cfg_data {
uint32_t csid_version; /* ISPIF_INIT */ uint32_t csid_version; /* ISPIF_INIT */
struct msm_ispif_vfe_info vfe_info; /* ISPIF_SET_VFE_INFO */ struct msm_ispif_vfe_info vfe_info; /* ISPIF_SET_VFE_INFO */
struct msm_ispif_param_data params; /* CFG, START, STOP */ struct msm_ispif_param_data params; /* CFG, START, STOP */
struct msm_camera_reg_list_cmd *reg_list;
}; };
}; };
#define ISPIF_RDI_PACK_MODE_SUPPORT 1 #define ISPIF_RDI_PACK_MODE_SUPPORT 1
#define ISPIF_RW_REG_LIST_SUPPORT
#define VIDIOC_MSM_ISPIF_CFG \ #define VIDIOC_MSM_ISPIF_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE, struct ispif_cfg_data) _IOWR('V', BASE_VIDIOC_PRIVATE, struct ispif_cfg_data)

View file

@ -3,16 +3,87 @@
#include <media/ais/msm_ais.h> #include <media/ais/msm_ais.h>
#define VREGNAME_SIZE 32
#define CLKNAME_SIZE 32
enum cam_ahb_clk_vote {
/* need to update the voting requests
* according to dtsi entries.
*/
CAM_AHB_SUSPEND_VOTE = 0x0,
CAM_AHB_SVS_VOTE = 0x01,
CAM_AHB_NOMINAL_VOTE = 0x02,
CAM_AHB_TURBO_VOTE = 0x03,
CAM_AHB_DYNAMIC_VOTE = 0xFF,
};
enum clk_mgr_cfg_type_t { enum clk_mgr_cfg_type_t {
AIS_CLK_ENABLE, AIS_CLK_ENABLE,
AIS_CLK_DISABLE, AIS_CLK_DISABLE,
AIS_CLK_ENABLE_ALLCLK,
AIS_CLK_DISABLE_ALLCLK
};
enum ais_mgr_cfg_ext_type_t {
AIS_DIAG_GET_REGULATOR_INFO_LIST,
AIS_DIAG_GET_BUS_INFO_STATE,
AIS_DIAG_GET_CLK_INFO_LIST,
AIS_DIAG_GET_GPIO_LIST,
AIS_DIAG_SET_GPIO_LIST,
}; };
#define AIS_CLK_ENABLE AIS_CLK_ENABLE #define AIS_CLK_ENABLE AIS_CLK_ENABLE
#define AIS_CLK_DISABLE AIS_CLK_DISABLE #define AIS_CLK_DISABLE AIS_CLK_DISABLE
struct msm_camera_reg_list_cmd {
void __user *value_list;
void __user *regaddr_list;
uint32_t reg_num;
};
struct msm_ais_diag_regulator_info_t {
int enable;
char regulatorname[VREGNAME_SIZE];
};
struct msm_ais_diag_regulator_info_list_t {
struct msm_ais_diag_regulator_info_t *infolist;
uint32_t regulator_num;
};
struct msm_ais_diag_bus_info_t {
enum cam_ahb_clk_vote ahb_clk_vote_state;
uint32_t isp_bus_vector_idx; /* 0 - init 1- ping 2 - pong */
uint64_t isp_ab;
uint64_t isp_ib;
};
struct msm_ais_diag_clk_info_t {
char clk_name[CLKNAME_SIZE];
long clk_rate;
uint8_t enable;
};
struct msm_ais_diag_clk_list_t {
void __user *clk_info;
uint32_t clk_num;
};
struct msm_ais_diag_gpio_list_t {
uint32_t __user *gpio_idx_list;
int32_t __user *gpio_val_list;
uint32_t gpio_num;
};
struct clk_mgr_cfg_data_ext { struct clk_mgr_cfg_data_ext {
enum clk_mgr_cfg_type_t cfg_type; enum ais_mgr_cfg_ext_type_t cfg_type;
union {
struct msm_ais_diag_regulator_info_list_t vreg_infolist;
struct msm_ais_diag_bus_info_t bus_info;
struct msm_ais_diag_clk_list_t clk_infolist;
struct msm_ais_diag_gpio_list_t gpio_list;
} data;
}; };
struct clk_mgr_cfg_data { struct clk_mgr_cfg_data {

View file

@ -3,7 +3,7 @@
#include <linux/v4l2-mediabus.h> #include <linux/v4l2-mediabus.h>
#include <media/ais/msm_ais_sensor_sdk.h> #include <media/ais/msm_ais_sensor_sdk.h>
#include <media/ais/msm_ais_mgr.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/i2c.h> #include <linux/i2c.h>
@ -152,6 +152,8 @@ enum csid_cfg_type_t {
CSID_START, CSID_START,
CSID_STOP, CSID_STOP,
CSID_RELEASE, CSID_RELEASE,
CSID_READ_REG_LIST_CMD,
CSID_WRITE_REG_LIST_CMD,
}; };
enum csiphy_cfg_type_t { enum csiphy_cfg_type_t {
@ -160,6 +162,8 @@ enum csiphy_cfg_type_t {
CSIPHY_START, CSIPHY_START,
CSIPHY_STOP, CSIPHY_STOP,
CSIPHY_RELEASE, CSIPHY_RELEASE,
CSIPHY_READ_REG_LIST_CMD,
CSIPHY_WRITE_REG_LIST_CMD,
}; };
enum camera_vreg_type { enum camera_vreg_type {
@ -291,6 +295,7 @@ struct csid_cfg_data {
struct msm_camera_csid_params *csid_params; struct msm_camera_csid_params *csid_params;
struct msm_camera_csid_testmode_parms *csid_testmode_params; struct msm_camera_csid_testmode_parms *csid_testmode_params;
uint32_t csid_cidmask; uint32_t csid_cidmask;
struct msm_camera_reg_list_cmd *csid_reg_list_cmd;
} cfg; } cfg;
}; };
@ -299,6 +304,7 @@ struct csiphy_cfg_data {
union { union {
struct msm_camera_csiphy_params *csiphy_params; struct msm_camera_csiphy_params *csiphy_params;
struct msm_camera_csi_lane_params *csi_lane_params; struct msm_camera_csi_lane_params *csi_lane_params;
struct msm_camera_reg_list_cmd *csiphy_reg_list_cmd;
} cfg; } cfg;
}; };
@ -613,6 +619,8 @@ struct sensor_init_cfg_data {
} cfg; } cfg;
}; };
#define CSI_RW_REG_LIST_SUPPORT
#define VIDIOC_MSM_SENSOR_CFG \ #define VIDIOC_MSM_SENSOR_CFG \
_IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct sensorb_cfg_data) _IOWR('V', BASE_VIDIOC_PRIVATE + 1, struct sensorb_cfg_data)