diff options
author | Shiju Mathew <shijum@codeaurora.org> | 2016-06-15 19:25:02 -0400 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-05-26 01:39:32 -0700 |
commit | cbfef60b3fa54533e65fe7e445abe5f991fd0b2f (patch) | |
tree | 62e82ed9c3135721f06e5f9f7a3365f834a9e94a /drivers/media/i2c | |
parent | 8ff7c3b809aa1a1624252c5418b657862501bffc (diff) |
adv7481: Add support for CVBS input on MSM8996 Auto
Enable adv7481 CVBS input on MSM8996 automotive.
CRs-Fixed: 1029211
Change-Id: I06ba481be4f5f899df248615b2458ec81a3a17df
Signed-off-by: Shiju Mathew <shijum@codeaurora.org>
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r-- | drivers/media/i2c/adv7481.c | 110 |
1 files changed, 76 insertions, 34 deletions
diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c index 447fa23e713c..1b9ed8c9e5a5 100644 --- a/drivers/media/i2c/adv7481.c +++ b/drivers/media/i2c/adv7481.c @@ -917,6 +917,8 @@ static int adv7481_get_sd_timings(struct adv7481_state *state, int *sd_standard) if (sd_standard == NULL) return -EINVAL; + /* Select SDP read-only main Map */ + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0e, 0x01); do { sdp_stat = adv7481_rd_byte(&state->i2c_client, state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); @@ -925,6 +927,7 @@ static int adv7481_get_sd_timings(struct adv7481_state *state, int *sd_standard) sdp_stat2 = adv7481_rd_byte(&state->i2c_client, state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); } while ((sdp_stat != sdp_stat2) && (timeout < SDP_NUM_TRIES)); + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0e, 0x00); if (sdp_stat != sdp_stat2) { pr_err("%s, adv7481 SDP status unstable: 1\n", __func__); @@ -979,11 +982,29 @@ static int adv7481_set_cvbs_mode(struct adv7481_state *state) /* cvbs video settings ntsc etc */ ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, 0x00, 0x30); + ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, + 0x0e, 0xff); ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0f, 0x00); ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x52, 0xcd); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x00, 0x00); ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x0e, 0x80); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x9c, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x9c, 0xff); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x0e, 0x00); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x80, 0x51); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x81, 0x51); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + 0x82, 0x68); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x03, 0x42); ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x04, 0x07); @@ -993,19 +1014,16 @@ static int adv7481_set_cvbs_mode(struct adv7481_state *state) 0x17, 0x41); ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x31, 0x12); - ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, - 0x52, 0xcd); - ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, - 0x0e, 0xff); + val = adv7481_rd_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_CSI_PIX_EN_SEL_ADDR); /* Output of SD core routed to MIPI CSI 4-lane Tx */ - val |= ADV_REG_SETFIELD(0x10, IO_CTRL_CSI4_IN_SEL); + val = ADV_REG_SETFIELD(1, IO_CTRL_CSI4_EN) | + ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | + ADV_REG_SETFIELD(0x2, IO_CTRL_CSI4_IN_SEL); + ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr, IO_REG_CSI_PIX_EN_SEL_ADDR, val); - /* Enable autodetect */ - ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, - 0x0e, 0x81); return ret; } @@ -1349,14 +1367,11 @@ static int adv7481_s_routing(struct v4l2_subdev *sd, u32 input, goto unlock_exit; } - if (state->mode != adv_input) { - ret = adv7481_set_ip_mode(state, adv_input); - if (ret) - pr_err("%s: Set input mode failed: %d\n", - __func__, ret); - else - state->mode = adv_input; - } + ret = adv7481_set_ip_mode(state, adv_input); + if (ret) + pr_err("%s: Set input mode failed: %d\n", __func__, ret); + else + state->mode = adv_input; unlock_exit: mutex_unlock(&state->mutex); @@ -1612,11 +1627,22 @@ static int adv7481_query_sd_std(struct v4l2_subdev *sd, v4l2_std_id *std) int temp = 0; struct adv7481_state *state = to_state(sd); uint8_t tStatus = 0x0; + uint32_t count = 0; pr_debug("Enter %s\n", __func__); - tStatus = adv7481_rd_byte(&state->i2c_client, state->i2c_sdp_addr, - SDP_RO_MAIN_STATUS1_ADDR); - if (!ADV_REG_GETFIELD(tStatus, SDP_RO_MAIN_IN_LOCK)) + /* Select SDP read-only main Map */ + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0e, 0x01); + do { + tStatus = adv7481_rd_byte(&state->i2c_client, + state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); + if (ADV_REG_GETFIELD(tStatus, SDP_RO_MAIN_IN_LOCK)) + break; + count++; + usleep_range(LOCK_MIN_SLEEP, LOCK_MAX_SLEEP); + } while (count < LOCK_NUM_TRIES); + + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0e, 0x00); + if (count >= LOCK_NUM_TRIES) pr_err("%s(%d), adv7481 SD Input NOT Locked: 0x%x\n", __func__, __LINE__, tStatus); @@ -1699,6 +1725,12 @@ static int adv7481_g_mbus_fmt(struct v4l2_subdev *sd, __func__, ret); } break; + case ADV7481_IP_CVBS_1: + fmt->code = V4L2_MBUS_FMT_UYVY8_2X8; + fmt->colorspace = V4L2_COLORSPACE_SMPTE170M; + fmt->width = 720; + fmt->height = 576; + break; default: return -EINVAL; } @@ -1789,9 +1821,15 @@ static int adv7481_csi_powerup(struct adv7481_state *state, pr_debug("Enter %s for output: %d\n", __func__, output); /* Select CSI TX to configure data */ if (output == ADV7481_OP_CSIA) { - csi_sel = ADV_REG_SETFIELD(1, IO_CTRL_CSI4_EN) | - ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | - ADV_REG_SETFIELD(0, IO_CTRL_CSI4_IN_SEL); + if (state->csia_src == ADV7481_IP_HDMI) { + csi_sel = ADV_REG_SETFIELD(1, IO_CTRL_CSI4_EN) | + ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | + ADV_REG_SETFIELD(0, IO_CTRL_CSI4_IN_SEL); + } else { + csi_sel = ADV_REG_SETFIELD(1, IO_CTRL_CSI4_EN) | + ADV_REG_SETFIELD(1, IO_CTRL_PIX_OUT_EN) | + ADV_REG_SETFIELD(0x2, IO_CTRL_CSI4_IN_SEL); + } csi_map = state->i2c_csi_txa_addr; } else if (output == ADV7481_OP_CSIB) { /* Enable 1-Lane MIPI Tx, enable pixel output and @@ -1926,9 +1964,21 @@ static int adv7481_g_input_status(struct v4l2_subdev *sd, u32 *status) *status |= V4L2_IN_ST_NO_SIGNAL; } } else { - val = adv7481_rd_byte(&state->i2c_client, state->i2c_sdp_addr, - SDP_RO_MAIN_STATUS1_ADDR); - if (!ADV_REG_GETFIELD(val, SDP_RO_MAIN_IN_LOCK)) { + /* Select SDP read-only main Map */ + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0e, + 0x01); + do { + val = adv7481_rd_byte(&state->i2c_client, + state->i2c_sdp_addr, SDP_RO_MAIN_STATUS1_ADDR); + if (ADV_REG_GETFIELD(val, SDP_RO_MAIN_IN_LOCK)) + break; + count++; + usleep_range(LOCK_MIN_SLEEP, LOCK_MAX_SLEEP); + } while (count < LOCK_NUM_TRIES); + + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, 0x0e, + 0x00); + if (count >= LOCK_NUM_TRIES) { pr_err("%s(%d), SD Input NOT Locked: 0x%x\n", __func__, __LINE__, val); *status |= V4L2_IN_ST_NO_SIGNAL; @@ -2036,7 +2086,7 @@ static int adv7481_cci_init(struct adv7481_state *state) cci_client->sid = state->i2c_slave_addr; cci_client->retries = 3; cci_client->id_map = 0; - cci_client->i2c_freq_mode = I2C_FAST_MODE; + cci_client->i2c_freq_mode = I2C_CUSTOM_MODE; ret = state->i2c_client.i2c_func_tbl->i2c_util( &state->i2c_client, MSM_CCI_INIT); if (ret < 0) @@ -2214,14 +2264,6 @@ static int adv7481_probe(struct platform_device *pdev) goto err_media_entity; } - /* Set hdmi settings */ - ret = adv7481_set_hdmi_mode(state); - if (ret) { - ret = -EIO; - pr_err("%s: failed to set hdmi mode\n", __func__); - goto err_media_entity; - } - /* BA registration */ ret = msm_ba_register_subdev_node(sd); if (ret) { |