diff options
-rw-r--r-- | arch/arm/mach-mx6/board-mx6q_phyflex.c | 13 | ||||
-rw-r--r-- | drivers/media/video/mxc_camera.c | 2 | ||||
-rw-r--r-- | drivers/media/video/soc_camera.c | 24 | ||||
-rw-r--r-- | drivers/media/video/tw9910.c | 58 | ||||
-rw-r--r-- | include/media/soc_camera.h | 2 |
5 files changed, 86 insertions, 13 deletions
diff --git a/arch/arm/mach-mx6/board-mx6q_phyflex.c b/arch/arm/mach-mx6/board-mx6q_phyflex.c index 4c3e434547e9..fc41f71b727c 100644 --- a/arch/arm/mach-mx6/board-mx6q_phyflex.c +++ b/arch/arm/mach-mx6/board-mx6q_phyflex.c @@ -57,6 +57,7 @@ #include <linux/spi/max7301.h> #include <linux/can/platform/mcp251x.h> #include <sound/tlv320aic3x.h> +#include <media/tw9910.h> #include <linux/i2c-gpio.h> #include <linux/w1-gpio.h> @@ -1037,11 +1038,18 @@ static struct i2c_board_info phyflex_cameras[] = { [4] = { I2C_BOARD_INFO("mt9v022", 0x48), /* CTRL1 = 1 */ }, + [5] = { + I2C_BOARD_INFO("tw9910", 0x45), /* CTRL1 = 1 */ + }, }; #define SOC_CAM_LINK(bus, bi, i2c_adapter) \ .bus_id = bus, .board_info = bi, .i2c_adapter_id = i2c_adapter +struct tw9910_video_info tw9910_info = { + .buswidth = SOCAM_DATAWIDTH_8, + .mpout = TW9910_MPO_RTCO, +}; static struct soc_camera_link phyflex_iclinks[] = { { @@ -1049,6 +1057,9 @@ static struct soc_camera_link phyflex_iclinks[] = { }, { SOC_CAM_LINK(0, &phyflex_cameras[2], 2) }, { + SOC_CAM_LINK(1, &phyflex_cameras[5], 2), + .priv = &tw9910_info, + }, { SOC_CAM_LINK(1, &phyflex_cameras[1], 2) }, { SOC_CAM_LINK(1, &phyflex_cameras[3], 2) @@ -1071,6 +1082,8 @@ static struct platform_device mxc_ipu_cameras[] = { SOC_CAM_PDRV(3, phyflex_iclinks), }, { SOC_CAM_PDRV(4, phyflex_iclinks), + }, { + SOC_CAM_PDRV(5, phyflex_iclinks), }, }; diff --git a/drivers/media/video/mxc_camera.c b/drivers/media/video/mxc_camera.c index ff8e3a9a468c..3b323f2a743c 100644 --- a/drivers/media/video/mxc_camera.c +++ b/drivers/media/video/mxc_camera.c @@ -660,6 +660,8 @@ static int mxc_camera_try_fmt(struct soc_camera_device *icd, break; case V4L2_FIELD_NONE: break; + case V4L2_FIELD_INTERLACED_BT: + break; default: dev_err(icd->dev.parent, "Field type %d unsupported.\n", mf.field); diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 4e4d4122d9a6..3d10c126357a 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c @@ -202,11 +202,10 @@ static int soc_camera_enum_input(struct file *file, void *priv, struct soc_camera_device *icd = file->private_data; int ret = 0; - if (inp->index != 0) - return -EINVAL; - if (icd->ops->enum_input) ret = icd->ops->enum_input(icd, inp); + else if (inp->index != 0) + return -EINVAL; else { /* default is camera */ inp->type = V4L2_INPUT_TYPE_CAMERA; @@ -219,17 +218,28 @@ static int soc_camera_enum_input(struct file *file, void *priv, static int soc_camera_g_input(struct file *file, void *priv, unsigned int *i) { - *i = 0; + struct soc_camera_device *icd = file->private_data; + int ret = 0; - return 0; + if (icd->ops->g_input) + ret = icd->ops->g_input(icd, i); + else + *i = 0; + + return ret; } static int soc_camera_s_input(struct file *file, void *priv, unsigned int i) { - if (i > 0) + struct soc_camera_device *icd = file->private_data; + int ret = 0; + + if (icd->ops->s_input) + ret = icd->ops->s_input(icd, i); + else if (i > 0) return -EINVAL; - return 0; + return ret; } static int soc_camera_s_std(struct file *file, void *priv, v4l2_std_id *a) diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 0347bbe36459..9108de02881b 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -555,9 +555,27 @@ static int tw9910_s_std(struct v4l2_subdev *sd, v4l2_std_id norm) static int tw9910_enum_input(struct soc_camera_device *icd, struct v4l2_input *inp) { - inp->type = V4L2_INPUT_TYPE_TUNER; - inp->std = V4L2_STD_UNKNOWN; - strcpy(inp->name, "Video"); + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + + switch (inp->index) { + case 0: + strcpy(inp->name, "Video Input 1"); + break; + case 1: + strcpy(inp->name, "Video Input 2"); + break; + case 2: + strcpy(inp->name, "Video Input 3"); + break; + case 3: + strcpy(inp->name, "Video Input 4"); + break; + default: + return -EINVAL; + } + + inp->type = V4L2_INPUT_TYPE_CAMERA; + inp->std = V4L2_STD_625_50 | V4L2_STD_525_60; return 0; } @@ -817,11 +835,15 @@ static int tw9910_try_fmt(struct v4l2_subdev *sd, struct soc_camera_device *icd = client->dev.platform_data; const struct tw9910_scale_ctrl *scale; - if (V4L2_FIELD_ANY == mf->field) { + switch (mf->field) { + case V4L2_FIELD_ANY: + case V4L2_FIELD_INTERLACED: mf->field = V4L2_FIELD_INTERLACED_BT; - } else if (V4L2_FIELD_INTERLACED_BT != mf->field) { + break; + case V4L2_FIELD_INTERLACED_BT: + break; + default: dev_err(&client->dev, "Field type %d invalid.\n", mf->field); - return -EINVAL; } mf->code = V4L2_MBUS_FMT_UYVY8_2X8; @@ -888,10 +910,34 @@ static int tw9910_video_probe(struct soc_camera_device *icd, return 0; } +static int tw9910_g_input(struct soc_camera_device *icd, unsigned int *i) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + + *i = (i2c_smbus_read_byte_data(client, INFORM) & 0x0C) >> 2; + + if (*i < 0) + return -EINVAL; + + return 0; +} + +static int tw9910_s_input(struct soc_camera_device *icd, unsigned int i) +{ + struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); + + if (tw9910_mask_set(client, INFORM, 0X0C, i << 2)) + return -EINVAL; + + return 0; +} + static struct soc_camera_ops tw9910_ops = { .set_bus_param = tw9910_set_bus_param, .query_bus_param = tw9910_query_bus_param, .enum_input = tw9910_enum_input, + .g_input = tw9910_g_input, + .s_input = tw9910_s_input, }; static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = { diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index 68520c6611eb..cdc8022d2169 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h @@ -212,6 +212,8 @@ struct soc_camera_ops { unsigned long (*query_bus_param)(struct soc_camera_device *); int (*set_bus_param)(struct soc_camera_device *, unsigned long); int (*enum_input)(struct soc_camera_device *, struct v4l2_input *); + int (*g_input)(struct soc_camera_device *, unsigned int *); + int (*s_input)(struct soc_camera_device *, unsigned int); const struct v4l2_queryctrl *controls; int num_controls; }; |