Merge "msm: camera: csiphy: Expand CSIPHY Onthego support" into camera-kernel.lnx.7.0
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
7faeb4a453
@@ -33,13 +33,12 @@
|
||||
*/
|
||||
#define CAM_MAX_PHYS_PER_CP_CTRL_REG 4
|
||||
|
||||
static DEFINE_MUTEX(active_csiphy_cnt_mutex);
|
||||
static DEFINE_MUTEX(main_aon_selection);
|
||||
/*
|
||||
* PHY ON-The-Go Buffer Size
|
||||
*/
|
||||
#define CSIPHY_ONTHEGO_BUFSIZE 30
|
||||
|
||||
|
||||
static int csiphy_onthego_reg_count;
|
||||
static unsigned int csiphy_onthego_regs[150];
|
||||
module_param_array(csiphy_onthego_regs, uint, &csiphy_onthego_reg_count, 0644);
|
||||
MODULE_PARM_DESC(csiphy_onthego_regs, "Functionality to let csiphy registers program on the fly");
|
||||
|
||||
struct g_csiphy_data {
|
||||
void __iomem *base_address;
|
||||
@@ -51,8 +50,125 @@ struct g_csiphy_data {
|
||||
struct cam_csiphy_aon_sel_params_t *aon_sel_param;
|
||||
};
|
||||
|
||||
static DEFINE_MUTEX(active_csiphy_cnt_mutex);
|
||||
static DEFINE_MUTEX(main_aon_selection);
|
||||
static struct g_csiphy_data g_phy_data[MAX_CSIPHY] = {0};
|
||||
static int active_csiphy_hw_cnt;
|
||||
static char csiphy_onthego_regs[20];
|
||||
static int csiphy_onthego_reg_count[MAX_CSIPHY];
|
||||
static unsigned int csiphy_onthego_regvals[MAX_CSIPHY][CSIPHY_ONTHEGO_BUFSIZE];
|
||||
|
||||
|
||||
typedef int (*csiphy_onthego_func)(int *inp, int n_inp, int phy_idx, char *outp);
|
||||
static int csiphy_onthego_get_set(int *inp, int n_inp, int phy_idx, char *outp);
|
||||
|
||||
static int csiphy_set_onthego_values(const char *val, const struct kernel_param *kp)
|
||||
{
|
||||
/**
|
||||
* Expected format string: ":n1,n2,..:val1,val2,...""
|
||||
* Values between the colons, specify the PHY(s) with
|
||||
* which these settings apply to
|
||||
* The actual onthego values should have comma-delimited
|
||||
* entries with total a multiple of 3 (reg_addr, val, delay)
|
||||
*/
|
||||
csiphy_onthego_func fn = (csiphy_onthego_func) kp->arg;
|
||||
int i, idx, onthego_val, onthego_idx = 0;
|
||||
int onthego_values[CSIPHY_ONTHEGO_BUFSIZE] = {0};
|
||||
char *p1, *p2, *token;
|
||||
bool phy_target[MAX_CSIPHY] = {false};
|
||||
|
||||
p1 = strnchr(val, 1, ':'); p2 = strrchr(val, ':');
|
||||
if (!p1 || !p2 || p2 - p1 < 2) {
|
||||
CAM_ERR(CAM_CSIPHY, "Invalid csiphy onthego input string: %s", val);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
strscpy(csiphy_onthego_regs, p1, 20);
|
||||
while ((token = strsep(&p1, ":")) != NULL) {
|
||||
if (!kstrtoint(token, 0, &idx) && idx >= 0 && idx < MAX_CSIPHY)
|
||||
phy_target[idx] = true;
|
||||
}
|
||||
|
||||
p1 = p2 + 1;
|
||||
|
||||
if (!strncasecmp(p1, "X", 1)) {
|
||||
for (i = 0; i < MAX_CSIPHY; i++) {
|
||||
if (phy_target[i])
|
||||
csiphy_onthego_reg_count[i] = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((token = strsep(&p1, ",")) != NULL) {
|
||||
if (!kstrtoint(token, 0, &onthego_val))
|
||||
onthego_values[onthego_idx++] = onthego_val;
|
||||
}
|
||||
|
||||
if (!onthego_idx || (onthego_idx % 3)) {
|
||||
CAM_ERR(CAM_CSIPHY, "Invalid multiple of onthego entries: %d,", onthego_idx);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_CSIPHY && onthego_idx; i++) {
|
||||
if (phy_target[i])
|
||||
fn(onthego_values, onthego_idx, i, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int csiphy_get_onthego_values(char *buffer, const struct kernel_param *kp)
|
||||
{
|
||||
csiphy_onthego_func fn = (csiphy_onthego_func) kp->arg;
|
||||
int rc = 0, i;
|
||||
char *p = buffer;
|
||||
|
||||
for (i = 0; i < MAX_CSIPHY; i++)
|
||||
rc += fn(NULL, 0, i, p + rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct kernel_param_ops csiphy_onthego_ops = {
|
||||
.set = csiphy_set_onthego_values,
|
||||
.get = csiphy_get_onthego_values,
|
||||
};
|
||||
|
||||
module_param_cb(csiphy_onthego_regs, &csiphy_onthego_ops, csiphy_onthego_get_set, 0644);
|
||||
MODULE_PARM_DESC(csiphy_onthego_regs, "Functionality to let csiphy registers program on the fly");
|
||||
|
||||
static int csiphy_onthego_get_set(int *inp, int n_inp, int phy_idx, char *outp)
|
||||
{
|
||||
int i, idx, rc = 0;
|
||||
char *p;
|
||||
|
||||
idx = csiphy_onthego_reg_count[phy_idx];
|
||||
|
||||
if (inp && n_inp) {
|
||||
for (i = 0; i < n_inp; i++) {
|
||||
csiphy_onthego_regvals[phy_idx][idx] = (unsigned int) inp[i];
|
||||
if (++idx == CSIPHY_ONTHEGO_BUFSIZE) {
|
||||
CAM_WARN(CAM_CSIPHY,
|
||||
"Onthego input for PHY %d reached end of circular buffer, circling back",
|
||||
phy_idx);
|
||||
idx = idx % CSIPHY_ONTHEGO_BUFSIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
csiphy_onthego_reg_count[phy_idx] = idx;
|
||||
|
||||
if (outp) {
|
||||
p = outp;
|
||||
rc += scnprintf(p, PAGE_SIZE, "PHY idx %d: ", phy_idx);
|
||||
for (i = 0; i < idx; i++)
|
||||
rc += scnprintf(p + rc, PAGE_SIZE - rc, "0x%x,",
|
||||
csiphy_onthego_regvals[phy_idx][i]);
|
||||
rc += scnprintf(p + rc, PAGE_SIZE - rc, "\n");
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void cam_csiphy_update_auxiliary_mask(struct csiphy_device *csiphy_dev)
|
||||
{
|
||||
@@ -172,23 +288,23 @@ static inline void cam_csiphy_apply_onthego_reg_values(void __iomem *csiphybase,
|
||||
|
||||
CAM_DBG(CAM_CSIPHY, "csiphy: %d, onthego_reg_count: %d",
|
||||
csiphy_idx,
|
||||
csiphy_onthego_reg_count);
|
||||
csiphy_onthego_reg_count[csiphy_idx]);
|
||||
|
||||
if (csiphy_onthego_reg_count % 3)
|
||||
csiphy_onthego_reg_count -= (csiphy_onthego_reg_count % 3);
|
||||
for (i = 0; i < csiphy_onthego_reg_count[csiphy_idx]; i += 3) {
|
||||
cam_io_w_mb(csiphy_onthego_regvals[csiphy_idx][i+1],
|
||||
csiphybase + csiphy_onthego_regvals[csiphy_idx][i]);
|
||||
|
||||
for (i = 0; i < csiphy_onthego_reg_count; i += 3) {
|
||||
cam_io_w_mb(csiphy_onthego_regs[i+1],
|
||||
csiphybase + csiphy_onthego_regs[i]);
|
||||
|
||||
if (csiphy_onthego_regs[i+2])
|
||||
usleep_range(csiphy_onthego_regs[i+2], csiphy_onthego_regs[i+2] + 5);
|
||||
if (csiphy_onthego_regvals[csiphy_idx][i+2])
|
||||
usleep_range(csiphy_onthego_regvals[csiphy_idx][i+2],
|
||||
csiphy_onthego_regvals[csiphy_idx][i+2] + 5);
|
||||
|
||||
CAM_INFO(CAM_CSIPHY, "Offset: 0x%x, Val: 0x%x Delay(us): %u",
|
||||
csiphy_onthego_regs[i],
|
||||
cam_io_r_mb(csiphybase + csiphy_onthego_regs[i]),
|
||||
csiphy_onthego_regs[i+2]);
|
||||
csiphy_onthego_regvals[csiphy_idx][i],
|
||||
cam_io_r_mb(csiphybase + csiphy_onthego_regvals[csiphy_idx][i]),
|
||||
csiphy_onthego_regvals[csiphy_idx][i+2]);
|
||||
}
|
||||
|
||||
csiphy_onthego_reg_count[csiphy_idx] = 0;
|
||||
}
|
||||
|
||||
static inline int cam_csiphy_release_from_reset_state(struct csiphy_device *csiphy_dev,
|
||||
@@ -2100,6 +2216,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
csiphy_reg = csiphy_dev->ctrl_reg->csiphy_reg;
|
||||
status_reg_ptr = csiphy_reg->status_reg_params;
|
||||
|
||||
if (!status_reg_ptr) {
|
||||
CAM_ERR(CAM_CSIPHY, "CSIPHY %d status reg is NULL: %s",
|
||||
soc_info->index, CAM_IS_NULL_TO_STR(status_reg_ptr));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_CSIPHY, "Opcode received: %d", cmd->op_code);
|
||||
mutex_lock(&csiphy_dev->mutex);
|
||||
switch (cmd->op_code) {
|
||||
@@ -2715,12 +2837,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
|
||||
goto hw_cnt_decrement;
|
||||
}
|
||||
|
||||
if (csiphy_onthego_reg_count)
|
||||
if (csiphy_onthego_reg_count[soc_info->index])
|
||||
cam_csiphy_apply_onthego_reg_values(csiphybase, soc_info->index);
|
||||
|
||||
cam_csiphy_release_from_reset_state(csiphy_dev, csiphybase, offset);
|
||||
|
||||
if (g_phy_data[soc_info->index].is_3phase && status_reg_ptr) {
|
||||
if (g_phy_data[soc_info->index].is_3phase) {
|
||||
for (i = 0; i < CAM_CSIPHY_MAX_CPHY_LANES; i++) {
|
||||
if (status_reg_ptr->cphy_lane_status[i]) {
|
||||
cphy_trio_status = cam_io_r_mb(csiphybase +
|
||||
|
Reference in New Issue
Block a user