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); }
static int adv7180_set_power(struct adv7180_state *state, bool on) { u8 val; int ret; if (on) val = ADV7180_PWR_MAN_ON; else val = ADV7180_PWR_MAN_OFF; ret = adv7180_write(state, ADV7180_REG_PWR_MAN, val); if (ret) return ret; if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) { if (on) { adv7180_csi_write(state, 0xDE, 0x02); adv7180_csi_write(state, 0xD2, 0xF7); adv7180_csi_write(state, 0xD8, 0x65); adv7180_csi_write(state, 0xE0, 0x09); adv7180_csi_write(state, 0x2C, 0x00); if (state->field == V4L2_FIELD_NONE) adv7180_csi_write(state, 0x1D, 0x80); adv7180_csi_write(state, 0x00, 0x00); } else { adv7180_csi_write(state, 0x00, 0x80); } } return 0; }
static int adv7180_s_ctrl(struct v4l2_ctrl *ctrl) { struct v4l2_subdev *sd = to_adv7180_sd(ctrl); struct adv7180_state *state = to_state(sd); int ret = mutex_lock_interruptible(&state->mutex); int val; if (ret) return ret; val = ctrl->val; switch (ctrl->id) { case V4L2_CID_BRIGHTNESS: ret = adv7180_write(state, ADV7180_REG_BRI, val); break; case V4L2_CID_HUE: /*Hue is inverted according to HSL chart */ ret = adv7180_write(state, ADV7180_REG_HUE, -val); break; case V4L2_CID_CONTRAST: ret = adv7180_write(state, ADV7180_REG_CON, val); break; case V4L2_CID_SATURATION: /* *This could be V4L2_CID_BLUE_BALANCE/V4L2_CID_RED_BALANCE *Let's not confuse the user, everybody understands saturation */ ret = adv7180_write(state, ADV7180_REG_SD_SAT_CB, val); if (ret < 0) break; ret = adv7180_write(state, ADV7180_REG_SD_SAT_CR, val); break; case V4L2_CID_ADV_FAST_SWITCH: if (ctrl->val) { /* ADI required write */ adv7180_write(state, 0x80d9, 0x44); adv7180_write(state, ADV7180_REG_FLCONTROL, ADV7180_FLCONTROL_FL_ENABLE); } else { /* ADI required write */ adv7180_write(state, 0x80d9, 0xc4); adv7180_write(state, ADV7180_REG_FLCONTROL, 0x00); } break; default: ret = -EINVAL; } mutex_unlock(&state->mutex); return ret; }
static int adv7180_select_input(struct adv7180_state *state, unsigned int input) { int ret; ret = adv7180_read(state, ADV7180_REG_INPUT_CONTROL); if (ret < 0) return ret; ret &= ~ADV7180_INPUT_CONTROL_INSEL_MASK; ret |= input; return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, ret); }
static irqreturn_t adv7180_irq(int irq, void *devid) { struct adv7180_state *state = devid; u8 isr3; mutex_lock(&state->mutex); isr3 = adv7180_read(state, ADV7180_REG_ISR3); /* clear */ adv7180_write(state, ADV7180_REG_ICR3, isr3); if (isr3 & ADV7180_IRQ3_AD_CHANGE) { static const struct v4l2_event src_ch = { .type = V4L2_EVENT_SOURCE_CHANGE, .u.src_change.changes = V4L2_EVENT_SRC_CH_RESOLUTION, }; v4l2_subdev_notify_event(&state->sd, &src_ch); } mutex_unlock(&state->mutex); return IRQ_HANDLED; } 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); }
static irqreturn_t adv7180_irq(int irq, void *devid) { struct adv7180_state *state = devid; u8 isr3; mutex_lock(&state->mutex); isr3 = adv7180_read(state, ADV7180_REG_ISR3); /* clear */ adv7180_write(state, ADV7180_REG_ICR3, isr3); if (isr3 & ADV7180_IRQ3_AD_CHANGE && state->autodetect) __adv7180_status(state, NULL, &state->curr_norm); mutex_unlock(&state->mutex); return IRQ_HANDLED; }
static int init_device(struct adv7180_state *state) { int ret; mutex_lock(&state->mutex); adv7180_write(state, ADV7180_REG_PWR_MAN, ADV7180_PWR_MAN_RES); usleep_range(5000, 10000); ret = state->chip_info->init(state); if (ret) goto out_unlock; ret = adv7180_program_std(state); if (ret) goto out_unlock; adv7180_set_field_mode(state); /* register for interrupts */ if (state->irq > 0) { /* config the Interrupt pin to be active low */ ret = adv7180_write(state, ADV7180_REG_ICONF1, ADV7180_ICONF1_ACTIVE_LOW | ADV7180_ICONF1_PSYNC_ONLY); if (ret < 0) goto out_unlock; ret = adv7180_write(state, ADV7180_REG_IMR1, 0); if (ret < 0) goto out_unlock; ret = adv7180_write(state, ADV7180_REG_IMR2, 0); if (ret < 0) goto out_unlock; /* enable AD change interrupts interrupts */ ret = adv7180_write(state, ADV7180_REG_IMR3, ADV7180_IRQ3_AD_CHANGE); if (ret < 0) goto out_unlock; ret = adv7180_write(state, ADV7180_REG_IMR4, 0); if (ret < 0) goto out_unlock; } out_unlock: mutex_unlock(&state->mutex); return ret; }
static int adv7182_select_input(struct adv7180_state *state, unsigned int input) { enum adv7182_input_type input_type; unsigned int *lbias; unsigned int i; int ret; ret = adv7180_write(state, ADV7180_REG_INPUT_CONTROL, input); if (ret) return ret; /* Reset clamp circuitry - ADI recommended writes */ adv7180_write(state, 0x809c, 0x00); adv7180_write(state, 0x809c, 0xff); input_type = adv7182_get_input_type(input); switch (input_type) { case ADV7182_INPUT_TYPE_CVBS: case ADV7182_INPUT_TYPE_DIFF_CVBS: /* ADI recommends to use the SH1 filter */ adv7180_write(state, 0x0017, 0x41); break; default: adv7180_write(state, 0x0017, 0x01); break; } if (state->chip_info->flags & ADV7180_FLAG_V2) lbias = adv7280_lbias_settings[input_type]; else lbias = adv7182_lbias_settings[input_type]; for (i = 0; i < ARRAY_SIZE(adv7182_lbias_settings[0]); i++) adv7180_write(state, 0x0052 + 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); } 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); } return 0; }
static int adv7182_set_std(struct adv7180_state *state, unsigned int std) { return adv7180_write(state, ADV7182_REG_INPUT_VIDSEL, std << 4); }
static int adv7182_init(struct adv7180_state *state) { if (state->chip_info->flags & ADV7180_FLAG_MIPI_CSI2) adv7180_write(state, ADV7180_REG_CSI_SLAVE_ADDR, ADV7180_DEFAULT_CSI_I2C_ADDR << 1); if (state->chip_info->flags & ADV7180_FLAG_I2P) adv7180_write(state, ADV7180_REG_VPP_SLAVE_ADDR, ADV7180_DEFAULT_VPP_I2C_ADDR << 1); if (state->chip_info->flags & ADV7180_FLAG_V2) { /* ADI recommended writes for improved video quality */ adv7180_write(state, 0x0080, 0x51); adv7180_write(state, 0x0081, 0x51); adv7180_write(state, 0x0082, 0x68); } /* 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); } 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, 0x0013, 0x00); return 0; }
static int adv7180_set_std(struct adv7180_state *state, unsigned int std) { return adv7180_write(state, ADV7180_REG_INPUT_CONTROL, (std << 4) | state->input); }
/* * adv7180_init * Initializes adv7180 via I2C */ int __init adv7180_init(int i2c_adapt, int i2c_addr, int reset_gpio, int input) { int err = 0; printk(KERN_INFO "Initializing ADV7180\n"); /* * Reset the adv7180 */ if (reset_gpio) { if (gpio_request(reset_gpio, "ADV7180 Reset")) { printk(KERN_WARNING "%s: failed to allocate ADV7180 Reset\n", __FUNCTION__); return -EBUSY; } gpio_direction_output(reset_gpio, 0); udelay(1); gpio_set_value(reset_gpio, 1); udelay(1); } /* * Turn on transmitter. */ err = adv7180_write(i2c_adapt, i2c_addr, 0x00, 0x10 | input); err = adv7180_write(i2c_adapt, i2c_addr, 0x03, 0x08); err = adv7180_write(i2c_adapt, i2c_addr, 0x04, 0x5d); err = adv7180_write(i2c_adapt, i2c_addr, 0x17, 0x41); err = adv7180_write(i2c_adapt, i2c_addr, 0x31, 0x12); err = adv7180_write(i2c_adapt, i2c_addr, 0x3d, 0xa2); err = adv7180_write(i2c_adapt, i2c_addr, 0x3e, 0x6a); err = adv7180_write(i2c_adapt, i2c_addr, 0x3f, 0xa0); err = adv7180_write(i2c_adapt, i2c_addr, 0x0e, 0x80); err = adv7180_write(i2c_adapt, i2c_addr, 0x55, 0x81); err = adv7180_write(i2c_adapt, i2c_addr, 0x0e, 0x00); err = adv7180_write(i2c_adapt, i2c_addr, 0x8f, 0x50); err = adv7180_write(i2c_adapt, i2c_addr, 0xe6, 0x10); err = adv7180_write(i2c_adapt, i2c_addr, 0x34, 0x00); err = adv7180_write(i2c_adapt, i2c_addr, 0x35, 240); err = adv7180_write(i2c_adapt, i2c_addr, 0x36, 0x00); if (err) { printk(KERN_WARNING "%s: failed to write ADV7180\n", __FUNCTION__); return err; } return 0; }