summaryrefslogtreecommitdiff
path: root/drivers/media/i2c/adv7481.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/i2c/adv7481.c')
-rw-r--r--drivers/media/i2c/adv7481.c266
1 files changed, 221 insertions, 45 deletions
diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c
index 7cac0a8abd81..e51fd653d8c9 100644
--- a/drivers/media/i2c/adv7481.c
+++ b/drivers/media/i2c/adv7481.c
@@ -41,25 +41,32 @@
#include "msm_camera_i2c.h"
#include "msm_camera_io_util.h"
#include "msm_camera_dt_util.h"
+#include "linux/hdmi.h"
#define DRIVER_NAME "adv7481"
-#define I2C_RW_DELAY 1
-#define I2C_SW_RST_DELAY 5000
+#define I2C_RW_DELAY 1
+#define I2C_SW_RST_DELAY 5000
#define GPIO_HW_RST_DELAY_HI 10000
#define GPIO_HW_RST_DELAY_LOW 10000
#define SDP_MIN_SLEEP 5000
#define SDP_MAX_SLEEP 6000
-#define SDP_NUM_TRIES 30
+#define SDP_NUM_TRIES 50
#define LOCK_MIN_SLEEP 5000
#define LOCK_MAX_SLEEP 6000
#define LOCK_NUM_TRIES 200
+#define MAX_DEFAULT_WIDTH 1280
+#define MAX_DEFAULT_HEIGHT 720
#define MAX_DEFAULT_FRAME_RATE 60
#define MAX_DEFAULT_PIX_CLK_HZ 74240000
-#define ONE_MHZ_TO_HZ 1000000
-#define I2C_BLOCK_WRITE_SIZE 1024
+#define ONE_MHZ_TO_HZ 1000000
+#define I2C_BLOCK_WRITE_SIZE 1024
+#define ADV_REG_STABLE_DELAY 70 /* ms*/
+
+#define AVI_INFOFRAME_SIZE 31
+#define INFOFRAME_DATA_SIZE 28
enum adv7481_gpio_t {
@@ -117,6 +124,7 @@ struct adv7481_state {
uint8_t i2c_csi_txa_addr;
uint8_t i2c_csi_txb_addr;
uint8_t i2c_hdmi_addr;
+ uint8_t i2c_hdmi_inf_addr;
uint8_t i2c_edid_addr;
uint8_t i2c_cp_addr;
uint8_t i2c_sdp_addr;
@@ -138,6 +146,9 @@ struct adv7481_state {
int csib_src;
int mode;
+ /* AVI Infoframe Params */
+ struct avi_infoframe_params hdmi_avi_infoframe;
+
/* resolution configuration */
struct resolution_config res_configs[RES_MAX];
@@ -182,19 +193,20 @@ const uint8_t adv7481_default_edid_data[] = {
/* Display Parameters */
0x80, 0x10, 0x09, 0x78, 0x0A,
/* Color characteristics */
-0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27, 0x12, 0x48, 0x4C,
+0x0D, 0xC9, 0xA0, 0x57, 0x47, 0x98, 0x27, 0x12,
+0x48, 0x4C,
/* Established Timings */
0x21, 0x08, 0x00,
/* Standard Timings */
-0x81, 0xC0, 0x81, 0x40, 0x3B, 0xC0, 0x3B, 0x40,
-0x31, 0xC0, 0x31, 0x40, 0x01, 0x01, 0x01, 0x01,
+0xD1, 0xC0, 0xD1, 0x40, 0x81, 0xC0, 0x81, 0x40,
+0x3B, 0xC0, 0x3B, 0x40, 0x31, 0xC0, 0x31, 0x40,
/* Detailed Timings Block */
-0x01, 0x1D, 0x00, 0xBC, 0x52, 0xD0, 0x1E, 0x20,
-0xB8, 0x28, 0x55, 0x40, 0xA0, 0x5A, 0x00, 0x00,
+0x1A, 0x36, 0x80, 0xA0, 0x70, 0x38, 0x1F, 0x40,
+0x30, 0x20, 0x35, 0x00, 0x40, 0x44, 0x21, 0x00,
0x00, 0x1E,
/* Monitor Descriptor Block 2 */
-0x8C, 0x0A, 0xD0, 0xB4, 0x20, 0xE0, 0x14, 0x10,
-0x12, 0x48, 0x3A, 0x00, 0xD8, 0xA2, 0x00, 0x00,
+0x00, 0x19, 0x00, 0xA0, 0x50, 0xD0, 0x15, 0x20,
+0x30, 0x20, 0x35, 0x00, 0x80, 0xD8, 0x10, 0x00,
0x00, 0x1E,
/* Monitor Descriptor Block 3 */
0x00, 0x00, 0x00, 0xFD, 0x00, 0x17, 0x4B, 0x0F,
@@ -207,16 +219,16 @@ const uint8_t adv7481_default_edid_data[] = {
/* Extension Flag CEA */
0x01,
/* Checksum */
-0x5B,
+0x16,
/* Block 1 (Extension Block) */
/* Extension Header */
-0x02, 0x03, 0x1E,
+0x02, 0x03, 0x22,
/* Display supports */
0x71,
-/* Video Data Bock */
-0x48, 0x84, 0x13, 0x3C, 0x03, 0x02, 0x11, 0x12,
-0x01,
+/* Video Data Block */
+0x4C, 0x84, 0x13, 0x3C, 0x03, 0x02, 0x11, 0x12,
+0x01, 0x90, 0x1F, 0x20, 0x22,
/* HDMI VSDB */
/* Deep color All, Max_TMDS_Clock = 150 MHz */
0x68, 0x03, 0x0C, 0x00, 0x10, 0x00, 0x80,
@@ -228,17 +240,17 @@ const uint8_t adv7481_default_edid_data[] = {
/* Speaker Allocation Data Block */
0x83, 0x01, 0x00, 0x00,
/* Detailed Timing Descriptor */
-0x01, 0x1D, 0x00, 0x72, 0x51, 0xD0, 0x1E, 0x20,
-0x6E, 0x28, 0x55, 0x00, 0xA0, 0x2A, 0x53, 0x00,
+0x1A, 0x36, 0x80, 0xA0, 0x70, 0x38, 0x1F, 0x40,
+0x30, 0x20, 0x35, 0x00, 0x40, 0x44, 0x21, 0x00,
0x00, 0x1E,
/* Detailed Timing Descriptor */
-0x8C, 0x0A, 0xD0, 0xB4, 0x20, 0xE0, 0x14, 0x10,
-0x12, 0x48, 0x3A, 0x00, 0xD8, 0xA2, 0x00, 0x00,
+0x00, 0x19, 0x00, 0xA0, 0x50, 0xD0, 0x15, 0x20,
+0x30, 0x20, 0x35, 0x00, 0x80, 0xD8, 0x10, 0x00,
0x00, 0x1E,
/* Detailed Timing Descriptor */
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-0x00, 0x00,
+0x41, 0x0A, 0xD0, 0xA0, 0x20, 0xE0, 0x13, 0x10,
+0x30, 0x20, 0x3A, 0x00, 0xD8, 0x90, 0x00, 0x00,
+0x00, 0x18,
/* Detailed Timing Descriptor */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -248,9 +260,9 @@ const uint8_t adv7481_default_edid_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* DTD padding */
-0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00,
/* Checksum */
-0xC6
+0x8C
};
#define ADV7481_EDID_SIZE ARRAY_SIZE(adv7481_default_edid_data)
@@ -301,6 +313,14 @@ static int32_t adv7481_cci_i2c_read(struct msm_camera_i2c_client *i2c_client,
data, data_type);
}
+static int32_t adv7481_cci_i2c_read_seq(
+ struct msm_camera_i2c_client *i2c_client,
+ uint8_t reg, uint8_t *data, uint32_t size)
+{
+ return i2c_client->i2c_func_tbl->i2c_read_seq(i2c_client, reg,
+ data, size);
+}
+
static int32_t adv7481_wr_byte(struct msm_camera_i2c_client *c_i2c_client,
uint8_t sid, uint8_t reg, uint8_t data)
{
@@ -331,6 +351,20 @@ static int32_t adv7481_wr_block(struct msm_camera_i2c_client *c_i2c_client,
return ret;
}
+static int32_t adv7481_rd_block(struct msm_camera_i2c_client *c_i2c_client,
+ uint8_t sid, uint8_t reg, uint8_t *data, uint32_t size)
+{
+ int ret = 0;
+
+ c_i2c_client->cci_client->sid = sid;
+
+ ret = adv7481_cci_i2c_read_seq(c_i2c_client, reg, data, size);
+ if (ret < 0)
+ pr_err("Error %d reading cci i2c block data\n", ret);
+
+ return ret;
+}
+
static uint8_t adv7481_rd_byte(struct msm_camera_i2c_client *c_i2c_client,
uint8_t sid, uint8_t reg)
{
@@ -389,6 +423,7 @@ static int adv7481_set_irq(struct adv7481_state *state)
ADV_REG_SETFIELD(1, IO_CP_UNLOCK_CP_MB1) |
ADV_REG_SETFIELD(1, IO_VMUTE_REQUEST_HDMI_MB1) |
ADV_REG_SETFIELD(1, IO_INT_SD_MB1));
+
/* Set cable detect */
ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
IO_HDMI_LVL_INT_MASKB_3_ADDR,
@@ -476,7 +511,7 @@ static irqreturn_t adv7481_irq(int irq, void *dev)
struct adv7481_state *state = dev;
schedule_delayed_work(&state->irq_delayed_work,
- msecs_to_jiffies(0));
+ msecs_to_jiffies(ADV_REG_STABLE_DELAY));
return IRQ_HANDLED;
}
@@ -578,7 +613,8 @@ static void adv7481_irq_delay_work(struct work_struct *work)
pr_debug("%s: dev: %d got datapath raw status: 0x%x\n",
__func__, state->device_num, raw_status);
- if (ADV_REG_GETFIELD(int_status, IO_INT_SD_ST) &&
+ if ((state->mode == ADV7481_IP_CVBS_1) &&
+ ADV_REG_GETFIELD(int_status, IO_INT_SD_ST) &&
ADV_REG_GETFIELD(raw_status, IO_INT_SD_RAW)) {
uint8_t sdp_sts = 0;
@@ -614,7 +650,7 @@ static void adv7481_irq_delay_work(struct work_struct *work)
adv7481_wr_byte(&state->i2c_client,
state->i2c_sdp_addr, SDP_RW_MAP_REG,
0x00);
- } else {
+ } else if (state->mode == ADV7481_IP_HDMI) {
if (ADV_REG_GETFIELD(int_status,
IO_CP_LOCK_CP_ST) &&
ADV_REG_GETFIELD(raw_status,
@@ -741,18 +777,12 @@ static int adv7481_dev_init(struct adv7481_state *state)
mutex_lock(&state->mutex);
- /* Soft reset */
- ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
- IO_REG_MAIN_RST_ADDR, IO_REG_MAIN_RST_VALUE);
- /* Delay required following I2C reset and I2C transactions */
- udelay(I2C_SW_RST_DELAY);
-
chip_rev_id = adv7481_rd_word(&state->i2c_client, state->i2c_io_addr,
IO_REG_CHIP_REV_ID_1_ADDR);
pr_debug("%s: ADV7481 chip rev id: 0x%x", __func__, chip_rev_id);
/* Disable CEC wake up in power-down mode */
- ret |= adv7481_cec_wakeup(state, 0);
+ ret = adv7481_cec_wakeup(state, 0);
/* Setting Vid_Std to 720x480p60 */
ret |= adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
IO_REG_CP_VID_STD_ADDR, 0x4A);
@@ -804,6 +834,7 @@ static int adv7481_dev_init(struct adv7481_state *state)
state->i2c_csi_txb_addr = IO_REG_CSI_TXB_SADDR >> 1;
state->i2c_cp_addr = IO_REG_CP_SADDR >> 1;
state->i2c_hdmi_addr = IO_REG_HDMI_SADDR >> 1;
+ state->i2c_hdmi_inf_addr = IO_REG_HDMI_INF_SADDR >> 1;
state->i2c_edid_addr = IO_REG_EDID_SADDR >> 1;
state->i2c_sdp_addr = IO_REG_SDP_SADDR >> 1;
state->i2c_rep_addr = IO_REG_HDMI_REP_SADDR >> 1;
@@ -1038,10 +1069,16 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
struct adv7481_vid_params vid_params;
struct adv7481_hdmi_params hdmi_params;
+ struct device *dev = state->dev;
+ union hdmi_infoframe hdmi_info_frame;
+ uint8_t inf_buffer[AVI_INFOFRAME_SIZE];
+
pr_debug("Enter %s with command: 0x%x", __func__, cmd);
memset(&vid_params, 0, sizeof(struct adv7481_vid_params));
memset(&hdmi_params, 0, sizeof(struct adv7481_hdmi_params));
+ memset(&hdmi_info_frame, 0, sizeof(union hdmi_infoframe));
+ memset(inf_buffer, 0, AVI_INFOFRAME_SIZE);
if (!sd)
return -EINVAL;
@@ -1094,6 +1131,58 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
}
break;
}
+ case VIDIOC_G_AVI_INFOFRAME: {
+ int int_raw = adv7481_rd_byte(&state->i2c_client,
+ state->i2c_io_addr,
+ IO_HDMI_EDG_RAW_STATUS_1_ADDR);
+ adv7481_wr_byte(&state->i2c_client,
+ state->i2c_io_addr,
+ IO_HDMI_EDG_INT_CLEAR_1_ADDR, int_raw);
+ if (ADV_REG_GETFIELD(int_raw, IO_NEW_AVI_INFO_RAW)) {
+ inf_buffer[0] = adv7481_rd_byte(&state->i2c_client,
+ state->i2c_hdmi_inf_addr,
+ HDMI_REG_AVI_PACKET_ID_ADDR);
+ inf_buffer[1] = adv7481_rd_byte(&state->i2c_client,
+ state->i2c_hdmi_inf_addr,
+ HDMI_REG_AVI_INF_VERS_ADDR);
+ inf_buffer[2] = adv7481_rd_byte(&state->i2c_client,
+ state->i2c_hdmi_inf_addr,
+ HDMI_REG_AVI_INF_LEN_ADDR);
+ ret = adv7481_rd_block(&state->i2c_client,
+ state->i2c_hdmi_inf_addr,
+ HDMI_REG_AVI_INF_PB_ADDR,
+ &inf_buffer[3],
+ INFOFRAME_DATA_SIZE);
+ if (ret) {
+ pr_err("%s:Error in VIDIOC_G_AVI_INFOFRAME\n",
+ __func__);
+ return -EINVAL;
+ }
+ if (hdmi_infoframe_unpack(&hdmi_info_frame,
+ (void *)inf_buffer) < 0) {
+ pr_err("%s: infoframe unpack fail\n", __func__);
+ return -EINVAL;
+ }
+ hdmi_infoframe_log(KERN_ERR, dev, &hdmi_info_frame);
+ state->hdmi_avi_infoframe.picture_aspect =
+ (enum picture_aspect_ratio)
+ hdmi_info_frame.avi.picture_aspect;
+ state->hdmi_avi_infoframe.active_aspect =
+ (enum active_format_aspect_ratio)
+ hdmi_info_frame.avi.active_aspect;
+ state->hdmi_avi_infoframe.video_code =
+ hdmi_info_frame.avi.video_code;
+ } else {
+ pr_err("%s: No new AVI Infoframe\n", __func__);
+ }
+ if (copy_to_user((void __user *)adv_arg.ptr,
+ (void *)&state->hdmi_avi_infoframe,
+ sizeof(struct avi_infoframe_params))) {
+ pr_err("%s: Failed to copy Infoframe\n", __func__);
+ return -EINVAL;
+ }
+ break;
+ }
case VIDIOC_G_FIELD_INFO:
/* Select SDP read-only Map 1 */
adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr,
@@ -1124,10 +1213,12 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
return ret;
}
-static int adv7481_get_sd_timings(struct adv7481_state *state, int *sd_standard)
+static int adv7481_get_sd_timings(struct adv7481_state *state,
+ int *sd_standard, struct adv7481_vid_params *vid_params)
{
int ret = 0;
int sdp_stat, sdp_stat2;
+ int interlace_reg = 0;
int timeout = 0;
if (sd_standard == NULL)
@@ -1144,6 +1235,25 @@ 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));
+
+ interlace_reg = adv7481_rd_byte(&state->i2c_client,
+ state->i2c_sdp_addr, SDP_RO_MAIN_INTERLACE_STATE_ADDR);
+
+ if (ADV_REG_GETFIELD(interlace_reg, SDP_RO_MAIN_INTERLACE_STATE))
+ pr_debug("%s: Interlaced video detected\n", __func__);
+ else
+ pr_debug("%s: Interlaced video not detected\n", __func__);
+
+ if (ADV_REG_GETFIELD(interlace_reg, SDP_RO_MAIN_FIELD_LEN))
+ pr_debug("%s: Field length is correct\n", __func__);
+ else
+ pr_debug("%s: Field length is not correct\n", __func__);
+
+ if (ADV_REG_GETFIELD(interlace_reg, SDP_RO_MAIN_SD_FIELD_RATE))
+ pr_debug("%s: SD 50 Hz detected\n", __func__);
+ else
+ pr_debug("%s: SD 60 Hz detected\n", __func__);
+
adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr,
SDP_RW_MAP_REG, 0x00);
@@ -1157,36 +1267,58 @@ static int adv7481_get_sd_timings(struct adv7481_state *state, int *sd_standard)
__func__, __LINE__, sdp_stat);
return -EBUSY;
}
+ vid_params->act_pix = 720;
+ vid_params->intrlcd = 1;
switch (ADV_REG_GETFIELD(sdp_stat, SDP_RO_MAIN_AD_RESULT)) {
case AD_NTSM_M_J:
*sd_standard = V4L2_STD_NTSC;
+ pr_debug("%s, V4L2_STD_NTSC\n", __func__);
+ vid_params->act_lines = 507;
break;
case AD_NTSC_4_43:
*sd_standard = V4L2_STD_NTSC_443;
+ pr_debug("%s, V4L2_STD_NTSC_443\n", __func__);
+ vid_params->act_lines = 507;
break;
case AD_PAL_M:
*sd_standard = V4L2_STD_PAL_M;
+ pr_debug("%s, V4L2_STD_PAL_M\n", __func__);
+ vid_params->act_lines = 576;
break;
case AD_PAL_60:
*sd_standard = V4L2_STD_PAL_60;
+ pr_debug("%s, V4L2_STD_PAL_60\n", __func__);
+ vid_params->act_lines = 576;
break;
case AD_PAL_B_G:
*sd_standard = V4L2_STD_PAL;
+ pr_debug("%s, V4L2_STD_PAL\n", __func__);
+ vid_params->act_lines = 576;
break;
case AD_SECAM:
*sd_standard = V4L2_STD_SECAM;
+ pr_debug("%s, V4L2_STD_SECAM\n", __func__);
+ vid_params->act_lines = 576;
break;
case AD_PAL_COMB_N:
*sd_standard = V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
+ pr_debug("%s, V4L2_STD_PAL_Nc | V4L2_STD_PAL_N\n", __func__);
+ vid_params->act_lines = 576;
break;
case AD_SECAM_525:
*sd_standard = V4L2_STD_SECAM;
+ pr_debug("%s, V4L2_STD_SECAM (AD_SECAM_525)\n", __func__);
+ vid_params->act_lines = 576;
break;
default:
*sd_standard = V4L2_STD_UNKNOWN;
+ pr_debug("%s, V4L2_STD_UNKNOWN\n", __func__);
+ vid_params->act_lines = 507;
break;
}
+ pr_debug("%s(%d), adv7481 TMDS Resolution: %d x %d\n",
+ __func__, __LINE__, vid_params->act_pix, vid_params->act_lines);
return ret;
}
@@ -1710,7 +1842,8 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state,
} else {
pr_err("%s(%d): PLL not locked return EBUSY\n",
__func__, __LINE__);
- return -EBUSY;
+ ret = -EBUSY;
+ goto set_default;
}
/* Check Timing Lock */
@@ -1804,6 +1937,8 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state,
vid_params->pix_clk = hdmi_params->tmds_freq;
+ vid_params->act_lines = vid_params->act_lines * fieldfactor;
+
switch (hdmi_params->color_depth) {
case CD_10BIT:
vid_params->pix_clk = ((vid_params->pix_clk*4)/5);
@@ -1830,6 +1965,17 @@ static int adv7481_get_hdmi_timings(struct adv7481_state *state,
(hdmi_params->pix_rep + 1));
}
+set_default:
+ if (ret) {
+ pr_debug("%s(%d), error %d resort to default fmt\n",
+ __func__, __LINE__, ret);
+ vid_params->act_pix = MAX_DEFAULT_WIDTH;
+ vid_params->act_lines = MAX_DEFAULT_HEIGHT;
+ vid_params->fr_rate = MAX_DEFAULT_FRAME_RATE;
+ vid_params->pix_clk = MAX_DEFAULT_PIX_CLK_HZ;
+ vid_params->intrlcd = 0;
+ ret = 0;
+ }
pr_debug("%s(%d), adv7481 TMDS Resolution: %d x %d @ %d fps\n",
__func__, __LINE__,
@@ -1893,6 +2039,9 @@ static int adv7481_query_sd_std(struct v4l2_subdev *sd, v4l2_std_id *std)
struct adv7481_state *state = to_state(sd);
uint8_t tStatus = 0x0;
uint32_t count = 0;
+ struct adv7481_vid_params vid_params;
+
+ memset(&vid_params, 0, sizeof(vid_params));
pr_debug("Enter %s\n", __func__);
/* Select SDP read-only main Map */
@@ -1933,7 +2082,7 @@ static int adv7481_query_sd_std(struct v4l2_subdev *sd, v4l2_std_id *std)
case ADV7481_IP_CVBS_6_HDMI_SIM:
case ADV7481_IP_CVBS_7_HDMI_SIM:
case ADV7481_IP_CVBS_8_HDMI_SIM:
- ret = adv7481_get_sd_timings(state, &temp);
+ ret = adv7481_get_sd_timings(state, &temp, &vid_params);
break;
default:
return -EINVAL;
@@ -1963,6 +2112,7 @@ static int adv7481_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_format *format)
{
int ret;
+ int sd_standard;
struct adv7481_vid_params vid_params;
struct adv7481_hdmi_params hdmi_params;
struct adv7481_state *state = to_state(sd);
@@ -1987,8 +2137,9 @@ static int adv7481_get_fmt(struct v4l2_subdev *sd,
if (!ret) {
fmt->width = vid_params.act_pix;
fmt->height = vid_params.act_lines;
+ fmt->field = V4L2_FIELD_NONE;
if (vid_params.intrlcd)
- fmt->height /= 2;
+ fmt->field = V4L2_FIELD_INTERLACED;
} else {
pr_err("%s: Error %d in adv7481_get_hdmi_timings\n",
__func__, ret);
@@ -1997,8 +2148,14 @@ static int adv7481_get_fmt(struct v4l2_subdev *sd,
case ADV7481_IP_CVBS_1:
fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
- fmt->width = 720;
- fmt->height = 576;
+ ret = adv7481_get_sd_timings(state, &sd_standard, &vid_params);
+ if (!ret) {
+ fmt->width = vid_params.act_pix;
+ fmt->height = vid_params.act_lines;
+ fmt->field = V4L2_FIELD_INTERLACED;
+ } else {
+ pr_err("%s: Unable to get sd_timings\n", __func__);
+ }
break;
default:
return -EINVAL;
@@ -2316,7 +2473,12 @@ static int adv7481_init_v4l2_controls(struct adv7481_state *state)
{
int ret = 0;
- v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
+ ret = v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
+ if (ret) {
+ pr_err("%s: v4l2_ctrl_handler_init failed, ret: %d\n",
+ __func__, ret);
+ return ret;
+ }
v4l2_ctrl_new_std(&state->ctrl_hdl, &adv7481_ctrl_ops,
V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
@@ -2333,7 +2495,10 @@ static int adv7481_init_v4l2_controls(struct adv7481_state *state)
v4l2_ctrl_handler_free(&state->ctrl_hdl);
} else {
- v4l2_ctrl_handler_setup(&state->ctrl_hdl);
+ ret = v4l2_ctrl_handler_setup(&state->ctrl_hdl);
+ if (ret)
+ pr_err("%s: v4l2_ctrl_handler_init failed, ret: %d\n",
+ __func__, ret);
}
pr_err("%s: Exit with ret: %d\n", __func__, ret);
@@ -2573,11 +2738,22 @@ static int adv7481_probe(struct platform_device *pdev)
goto err_media_entity;
}
+ /* Soft reset */
+ ret = adv7481_wr_byte(&state->i2c_client, state->i2c_io_addr,
+ IO_REG_MAIN_RST_ADDR, IO_REG_MAIN_RST_VALUE);
+ if (ret) {
+ pr_err("%s: Failed Soft reset %d\n", __func__, ret);
+ goto err_media_entity;
+ }
+ /* Delay required following I2C reset and I2C transactions */
+ udelay(I2C_SW_RST_DELAY);
+
/* Register V4l2 Control Functions */
ret = adv7481_init_v4l2_controls(state);
if (ret) {
pr_err("%s: V4L2 Controls Initialisation Failed %d\n",
__func__, ret);
+ goto err_media_entity;
}
/* Initial ADV7481 State Settings */
@@ -2600,7 +2776,7 @@ static int adv7481_probe(struct platform_device *pdev)
goto err_media_entity;
}
enable_irq(state->irq);
- pr_debug("Probe successful!\n");
+ pr_info("ADV7481 Probe successful!\n");
return ret;