Re: [PATCH 05/11] media: adv7180: init chip with AD recommended register settings

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jul 6, 2016 at 3:59 PM, Steve Longerbeam <slongerbeam@xxxxxxxxx> wrote:
> Define and load register tables that conform to Analog Device's
> recommended register settings. It loads the default single-ended
> CVBS on Ain1 configuration for both ADV7180 and ADV7182 chips.
>
> New register addresses have been defined for the tables. Those new
> defines are also used in existing locations where hard-coded addresses
> were used.
>
> Note this patch also enables NEWAVMODE, which is also recommended by
> Analog Devices. This will likely break any current backends using this
> subdev that are expecting different or manually configured AV codes.
>
> Note also that bt.656-4 support has been removed in this patch, but it
> will be brought back in a subsequent patch.
>
> Signed-off-by: Steve Longerbeam <steve_longerbeam@xxxxxxxxxx>
> ---
>  drivers/media/i2c/adv7180.c | 168 ++++++++++++++++++++++++++++++++++----------
>  1 file changed, 130 insertions(+), 38 deletions(-)
>
> diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
> index 42816d4..92e2f37 100644
> --- a/drivers/media/i2c/adv7180.c
> +++ b/drivers/media/i2c/adv7180.c
> @@ -56,10 +56,11 @@
>
>  #define ADV7182_REG_INPUT_VIDSEL                       0x0002
>
> +#define ADV7180_REG_OUTPUT_CONTROL                     0x0003
>  #define ADV7180_REG_EXTENDED_OUTPUT_CONTROL            0x0004
>  #define ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS                0xC5
>
> -#define ADV7180_REG_AUTODETECT_ENABLE                  0x07
> +#define ADV7180_REG_AUTODETECT_ENABLE                  0x0007
>  #define ADV7180_AUTODETECT_DEFAULT                     0x7f
>  /* Contrast */
>  #define ADV7180_REG_CON                0x0008  /*Unsigned */
> @@ -100,6 +101,20 @@
>  #define ADV7180_REG_IDENT 0x0011
>  #define ADV7180_ID_7180 0x18
>
> +#define ADV7180_REG_STATUS3            0x0013
> +#define ADV7180_REG_ANALOG_CLAMP_CTL   0x0014
> +#define ADV7180_REG_SHAP_FILTER_CTL_1  0x0017
> +#define ADV7180_REG_CTRL_2             0x001d
> +#define ADV7180_REG_VSYNC_FIELD_CTL_1  0x0031
> +#define ADV7180_REG_MANUAL_WIN_CTL_1   0x003d
> +#define ADV7180_REG_MANUAL_WIN_CTL_2   0x003e
> +#define ADV7180_REG_MANUAL_WIN_CTL_3   0x003f
> +#define ADV7180_REG_LOCK_CNT           0x0051
> +#define ADV7180_REG_CVBS_TRIM          0x0052
> +#define ADV7180_REG_CLAMP_ADJ          0x005a
> +#define ADV7180_REG_RES_CIR            0x005f
> +#define ADV7180_REG_DIFF_MODE          0x0060
> +
>  #define ADV7180_REG_ICONF1             0x2040
>  #define ADV7180_ICONF1_ACTIVE_LOW      0x01
>  #define ADV7180_ICONF1_PSYNC_ONLY      0x10
> @@ -129,9 +144,15 @@
>  #define ADV7180_REG_VPP_SLAVE_ADDR     0xFD
>  #define ADV7180_REG_CSI_SLAVE_ADDR     0xFE
>
> -#define ADV7180_REG_FLCONTROL 0x40e0
> +#define ADV7180_REG_ACE_CTRL1          0x4080
> +#define ADV7180_REG_ACE_CTRL5          0x4084
> +#define ADV7180_REG_FLCONTROL          0x40e0
>  #define ADV7180_FLCONTROL_FL_ENABLE 0x1
>
> +#define ADV7180_REG_RST_CLAMP  0x809c
> +#define ADV7180_REG_AGC_ADJ1   0x80b6
> +#define ADV7180_REG_AGC_ADJ2   0x80c0
> +
>  #define ADV7180_CSI_REG_PWRDN  0x00
>  #define ADV7180_CSI_PWRDN      0x80
>
> @@ -209,6 +230,11 @@ struct adv7180_state {
>                                             struct adv7180_state,       \
>                                             ctrl_hdl)->sd)
>
> +struct adv7180_reg_tbl_t {
> +       unsigned int reg;
> +       unsigned int val;
> +};
> +
>  static int adv7180_select_page(struct adv7180_state *state, unsigned int page)
>  {
>         if (state->register_page != page) {
> @@ -235,6 +261,20 @@ static int adv7180_read(struct adv7180_state *state, unsigned int reg)
>         return i2c_smbus_read_byte_data(state->client, reg & 0xff);
>  }
>
> +static int adv7180_load_reg_tbl(struct adv7180_state *state,
> +                               const struct adv7180_reg_tbl_t *tbl, int n)
> +{
> +       int ret, i;
> +
> +       for (i = 0; i < n; i++) {
> +               ret = adv7180_write(state, tbl[i].reg, tbl[i].val);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
>  static int adv7180_csi_write(struct adv7180_state *state, unsigned int reg,
>         unsigned int value)
>  {
> @@ -828,19 +868,36 @@ static irqreturn_t adv7180_irq(int irq, void *devid)
>         return IRQ_HANDLED;
>  }
>
> +/*
> + * This register table conforms to Analog Device's Register Settings
> + * Recommendation for the ADV7180. It configures single-ended CVBS
> + * input on Ain1, and enables NEWAVMODE.
> + */
> +static const struct adv7180_reg_tbl_t adv7180_single_ended_cvbs[] = {
> +       /* Set analog mux for CVBS on Ain1 */
> +       { ADV7180_REG_INPUT_CONTROL, 0x00 },
> +       /* ADI Required Write: Reset Clamp Circuitry */
> +       { ADV7180_REG_ANALOG_CLAMP_CTL, 0x30 },
> +       /* Enable SFL Output */
> +       { ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57 },
> +       /* Select SH1 Chroma Shaping Filter */
> +       { ADV7180_REG_SHAP_FILTER_CTL_1, 0x41 },
> +       /* Enable NEWAVMODE */
> +       { ADV7180_REG_VSYNC_FIELD_CTL_1, 0x02 },
> +       /* ADI Required Write: optimize windowing function Step 1,2,3 */
> +       { ADV7180_REG_MANUAL_WIN_CTL_1, 0xA2 },
> +       { ADV7180_REG_MANUAL_WIN_CTL_2, 0x6A },
> +       { ADV7180_REG_MANUAL_WIN_CTL_3, 0xA0 },
> +       /* ADI Required Write: Enable ADC step 1,2,3 */
> +       { 0x8055, 0x81 }, /* undocumented register 0x55 */
> +       /* Recommended AFE I BIAS Setting for CVBS mode */
> +       { ADV7180_REG_CVBS_TRIM, 0x0D },
> +};
> +
>  static int adv7180_init(struct adv7180_state *state)
>  {
> -       int ret;
> -
> -       /* ITU-R BT.656-4 compatible */
> -       ret = adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
> -                       ADV7180_EXTENDED_OUTPUT_CONTROL_NTSCDIS);
> -       if (ret < 0)
> -               return ret;
> -
> -       /* Manually set V bit end position in NTSC mode */
> -       return adv7180_write(state, ADV7180_REG_NTSC_V_BIT_END,
> -                                       ADV7180_NTSC_V_BIT_END_MANUAL_NVEND);
> +       return adv7180_load_reg_tbl(state, adv7180_single_ended_cvbs,
> +                                   ARRAY_SIZE(adv7180_single_ended_cvbs));
>  }
>
>  static int adv7180_set_std(struct adv7180_state *state, unsigned int std)
> @@ -862,8 +919,48 @@ static int adv7180_select_input(struct adv7180_state *state, unsigned int input)
>         return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret);
>  }
>
> +/*
> + * This register table conforms to Analog Device's Register Settings
> + * Recommendation revision C for the ADV7182. It configures single-ended
> + * CVBS inputs on Ain1, and enables NEWAVMODE.
> + */
> +static const struct adv7180_reg_tbl_t adv7182_single_ended_cvbs[] = {
> +       /* Exit Power Down Mode */
> +       { ADV7180_REG_PWR_MAN, 0x00 },
> +       /* Enable ADV7182 for 28.63636 MHz Crystal Clock Input */
> +       { ADV7180_REG_STATUS3, 0x00 },
> +       /* Set optimized IBIAS for single-ended CVBS input */
> +       { ADV7180_REG_CVBS_TRIM, 0xCD },
> +       /* Switch to single-ended CVBS on AIN1 */
> +       { ADV7180_REG_INPUT_CONTROL, 0x00 },
> +       /* ADI Required Write: Reset Current Clamp Circuitry steps 1,2,3,4 */
> +       { ADV7180_REG_RST_CLAMP, 0x00 },
> +       { ADV7180_REG_RST_CLAMP, 0xFF },
> +       /* Select SH1 Chroma Shaping Filter */
> +       { ADV7180_REG_SHAP_FILTER_CTL_1, 0x41 },
> +       /* Enable Pixel & Sync output drivers */
> +       { ADV7180_REG_OUTPUT_CONTROL, 0x0C },
> +       /* Power-up INTRQ, HS and VS/FIELD/SFL pad */
> +       { ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x07 },
> +       /* Enable LLC Output Driver */
> +       { ADV7180_REG_CTRL_2, 0x40 },
> +       /* Optimize ACE Performance */
> +       { ADV7180_REG_ACE_CTRL5, 0x00 },
> +       /* Enable ACE Feature */
> +       { ADV7180_REG_ACE_CTRL1, 0x80 },
> +       /* Enable NEWAVMODE */
> +       { ADV7180_REG_VSYNC_FIELD_CTL_1, 0x02 },
> +};
> +
>  static int adv7182_init(struct adv7180_state *state)
>  {
> +       int ret;
> +
> +       ret = adv7180_load_reg_tbl(state, adv7182_single_ended_cvbs,
> +                                  ARRAY_SIZE(adv7182_single_ended_cvbs));
> +       if (ret)
> +               return ret;
> +
>         if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2)
>                 adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR,
>                         ADV7180_DEFAULT_CSI_I2C_ADDR << 1);
> @@ -881,20 +978,15 @@ static int adv7182_init(struct adv7180_state *state)
>
>         /* ADI required writes */
>         if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) {
> -               adv7180_write(state, 0x0003, 0x4e);
> -               adv7180_write(state, 0x0004, 0x57);
> -               adv7180_write(state, 0x001d, 0xc0);
> +               adv7180_write(state, ADV7180_REG_OUTPUT_CONTROL, 0x4e);
> +               adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL, 0x57);
> +               adv7180_write(state, ADV7180_REG_CTRL_2, 0xc0);
>         } else {
>                 if (state->chip_info->flags & ADV7180_FLAG_V2)
> -                       adv7180_write(state, 0x0004, 0x17);
> -               else
> -                       adv7180_write(state, 0x0004, 0x07);
> -               adv7180_write(state, 0x0003, 0x0c);
> -               adv7180_write(state, 0x001d, 0x40);
> +                       adv7180_write(state, ADV7180_REG_EXTENDED_OUTPUT_CONTROL,
> +                                     0x17);
>         }
>
> -       adv7180_write(state, 0x0013, 0x00);
> -
>         return 0;
>  }
>
> @@ -967,8 +1059,8 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
>                 return ret;
>
>         /* Reset clamp circuitry - ADI recommended writes */
> -       adv7180_write(state, 0x809c, 0x00);
> -       adv7180_write(state, 0x809c, 0xff);
> +       adv7180_write(state, ADV7180_REG_RST_CLAMP, 0x00);
> +       adv7180_write(state, ADV7180_REG_RST_CLAMP, 0xff);
>
>         input_type = adv7182_get_input_type(input);
>
> @@ -976,10 +1068,10 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
>         case ADV7182_INPUT_TYPE_CVBS:
>         case ADV7182_INPUT_TYPE_DIFF_CVBS:
>                 /* ADI recommends to use the SH1 filter */
> -               adv7180_write(state, 0x0017, 0x41);
> +               adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x41);
>                 break;
>         default:
> -               adv7180_write(state, 0x0017, 0x01);
> +               adv7180_write(state, ADV7180_REG_SHAP_FILTER_CTL_1, 0x01);
>                 break;
>         }
>
> @@ -989,21 +1081,21 @@ static int adv7182_select_input(struct adv7180_state *state, unsigned int input)
>                 lbias = adv7182_lbias_settings[input_type];
>
>         for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++)
> -               adv7180_write(state, 0x0052 + i, lbias[i]);
> +               adv7180_write(state, ADV7180_REG_CVBS_TRIM + i, lbias[i]);
>
>         if (input_type == ADV7182_INPUT_TYPE_DIFF_CVBS) {
>                 /* ADI required writes to make differential CVBS work */
> -               adv7180_write(state, 0x005f, 0xa8);
> -               adv7180_write(state, 0x005a, 0x90);
> -               adv7180_write(state, 0x0060, 0xb0);
> -               adv7180_write(state, 0x80b6, 0x08);
> -               adv7180_write(state, 0x80c0, 0xa0);
> +               adv7180_write(state, ADV7180_REG_RES_CIR, 0xa8);
> +               adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0x90);
> +               adv7180_write(state, ADV7180_REG_DIFF_MODE, 0xb0);
> +               adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x08);
> +               adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0xa0);
>         } else {
> -               adv7180_write(state, 0x005f, 0xf0);
> -               adv7180_write(state, 0x005a, 0xd0);
> -               adv7180_write(state, 0x0060, 0x10);
> -               adv7180_write(state, 0x80b6, 0x9c);
> -               adv7180_write(state, 0x80c0, 0x00);
> +               adv7180_write(state, ADV7180_REG_RES_CIR, 0xf0);
> +               adv7180_write(state, ADV7180_REG_CLAMP_ADJ, 0xd0);
> +               adv7180_write(state, ADV7180_REG_DIFF_MODE, 0x10);
> +               adv7180_write(state, ADV7180_REG_AGC_ADJ1, 0x9c);
> +               adv7180_write(state, ADV7180_REG_AGC_ADJ2, 0x00);
>         }
>
>         return 0;
> --

Steve,

Tested on an IMX6 Gateworks Ventana with IMX6 capture drivers [1].

Tested-by: Tim Harvey <tharvey@xxxxxxxxxxxxx>
Acked-by: Tim Harvey <tharvey@xxxxxxxxxxxxx>

Added to Cc:
Cc: Lars-Peter Clausen <lars@xxxxxxxxxx>

Also adding Cc's to the people who are using the adv7180 on other
boards (renesas r8a779* boards) so we can get some feedback and/or
Tested-by from them:
Cc: Sergei Shtylyov <sergei.shtylyov@xxxxxxxxxxxxxxxxxx>
Cc: Simon Horman <horms+renesas@xxxxxxxxxxxx>

I'm wondering if those boards need the bt656-4 which was previously
being enabled per your comment and is now moved to a dt-prop per a
subsequent patch.

Regards,

Tim

[1] - http://thread.gmane.org/gmane.linux.drivers.video-input-infrastructure/102914
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux