Hi Lars,

On 01/13/2015 01:01 PM, Lars-Peter Clausen wrote:
> The adv7180 (and similar) has support for a so called free run mode in which
> it will output a predefined test signal. This patch adds support for
> configuring the various aspects of the so called free run mode.
> 
> The patch adds three new v4l controls:
>       * Free Running Mode: Allows to either disable or enable free running
>         mode or set it to automatic. In automatic mode the adv7180 will go to
>         free run mode if no external signal source could be detected
>       * Free Running Pattern: Allows to select which pattern will be displayed
>         in free run mode
>       * Free Running Color: Allows to select the color of the pattern
> 
> Signed-off-by: Lars-Peter Clausen <l...@metafoo.de>
> ---
>  drivers/media/i2c/adv7180.c | 125 
> ++++++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 122 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
> index 82c8296..678d6c9 100644
> --- a/drivers/media/i2c/adv7180.c
> +++ b/drivers/media/i2c/adv7180.c
> @@ -75,6 +75,9 @@
>  #define ADV7180_HUE_DEF              0
>  #define ADV7180_HUE_MAX              128
>  
> +#define ADV7180_REG_DEF_VAL_Y                0x000c
> +#define ADV7180_REG_DEF_VAL_C                0x000d
> +
>  #define ADV7180_REG_CTRL             0x000e
>  #define ADV7180_CTRL_IRQ_SPACE               0x20
>  
> @@ -168,6 +171,11 @@
>  #define ADV7180_DEFAULT_VPP_I2C_ADDR 0x42
>  
>  #define V4L2_CID_ADV_FAST_SWITCH     (V4L2_CID_DV_CLASS_BASE + 0x1010)
> +#define V4L2_CID_ADV_FREE_RUN_COLOR  (V4L2_CID_DV_CLASS_BASE + 0x1002)
> +#define V4L2_CID_ADV_FREE_RUN_MODE   (V4L2_CID_DV_CLASS_BASE + 0x1003)
> +#define V4L2_CID_ADV_FREE_RUN_PATTERN        (V4L2_CID_DV_CLASS_BASE + 
> 0x1004)

See same comment as I made in patch 8 regarding private controls.

> +
> +#define ADV7180_INPUT_DISABLED (~0x00)
>  
>  struct adv7180_state;
>  
> @@ -193,6 +201,7 @@ struct adv7180_state {
>       v4l2_std_id             curr_norm;
>       bool                    autodetect;
>       bool                    powered;
> +     bool                    force_free_run;
>       u8                      input;
>  
>       struct i2c_client       *client;
> @@ -363,10 +372,13 @@ static int adv7180_s_routing(struct v4l2_subdev *sd, 
> u32 input,
>               goto out;
>       }
>  
> -     ret = state->chip_info->select_input(state, input);
> -
> -     if (ret == 0)
> +     if (state->force_free_run) {
>               state->input = input;
> +     } else {
> +             ret = state->chip_info->select_input(state, input);
> +             if (ret == 0)
> +                     state->input = input;
> +     }
>  out:
>       mutex_unlock(&state->mutex);
>       return ret;
> @@ -488,6 +500,7 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
>  {
>       struct adv7180_state *state = ctrl_to_adv7180(ctrl);
>       int ret = mutex_lock_interruptible(&state->mutex);
> +     int reg_val;
>       int val;
>  
>       if (ret)
> @@ -526,6 +539,53 @@ static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl)
>                       adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00);
>               }
>               break;
> +     case V4L2_CID_ADV_FREE_RUN_MODE:
> +             switch (ctrl->val) {
> +             case 1: /* Enabled */
> +                     ret = state->chip_info->select_input(state,
> +                             ADV7180_INPUT_DISABLED);
> +                     state->force_free_run = true;
> +                     break;
> +             case 0: /* Disabled */
> +             case 2: /* Automatic */
> +                     ret = state->chip_info->select_input(state,
> +                             state->input);
> +                     state->force_free_run = false;
> +                     break;
> +             default:
> +                     break;
> +             }
> +             reg_val = adv7180_read(state, ADV7180_REG_DEF_VAL_Y);
> +             reg_val &= 0xfc;
> +             reg_val |= ctrl->val;
> +             adv7180_write(state, ADV7180_REG_DEF_VAL_Y, reg_val);
> +             break;
> +     case V4L2_CID_ADV_FREE_RUN_PATTERN:
> +             reg_val = adv7180_read(state, 0x14);
> +             reg_val &= 0xf8;
> +             reg_val |= ctrl->val;
> +             adv7180_write(state, 0x14, reg_val);
> +             break;
> +     case V4L2_CID_ADV_FREE_RUN_COLOR: {
> +             int r = (ctrl->val & 0xff0000) >> 16;
> +             int g = (ctrl->val & 0x00ff00) >> 8;
> +             int b = (ctrl->val & 0x0000ff);
> +             /* RGB -> YCbCr, numerical approximation */
> +             int y = ((66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
> +             int cb = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
> +             int cr = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
> +
> +             /* Y is 6-bit, Cb and Cr 4-bit */
> +             y >>= 2;
> +             cb >>= 4;
> +             cr >>= 4;
> +
> +             reg_val = adv7180_read(state, ADV7180_REG_DEF_VAL_Y);
> +             adv7180_write(state, ADV7180_REG_DEF_VAL_Y,
> +                     (y << 2) | (reg_val & 0x03));
> +             adv7180_write(state, ADV7180_REG_DEF_VAL_C, (cr << 4) | cb);
> +             break;
> +     }
>       default:
>               ret = -EINVAL;
>       }
> @@ -548,6 +608,53 @@ static const struct v4l2_ctrl_config 
> adv7180_ctrl_fast_switch = {
>       .step = 1,
>  };
>  
> +static const char * const adv7180_free_run_pattern_strings[] = {
> +     "Solid",
> +     "Bars",
> +     "Luma Ramp",
> +     "Reserved",
> +     "Reserved",
> +     "Boundary Box",
> +};
> +
> +static const char * const adv7180_free_run_mode_strings[] = {
> +     "Disabled",
> +     "Enabled",
> +     "Automatic",
> +};
> +
> +static const struct v4l2_ctrl_config adv7180_ctrl_free_run_color = {
> +     .ops = &adv7180_ctrl_ops,
> +     .id = V4L2_CID_ADV_FREE_RUN_COLOR,
> +     .name = "Free Running Color",
> +     .type = V4L2_CTRL_TYPE_INTEGER,
> +     .min = 0,
> +     .max = 0xffffff,
> +     .step = 0x1,
> +};
> +
> +static const struct v4l2_ctrl_config adv7180_ctrl_free_run_mode = {
> +     .ops = &adv7180_ctrl_ops,
> +     .id = V4L2_CID_ADV_FREE_RUN_MODE,
> +     .name = "Free Running Mode",
> +     .type = V4L2_CTRL_TYPE_MENU,
> +     .min = 0,
> +     .max = ARRAY_SIZE(adv7180_free_run_mode_strings) - 1,
> +     .def = 2,
> +     .qmenu = adv7180_free_run_mode_strings,
> +};

The adv7604 and adv7842 drivers have similar free-run controls. I am wondering
if these controls shouldn't be promoted to standard controls. Free-run support
is fairly common after all.

> +
> +static const struct v4l2_ctrl_config adv7180_ctrl_free_run_pattern = {
> +     .ops = &adv7180_ctrl_ops,
> +     .id = V4L2_CID_ADV_FREE_RUN_PATTERN,
> +     .name = "Free Running Pattern",
> +     .type = V4L2_CTRL_TYPE_MENU,
> +     .min = 0,
> +     .max = ARRAY_SIZE(adv7180_free_run_pattern_strings) - 1,
> +     .menu_skip_mask = 0x18, /* 0x3 and 0x4 are reserved */
> +     .qmenu = adv7180_free_run_pattern_strings,
> +};

Wouldn't it be better to use V4L2_CID_TEST_PATTERN for this?

> +
>  static int adv7180_init_controls(struct adv7180_state *state)
>  {
>       v4l2_ctrl_handler_init(&state->ctrl_hdl, 4);
> @@ -565,6 +672,12 @@ static int adv7180_init_controls(struct adv7180_state 
> *state)
>                         V4L2_CID_HUE, ADV7180_HUE_MIN,
>                         ADV7180_HUE_MAX, 1, ADV7180_HUE_DEF);
>       v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_fast_switch, NULL);
> +     v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_free_run_color,
> +             NULL);
> +     v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_free_run_mode,
> +             NULL);
> +     v4l2_ctrl_new_custom(&state->ctrl_hdl, &adv7180_ctrl_free_run_pattern,
> +             NULL);
>  
>       state->sd.ctrl_handler = &state->ctrl_hdl;
>       if (state->ctrl_hdl.error) {
> @@ -784,6 +897,9 @@ static int adv7180_select_input(struct adv7180_state 
> *state, unsigned int input)
>  {
>       int ret;
>  
> +     if (input == ADV7180_INPUT_DISABLED)
> +             input = 0x00;
> +
>       ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL);
>       if (ret < 0)
>               return ret;
> @@ -893,6 +1009,9 @@ static int adv7182_select_input(struct adv7180_state 
> *state, unsigned int input)
>       unsigned int i;
>       int ret;
>  
> +     if (input == ADV7180_INPUT_DISABLED)
> +             return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, 0xff);
> +
>       ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input);
>       if (ret)
>               return ret;
> 

Regards,

        Hans
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to