1
0

Merge "msm: camera: csiphy: Expand CSIPHY Onthego support" into camera-kernel.lnx.7.0

Este cometimento está contido em:
Camera Software Integration
2024-04-01 01:58:29 -07:00
cometido por Gerrit - the friendly Code Review server
ascendente 2b214147d4 7942cd08b8
cometimento 7faeb4a453

Ver ficheiro

@@ -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 +