diff options
author | Hans de Goede <hdegoede@redhat.com> | 2009-10-12 10:32:44 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-12-05 15:40:34 -0500 |
commit | ebbb5c3e0eb73db4da5bee57cd0344a74cf73319 (patch) | |
tree | a02fc47f82731627aab320a4735c1f2d7b0c4910 /drivers/media/video/gspca/ov519.c | |
parent | b46aaa02648cd8c1ebc20191304e2f6a2382d04c (diff) |
V4L/DVB (13146): gspca_ov519: cleanup sensor handling
There were various "if (sensor == foo)" pieces of code inside ov519.c,
move these bits to the sensor specific init functions, where they
belong.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/gspca/ov519.c')
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 159 |
1 files changed, 59 insertions, 100 deletions
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 30e91c365ea4..4d6a762a6f3d 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -3501,7 +3501,8 @@ static int ov519_mode_init_regs(struct sd *sd) | |||
3501 | static int mode_init_ov_sensor_regs(struct sd *sd) | 3501 | static int mode_init_ov_sensor_regs(struct sd *sd) |
3502 | { | 3502 | { |
3503 | struct gspca_dev *gspca_dev; | 3503 | struct gspca_dev *gspca_dev; |
3504 | int qvga; | 3504 | int qvga, xstart, xend, ystart, yend; |
3505 | __u8 v; | ||
3505 | 3506 | ||
3506 | gspca_dev = &sd->gspca_dev; | 3507 | gspca_dev = &sd->gspca_dev; |
3507 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; | 3508 | qvga = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv & 1; |
@@ -3517,9 +3518,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3517 | i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); | 3518 | i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); |
3518 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | 3519 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); |
3519 | return 0; | 3520 | return 0; |
3520 | case SEN_OV3610: { | 3521 | case SEN_OV3610: |
3521 | int xstart, xend, ystart, yend; | ||
3522 | |||
3523 | if (qvga) { | 3522 | if (qvga) { |
3524 | xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); | 3523 | xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4); |
3525 | ystart = (776 - gspca_dev->height) / 2; | 3524 | ystart = (776 - gspca_dev->height) / 2; |
@@ -3543,13 +3542,19 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3543 | i2c_w(sd, 0x19, ystart >> 3); | 3542 | i2c_w(sd, 0x19, ystart >> 3); |
3544 | i2c_w(sd, 0x1a, yend >> 3); | 3543 | i2c_w(sd, 0x1a, yend >> 3); |
3545 | return 0; | 3544 | return 0; |
3546 | } | ||
3547 | case SEN_OV8610: | 3545 | case SEN_OV8610: |
3548 | /* For OV8610 qvga means qsvga */ | 3546 | /* For OV8610 qvga means qsvga */ |
3549 | i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); | 3547 | i2c_w_mask(sd, OV7610_REG_COM_C, qvga ? (1 << 5) : 0, 1 << 5); |
3548 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3549 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3550 | i2c_w_mask(sd, 0x2d, 0x00, 0x40); /* from windrv 090403 */ | ||
3551 | i2c_w_mask(sd, 0x28, 0x20, 0x20); /* progressive mode on */ | ||
3550 | break; | 3552 | break; |
3551 | case SEN_OV7610: | 3553 | case SEN_OV7610: |
3552 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3554 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3555 | i2c_w(sd, 0x35, qvga?0x1e:0x9e); | ||
3556 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3557 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3553 | break; | 3558 | break; |
3554 | case SEN_OV7620: | 3559 | case SEN_OV7620: |
3555 | case SEN_OV76BE: | 3560 | case SEN_OV76BE: |
@@ -3560,6 +3565,10 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3560 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); | 3565 | i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); |
3561 | i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); | 3566 | i2c_w_mask(sd, 0x67, qvga ? 0xb0 : 0x90, 0xf0); |
3562 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); | 3567 | i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); |
3568 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3569 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3570 | if (sd->sensor == SEN_OV76BE) | ||
3571 | i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e); | ||
3563 | break; | 3572 | break; |
3564 | case SEN_OV7640: | 3573 | case SEN_OV7640: |
3565 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3574 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
@@ -3569,6 +3578,7 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3569 | /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ | 3578 | /* i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */ |
3570 | /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ | 3579 | /* i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */ |
3571 | /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ | 3580 | /* i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */ |
3581 | i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */ | ||
3572 | break; | 3582 | break; |
3573 | case SEN_OV7670: | 3583 | case SEN_OV7670: |
3574 | /* set COM7_FMT_VGA or COM7_FMT_QVGA | 3584 | /* set COM7_FMT_VGA or COM7_FMT_QVGA |
@@ -3577,55 +3587,56 @@ static int mode_init_ov_sensor_regs(struct sd *sd) | |||
3577 | i2c_w_mask(sd, OV7670_REG_COM7, | 3587 | i2c_w_mask(sd, OV7670_REG_COM7, |
3578 | qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, | 3588 | qvga ? OV7670_COM7_FMT_QVGA : OV7670_COM7_FMT_VGA, |
3579 | OV7670_COM7_FMT_MASK); | 3589 | OV7670_COM7_FMT_MASK); |
3590 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3591 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, | ||
3592 | OV7670_COM8_AWB); | ||
3593 | if (qvga) { /* QVGA from ov7670.c by | ||
3594 | * Jonathan Corbet */ | ||
3595 | xstart = 164; | ||
3596 | xend = 28; | ||
3597 | ystart = 14; | ||
3598 | yend = 494; | ||
3599 | } else { /* VGA */ | ||
3600 | xstart = 158; | ||
3601 | xend = 14; | ||
3602 | ystart = 10; | ||
3603 | yend = 490; | ||
3604 | } | ||
3605 | /* OV7670 hardware window registers are split across | ||
3606 | * multiple locations */ | ||
3607 | i2c_w(sd, OV7670_REG_HSTART, xstart >> 3); | ||
3608 | i2c_w(sd, OV7670_REG_HSTOP, xend >> 3); | ||
3609 | v = i2c_r(sd, OV7670_REG_HREF); | ||
3610 | v = (v & 0xc0) | ((xend & 0x7) << 3) | (xstart & 0x07); | ||
3611 | msleep(10); /* need to sleep between read and write to | ||
3612 | * same reg! */ | ||
3613 | i2c_w(sd, OV7670_REG_HREF, v); | ||
3614 | |||
3615 | i2c_w(sd, OV7670_REG_VSTART, ystart >> 2); | ||
3616 | i2c_w(sd, OV7670_REG_VSTOP, yend >> 2); | ||
3617 | v = i2c_r(sd, OV7670_REG_VREF); | ||
3618 | v = (v & 0xc0) | ((yend & 0x3) << 2) | (ystart & 0x03); | ||
3619 | msleep(10); /* need to sleep between read and write to | ||
3620 | * same reg! */ | ||
3621 | i2c_w(sd, OV7670_REG_VREF, v); | ||
3580 | break; | 3622 | break; |
3581 | case SEN_OV6620: | 3623 | case SEN_OV6620: |
3624 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | ||
3625 | i2c_w_mask(sd, 0x13, 0x00, 0x20); /* Select 16 bit data bus */ | ||
3626 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3627 | break; | ||
3582 | case SEN_OV6630: | 3628 | case SEN_OV6630: |
3583 | case SEN_OV66308AF: | 3629 | case SEN_OV66308AF: |
3584 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); | 3630 | i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20); |
3631 | i2c_w_mask(sd, 0x12, 0x04, 0x06); /* AWB: 1 Test pattern: 0 */ | ||
3585 | break; | 3632 | break; |
3586 | default: | 3633 | default: |
3587 | return -EINVAL; | 3634 | return -EINVAL; |
3588 | } | 3635 | } |
3589 | 3636 | ||
3590 | /******** Palette-specific regs ********/ | ||
3591 | |||
3592 | /* The OV518 needs special treatment. Although both the OV518 | ||
3593 | * and the OV6630 support a 16-bit video bus, only the 8 bit Y | ||
3594 | * bus is actually used. The UV bus is tied to ground. | ||
3595 | * Therefore, the OV6630 needs to be in 8-bit multiplexed | ||
3596 | * output mode */ | ||
3597 | |||
3598 | /* OV7640 is 8-bit only */ | ||
3599 | |||
3600 | if (sd->sensor != SEN_OV6630 && sd->sensor != SEN_OV66308AF && | ||
3601 | sd->sensor != SEN_OV7640) | ||
3602 | i2c_w_mask(sd, 0x13, 0x00, 0x20); | ||
3603 | |||
3604 | /******** Clock programming ********/ | 3637 | /******** Clock programming ********/ |
3605 | i2c_w(sd, 0x11, sd->clockdiv); | 3638 | i2c_w(sd, 0x11, sd->clockdiv); |
3606 | 3639 | ||
3607 | /******** Special Features ********/ | ||
3608 | /* no evidence this is possible with OV7670, either */ | ||
3609 | /* Test Pattern */ | ||
3610 | if (sd->sensor != SEN_OV7640 && sd->sensor != SEN_OV7670) | ||
3611 | i2c_w_mask(sd, 0x12, 0x00, 0x02); | ||
3612 | |||
3613 | /* Enable auto white balance */ | ||
3614 | if (sd->sensor == SEN_OV7670) | ||
3615 | i2c_w_mask(sd, OV7670_REG_COM8, OV7670_COM8_AWB, | ||
3616 | OV7670_COM8_AWB); | ||
3617 | else | ||
3618 | i2c_w_mask(sd, 0x12, 0x04, 0x04); | ||
3619 | |||
3620 | /* This will go away as soon as ov51x_mode_init_sensor_regs() */ | ||
3621 | /* is fully tested. */ | ||
3622 | /* 7620/6620/6630? don't have register 0x35, so play it safe */ | ||
3623 | if (sd->sensor == SEN_OV7610 || sd->sensor == SEN_OV76BE) { | ||
3624 | if (!qvga) | ||
3625 | i2c_w(sd, 0x35, 0x9e); | ||
3626 | else | ||
3627 | i2c_w(sd, 0x35, 0x1e); | ||
3628 | } | ||
3629 | return 0; | 3640 | return 0; |
3630 | } | 3641 | } |
3631 | 3642 | ||
@@ -3648,11 +3659,11 @@ static int set_ov_sensor_window(struct sd *sd) | |||
3648 | struct gspca_dev *gspca_dev; | 3659 | struct gspca_dev *gspca_dev; |
3649 | int qvga, crop; | 3660 | int qvga, crop; |
3650 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; | 3661 | int hwsbase, hwebase, vwsbase, vwebase, hwscale, vwscale; |
3651 | int ret, hstart, hstop, vstop, vstart; | 3662 | int ret; |
3652 | __u8 v; | ||
3653 | 3663 | ||
3654 | /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ | 3664 | /* mode setup is fully handled in mode_init_ov_sensor_regs for these */ |
3655 | if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610) | 3665 | if (sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610 || |
3666 | sd->sensor == SEN_OV7670) | ||
3656 | return mode_init_ov_sensor_regs(sd); | 3667 | return mode_init_ov_sensor_regs(sd); |
3657 | 3668 | ||
3658 | gspca_dev = &sd->gspca_dev; | 3669 | gspca_dev = &sd->gspca_dev; |
@@ -3701,11 +3712,6 @@ static int set_ov_sensor_window(struct sd *sd) | |||
3701 | hwebase = 0x1a; | 3712 | hwebase = 0x1a; |
3702 | vwsbase = vwebase = 0x03; | 3713 | vwsbase = vwebase = 0x03; |
3703 | break; | 3714 | break; |
3704 | case SEN_OV7670: | ||
3705 | /*handling of OV7670 hardware sensor start and stop values | ||
3706 | * is very odd, compared to the other OV sensors */ | ||
3707 | vwsbase = vwebase = hwebase = hwsbase = 0x00; | ||
3708 | break; | ||
3709 | default: | 3715 | default: |
3710 | return -EINVAL; | 3716 | return -EINVAL; |
3711 | } | 3717 | } |
@@ -3746,58 +3752,11 @@ static int set_ov_sensor_window(struct sd *sd) | |||
3746 | if (ret < 0) | 3752 | if (ret < 0) |
3747 | return ret; | 3753 | return ret; |
3748 | 3754 | ||
3749 | if (sd->sensor == SEN_OV8610) { | 3755 | i2c_w(sd, 0x17, hwsbase); |
3750 | i2c_w_mask(sd, 0x2d, 0x05, 0x40); | 3756 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); |
3751 | /* old 0x95, new 0x05 from windrv 090403 */ | 3757 | i2c_w(sd, 0x19, vwsbase); |
3752 | /* bits 5-7: reserved */ | 3758 | i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); |
3753 | i2c_w_mask(sd, 0x28, 0x20, 0x20); | ||
3754 | /* bit 5: progressive mode on */ | ||
3755 | } | ||
3756 | |||
3757 | /* The below is wrong for OV7670s because their window registers | ||
3758 | * only store the high bits in 0x17 to 0x1a */ | ||
3759 | |||
3760 | /* SRH Use sd->max values instead of requested win values */ | ||
3761 | /* SCS Since we're sticking with only the max hardware widths | ||
3762 | * for a given mode */ | ||
3763 | /* I can hard code this for OV7670s */ | ||
3764 | /* Yes, these numbers do look odd, but they're tested and work! */ | ||
3765 | if (sd->sensor == SEN_OV7670) { | ||
3766 | if (qvga) { /* QVGA from ov7670.c by | ||
3767 | * Jonathan Corbet */ | ||
3768 | hstart = 164; | ||
3769 | hstop = 28; | ||
3770 | vstart = 14; | ||
3771 | vstop = 494; | ||
3772 | } else { /* VGA */ | ||
3773 | hstart = 158; | ||
3774 | hstop = 14; | ||
3775 | vstart = 10; | ||
3776 | vstop = 490; | ||
3777 | } | ||
3778 | /* OV7670 hardware window registers are split across | ||
3779 | * multiple locations */ | ||
3780 | i2c_w(sd, OV7670_REG_HSTART, hstart >> 3); | ||
3781 | i2c_w(sd, OV7670_REG_HSTOP, hstop >> 3); | ||
3782 | v = i2c_r(sd, OV7670_REG_HREF); | ||
3783 | v = (v & 0xc0) | ((hstop & 0x7) << 3) | (hstart & 0x07); | ||
3784 | msleep(10); /* need to sleep between read and write to | ||
3785 | * same reg! */ | ||
3786 | i2c_w(sd, OV7670_REG_HREF, v); | ||
3787 | 3759 | ||
3788 | i2c_w(sd, OV7670_REG_VSTART, vstart >> 2); | ||
3789 | i2c_w(sd, OV7670_REG_VSTOP, vstop >> 2); | ||
3790 | v = i2c_r(sd, OV7670_REG_VREF); | ||
3791 | v = (v & 0xc0) | ((vstop & 0x3) << 2) | (vstart & 0x03); | ||
3792 | msleep(10); /* need to sleep between read and write to | ||
3793 | * same reg! */ | ||
3794 | i2c_w(sd, OV7670_REG_VREF, v); | ||
3795 | } else { | ||
3796 | i2c_w(sd, 0x17, hwsbase); | ||
3797 | i2c_w(sd, 0x18, hwebase + (sd->gspca_dev.width >> hwscale)); | ||
3798 | i2c_w(sd, 0x19, vwsbase); | ||
3799 | i2c_w(sd, 0x1a, vwebase + (sd->gspca_dev.height >> vwscale)); | ||
3800 | } | ||
3801 | return 0; | 3760 | return 0; |
3802 | } | 3761 | } |
3803 | 3762 | ||