V4L/DVB (13174): adv7180: Support for setting input status
authorRichard Röjfors <richard.rojfors@mocean-labs.com>
Tue, 22 Sep 2009 09:06:34 +0000 (06:06 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 5 Dec 2009 20:40:42 +0000 (18:40 -0200)
Support for settings the input standard of the ADV7180.

When the input standard is set there is no use to ask the
chip for standard, therefore it is cached in the driver.

Signed-off-by: Richard Röjfors <richard.rojfors@mocean-labs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/adv7180.c

index f3fce398020a9ef68fe44e8c2a47332cccf9c16b..8b199a86a3a9f999cdd8bddaddc08ba08ac0711b 100644 (file)
@@ -69,7 +69,9 @@
 
 
 struct adv7180_state {
-       struct v4l2_subdev sd;
+       struct v4l2_subdev      sd;
+       v4l2_std_id             curr_norm;
+       bool                    autodetect;
 };
 
 static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
@@ -96,6 +98,29 @@ static v4l2_std_id adv7180_std_to_v4l2(u8 status1)
        }
 }
 
+static int v4l2_std_to_adv7180(v4l2_std_id std)
+{
+       if (std == V4L2_STD_PAL_60)
+               return ADV7180_INPUT_CONTROL_PAL60;
+       if (std == V4L2_STD_NTSC_443)
+               return ADV7180_INPUT_CONTROL_NTSC_443;
+       if (std == V4L2_STD_PAL_N)
+               return ADV7180_INPUT_CONTROL_PAL_N;
+       if (std == V4L2_STD_PAL_M)
+               return ADV7180_INPUT_CONTROL_PAL_M;
+       if (std == V4L2_STD_PAL_Nc)
+               return ADV7180_INPUT_CONTROL_PAL_COMB_N;
+
+       if (std & V4L2_STD_PAL)
+               return ADV7180_INPUT_CONTROL_PAL_BG;
+       if (std & V4L2_STD_NTSC)
+               return ADV7180_INPUT_CONTROL_NTSC_M;
+       if (std & V4L2_STD_SECAM)
+               return ADV7180_INPUT_CONTROL_PAL_SECAM;
+
+       return -EINVAL;
+}
+
 static u32 adv7180_status_to_v4l2(u8 status1)
 {
        if (!(status1 & ADV7180_STATUS1_IN_LOCK))
@@ -127,7 +152,15 @@ static inline struct adv7180_state *to_state(struct v4l2_subdev *sd)
 
 static int adv7180_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
 {
-       return __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);
+       struct adv7180_state *state = to_state(sd);
+       int err = 0;
+
+       if (!state->autodetect)
+               *std = state->curr_norm;
+       else
+               err = __adv7180_status(v4l2_get_subdevdata(sd), NULL, std);
+
+       return err;
 }
 
 static int adv7180_g_input_status(struct v4l2_subdev *sd, u32 *status)
@@ -143,6 +176,39 @@ static int adv7180_g_chip_ident(struct v4l2_subdev *sd,
        return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7180, 0);
 }
 
+static int adv7180_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+{
+       struct adv7180_state *state = to_state(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+
+       /* all standards -> autodetect */
+       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);
+               if (ret < 0)
+                       goto out;
+
+               state->autodetect = true;
+       } else {
+               ret = v4l2_std_to_adv7180(std);
+               if (ret < 0)
+                       goto out;
+
+               ret = i2c_smbus_write_byte_data(client,
+                       ADV7180_INPUT_CONTROL_REG, ret);
+               if (ret < 0)
+                       goto out;
+
+               state->curr_norm = std;
+               state->autodetect = false;
+       }
+       ret = 0;
+out:
+       return ret;
+}
+
 static const struct v4l2_subdev_video_ops adv7180_video_ops = {
        .querystd = adv7180_querystd,
        .g_input_status = adv7180_g_input_status,
@@ -150,6 +216,7 @@ static const struct v4l2_subdev_video_ops adv7180_video_ops = {
 
 static const struct v4l2_subdev_core_ops adv7180_core_ops = {
        .g_chip_ident = adv7180_g_chip_ident,
+       .s_std = adv7180_s_std,
 };
 
 static const struct v4l2_subdev_ops adv7180_ops = {
@@ -179,6 +246,7 @@ static int adv7180_probe(struct i2c_client *client,
        state = kzalloc(sizeof(struct adv7180_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
+       state->autodetect = true;
        sd = &state->sd;
        v4l2_i2c_subdev_init(sd, client, &adv7180_ops);