diff options
author | Peter Gielda <pgielda@antmicro.com> | 2013-07-25 14:03:54 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2013-07-31 15:30:57 +0200 |
commit | 3e3245f2638d9763b7b0b8a6cc30ac4055e44731 (patch) | |
tree | e5903dab8c8474f99b4498f6284d69fd1f48b1a4 /drivers/media/video | |
parent | 435cd0744bae5b91e6fb1fb25aad19da96dbc58d (diff) |
media: adv7180: added input selection support
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/adv7180.c | 43 |
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: |