summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/adv7180.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/drivers/media/video/adv7180.c b/drivers/media/video/adv7180.c
index eac432982a5a..4721aedf9140 100644
--- a/drivers/media/video/adv7180.c
+++ b/drivers/media/video/adv7180.c
@@ -49,6 +49,12 @@
#define ADV7180_INPUT_CONTROL_PAL_COMB_N_PED 0xd0
#define ADV7180_INPUT_CONTROL_PAL_SECAM 0xe0
#define ADV7180_INPUT_CONTROL_PAL_SECAM_PED 0xf0
+#define ADV7180_INPUT_CONTROL_COMPOSITE_IN1 0x00
+#define ADV7180_INPUT_CONTROL_COMPOSITE_IN2 0x01
+#define ADV7180_INPUT_CONTROL_COMPOSITE_IN3 0x02
+#define ADV7180_INPUT_CONTROL_COMPOSITE_IN4 0x03
+#define ADV7180_INPUT_CONTROL_COMPOSITE_IN5 0x04
+#define ADV7180_INPUT_CONTROL_COMPOSITE_IN6 0x05
#define ADV7180_EXTENDED_OUTPUT_CONTROL_REG 0x04
#define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS 0xC5
@@ -97,6 +103,7 @@ struct adv7180_state {
struct work_struct work;
struct mutex mutex; /* mutual excl. when accessing chip */
int irq;
+ int active_input;
v4l2_std_id curr_norm;
bool autodetect;
};
@@ -226,14 +233,14 @@ static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
if (std == V4L2_STD_ALL) {
ret = i2c_smbus_write_byte_data(client,
ADV7180_INPUT_CONTROL_REG,
- ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
+ ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM | state->active_input);
if (ret < 0)
goto out;
__adv7180_status(client, NULL, &state->curr_norm);
state->autodetect = true;
} else {
- ret = v4l2_std_to_adv7180(std);
+ ret = v4l2_std_to_adv7180(std) | state->active_input;
if (ret < 0)
goto out;
@@ -379,6 +386,25 @@ static irqreturn_t adv7180_irq(int irq, void *devid)
return IRQ_HANDLED;
}
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i) {
+ struct soc_camera_device *icd = file->private_data;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ struct adv7180_state *state = to_state(sd);
+ if (i < 6) {
+ state->active_input = ADV7180_INPUT_CONTROL_COMPOSITE_IN1 + i;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) {
+ struct soc_camera_device *icd = file->private_data;
+ struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+ struct adv7180_state *state = to_state(sd);
+ *i = state->active_input;
+ return 0;
+}
+
/*
* Generic i2c probe
* concerning the addresses: i2c wants 7 bit (without the r/w bit), so '>>1'
@@ -392,6 +418,7 @@ static __devinit int adv7180_probe(struct i2c_client *client,
struct v4l2_subdev *sd;
u8 ident;
int ret;
+ struct v4l2_ioctl_ops *ops;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -410,6 +437,7 @@ static __devinit int adv7180_probe(struct i2c_client *client,
WARN_ON((ident != ADV7180_ID_7180) && (ident != ADV7180_ID2_7180));
v4l_info(client, "ident reg is 0x%02x\n", ident);
+ state->active_input = ADV7180_INPUT_CONTROL_COMPOSITE_IN1;
state->irq = client->irq;
INIT_WORK(&state->work, adv7180_work);
mutex_init(&state->mutex);
@@ -421,7 +449,7 @@ static __devinit int adv7180_probe(struct i2c_client *client,
/* Initialize adv7180 */
/* Enable autodetection */
ret = i2c_smbus_write_byte_data(client, ADV7180_INPUT_CONTROL_REG,
- ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM);
+ ADV7180_INPUT_CONTROL_AD_PAL_BG_NTSC_J_SECAM | state->active_input);
if (ret < 0)
goto err_unreg_subdev;
@@ -482,6 +510,15 @@ static __devinit int adv7180_probe(struct i2c_client *client,
goto err_unreg_subdev;
}
+ /*
+ * this is the only way to support more than one input as soc_camera
+ * assumes in its own vidioc_s(g)_input implementation that only one input
+ * is present we have to override that with our own handlers.
+ */
+ ops = (struct v4l2_ioctl_ops*)icd->vdev->ioctl_ops;
+ ops->vidioc_s_input = &vidioc_s_input;
+ ops->vidioc_g_input = &vidioc_g_input;
+
return 0;
err_unreg_subdev: