diff options
author | Hans Verkuil <hans.verkuil@cisco.com> | 2013-03-25 08:35:17 (GMT) |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-03-25 11:25:07 (GMT) |
commit | dcae5dacbce518513abf7776cb450b7bd95d722b (patch) | |
tree | 2e0d8d5376ca5655b38eae279b6112efdca7cc1d /drivers/staging/media/solo6x10/tw28.c | |
parent | c535cc6c714bd21b3afad35baa926b3b9eb51361 (diff) | |
download | linux-fsl-qoriq-dcae5dacbce518513abf7776cb450b7bd95d722b.tar.xz |
[media] solo6x10: sync to latest code from Bluecherry's git repo
Synced to commit e9815ac5503ae60cfbf6ff8037035de8f62e2846 from
branch next in git repository https://github.com/bluecherrydvr/solo6x10.git
Only removed some code under #if LINUX_VERSION_CODE < some-kernel-version,
renamed the driver back to solo6x10 from solo6x10-edge, removed the
unnecessary compat.h header and kept the slab.h includes.
Otherwise the code is identical.
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Ismael Luceno <ismael.luceno@corp.bluecherry.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/staging/media/solo6x10/tw28.c')
-rw-r--r-- | drivers/staging/media/solo6x10/tw28.c | 171 |
1 files changed, 99 insertions, 72 deletions
diff --git a/drivers/staging/media/solo6x10/tw28.c b/drivers/staging/media/solo6x10/tw28.c index db56b42..365ab10 100644 --- a/drivers/staging/media/solo6x10/tw28.c +++ b/drivers/staging/media/solo6x10/tw28.c @@ -1,6 +1,11 @@ /* - * Copyright (C) 2010 Bluecherry, LLC www.bluecherrydvr.com - * Copyright (C) 2010 Ben Collins <bcollins@bluecherry.net> + * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> + * + * Original author: + * Ben Collins <bcollins@ubuntu.com> + * + * Additional work by: + * John Brooks <john.brooks@bluecherry.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,12 +23,12 @@ */ #include <linux/kernel.h> +#include <linux/delay.h> + #include "solo6x10.h" #include "tw28.h" -/* XXX: Some of these values are masked into an 8-bit regs, and shifted - * around for other 8-bit regs. What are the magic bits in these values? */ -#define DEFAULT_HDELAY_NTSC (32 - 4) +#define DEFAULT_HDELAY_NTSC (32 - 8) #define DEFAULT_HACTIVE_NTSC (720 + 16) #define DEFAULT_VDELAY_NTSC (7 - 2) #define DEFAULT_VACTIVE_NTSC (240 + 4) @@ -33,15 +38,16 @@ #define DEFAULT_VDELAY_PAL (6) #define DEFAULT_VACTIVE_PAL (312-DEFAULT_VDELAY_PAL) -static u8 tbl_tw2864_template[] = { - 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ - 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ - 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x20 */ - 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, - 0x00, 0x00, 0x80, 0x10, 0x80, 0x80, 0x00, 0x02, /* 0x30 */ - 0x12, 0xf5, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, + +static const u8 tbl_tw2864_ntsc_template[] = { + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ + 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ + 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x20 */ + 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x30 */ + 0x12, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ @@ -61,14 +67,49 @@ static u8 tbl_tw2864_template[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00, 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */ - 0x64, 0xa8, 0xec, 0xd1, 0x0f, 0x11, 0x11, 0x81, - 0x10, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ + 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81, + 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, 0x83, 0xb5, 0x09, 0x78, 0x85, 0x00, 0x01, 0x20, /* 0xf0 */ 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00, }; -static u8 tbl_tw2865_ntsc_template[] = { +static const u8 tbl_tw2864_pal_template[] = { + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */ + 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */ + 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x20 */ + 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, + 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x30 */ + 0x18, 0xf5, 0x0c, 0xd0, 0x00, 0x00, 0x01, 0x7f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA3, 0x00, + 0x00, 0x02, 0x00, 0xcc, 0x00, 0x80, 0x44, 0x50, /* 0x80 */ + 0x22, 0x01, 0xd8, 0xbc, 0xb8, 0x44, 0x38, 0x00, + 0x00, 0x78, 0x72, 0x3e, 0x14, 0xa5, 0xe4, 0x05, /* 0x90 */ + 0x00, 0x28, 0x44, 0x44, 0xa0, 0x90, 0x5a, 0x01, + 0x0a, 0x0a, 0x0a, 0x0a, 0x1a, 0x1a, 0x1a, 0x1a, /* 0xa0 */ + 0x00, 0x00, 0x00, 0xf0, 0xf0, 0xf0, 0xf0, 0x44, + 0x44, 0x0a, 0x00, 0xff, 0xef, 0xef, 0xef, 0xef, /* 0xb0 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ + 0x00, 0x00, 0x55, 0x00, 0xb1, 0xe4, 0x40, 0x00, + 0x77, 0x77, 0x01, 0x13, 0x57, 0x9b, 0xdf, 0x20, /* 0xd0 */ + 0x64, 0xa8, 0xec, 0xc1, 0x0f, 0x11, 0x11, 0x81, + 0x00, 0xe0, 0xbb, 0xbb, 0x00, 0x11, 0x00, 0x00, /* 0xe0 */ + 0x11, 0x00, 0x00, 0x11, 0x00, 0x00, 0x11, 0x00, + 0x83, 0xb5, 0x09, 0x00, 0xa0, 0x00, 0x01, 0x20, /* 0xf0 */ + 0x64, 0x11, 0x40, 0xaf, 0xff, 0x00, 0x00, 0x00, +}; + +static const u8 tbl_tw2865_ntsc_template[] = { 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x00 */ 0x12, 0xff, 0x09, 0xd0, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x02, /* 0x10 */ @@ -103,7 +144,7 @@ static u8 tbl_tw2865_ntsc_template[] = { 0x64, 0x51, 0x40, 0xaf, 0xFF, 0xF0, 0x00, 0xC0, }; -static u8 tbl_tw2865_pal_template[] = { +static const u8 tbl_tw2865_pal_template[] = { 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x00 */ 0x11, 0xff, 0x01, 0xc3, 0x00, 0x00, 0x01, 0x7f, 0x00, 0xf0, 0x70, 0x30, 0x80, 0x80, 0x00, 0x12, /* 0x10 */ @@ -180,8 +221,8 @@ static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off, msleep_interruptible(1); } -/* printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", - addr, off, val); */ +/* printk("solo6x10/tw28: Error writing register: %02x->%02x [%02x]\n", */ +/* addr, off, val); */ } static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr) @@ -216,16 +257,17 @@ static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr) for (i = 0; i < 0xff; i++) { /* Skip read only registers */ - if (i >= 0xb8 && i <= 0xc1) - continue; - if ((i & ~0x30) == 0x00 || - (i & ~0x30) == 0x0c || - (i & ~0x30) == 0x0d) - continue; - if (i >= 0xc4 && i <= 0xc7) + switch (i) { + case 0xb8 ... 0xc1: + case 0xc4 ... 0xc7: + case 0xfd: continue; - if (i == 0xfd) + } + switch (i & ~0x30) { + case 0x00: + case 0x0c ... 0x0d: continue; + } tw_write_and_verify(solo_dev, dev_addr, i, tbl_tw2865_common[i]); @@ -236,11 +278,15 @@ static int tw2865_setup(struct solo_dev *solo_dev, u8 dev_addr) static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr) { - u8 tbl_tw2864_common[sizeof(tbl_tw2864_template)]; + u8 tbl_tw2864_common[256]; int i; - memcpy(tbl_tw2864_common, tbl_tw2864_template, - sizeof(tbl_tw2864_common)); + if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) + memcpy(tbl_tw2864_common, tbl_tw2864_pal_template, + sizeof(tbl_tw2864_common)); + else + memcpy(tbl_tw2864_common, tbl_tw2864_ntsc_template, + sizeof(tbl_tw2864_common)); if (solo_dev->tw2865 == 0) { /* IRQ Mode */ @@ -285,33 +331,19 @@ static int tw2864_setup(struct solo_dev *solo_dev, u8 dev_addr) } } - /* NTSC or PAL */ - if (solo_dev->video_type == SOLO_VO_FMT_TYPE_PAL) { - for (i = 0; i < 4; i++) { - tbl_tw2864_common[0x07 | (i << 4)] |= 0x10; - tbl_tw2864_common[0x08 | (i << 4)] |= 0x06; - tbl_tw2864_common[0x0a | (i << 4)] |= 0x08; - tbl_tw2864_common[0x0b | (i << 4)] |= 0x13; - tbl_tw2864_common[0x0e | (i << 4)] |= 0x01; - } - tbl_tw2864_common[0x9d] = 0x90; - tbl_tw2864_common[0xf3] = 0x00; - tbl_tw2864_common[0xf4] = 0xa0; - } - for (i = 0; i < 0xff; i++) { /* Skip read only registers */ - if (i >= 0xb8 && i <= 0xc1) - continue; - if ((i & ~0x30) == 0x00 || - (i & ~0x30) == 0x0c || - (i & ~0x30) == 0x0d) - continue; - if (i == 0x74 || i == 0x77 || i == 0x78 || - i == 0x79 || i == 0x7a) + switch (i) { + case 0xb8 ... 0xc1: + case 0xfd: continue; - if (i == 0xfd) + } + switch (i & ~0x30) { + case 0x00: + case 0x0c: + case 0x0d: continue; + } tw_write_and_verify(solo_dev, dev_addr, i, tbl_tw2864_common[i]); @@ -544,8 +576,8 @@ int solo_tw28_init(struct solo_dev *solo_dev) int i; u8 value; - /* Detect techwell chip type */ - for (i = 0; i < TW_NUM_CHIP; i++) { + /* Detect techwell chip type(s) */ + for (i = 0; i < solo_dev->nr_chans / 4; i++) { value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, TW_CHIP_OFFSET_ADDR(i), 0xFF); @@ -560,7 +592,8 @@ int solo_tw28_init(struct solo_dev *solo_dev) break; default: value = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, - TW_CHIP_OFFSET_ADDR(i), 0x59); + TW_CHIP_OFFSET_ADDR(i), + 0x59); if ((value >> 3) == 0x04) { solo_dev->tw2815 |= 1 << i; solo_dev->tw28_cnt++; @@ -568,8 +601,11 @@ int solo_tw28_init(struct solo_dev *solo_dev) } } - if (!solo_dev->tw28_cnt) + if (solo_dev->tw28_cnt != (solo_dev->nr_chans >> 2)) { + dev_err(&solo_dev->pdev->dev, + "Could not initialize any techwell chips\n"); return -EINVAL; + } saa7128_setup(solo_dev); @@ -582,17 +618,6 @@ int solo_tw28_init(struct solo_dev *solo_dev) tw2815_setup(solo_dev, TW_CHIP_OFFSET_ADDR(i)); } - dev_info(&solo_dev->pdev->dev, "Initialized %d tw28xx chip%s:", - solo_dev->tw28_cnt, solo_dev->tw28_cnt == 1 ? "" : "s"); - - if (solo_dev->tw2865) - printk(" tw2865[%d]", hweight32(solo_dev->tw2865)); - if (solo_dev->tw2864) - printk(" tw2864[%d]", hweight32(solo_dev->tw2864)); - if (solo_dev->tw2815) - printk(" tw2815[%d]", hweight32(solo_dev->tw2815)); - printk("\n"); - return 0; } @@ -610,7 +635,7 @@ int tw28_get_video_status(struct solo_dev *solo_dev, u8 ch) chip_num = ch / 4; ch %= 4; - val = tw_readbyte(solo_dev, chip_num, TW286X_AV_STAT_ADDR, + val = tw_readbyte(solo_dev, chip_num, TW286x_AV_STAT_ADDR, TW_AV_STAT_ADDR) & 0x0f; return val & (1 << ch) ? 1 : 0; @@ -626,7 +651,7 @@ u16 tw28_get_audio_status(struct solo_dev *solo_dev) int i; for (i = 0; i < solo_dev->tw28_cnt; i++) { - val = (tw_readbyte(solo_dev, i, TW286X_AV_STAT_ADDR, + val = (tw_readbyte(solo_dev, i, TW286x_AV_STAT_ADDR, TW_AV_STAT_ADDR) & 0xf0) >> 4; status |= val << (i * 4); } @@ -635,7 +660,8 @@ u16 tw28_get_audio_status(struct solo_dev *solo_dev) } #endif -int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val) +int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, + s32 val) { char sval; u8 chip_num; @@ -676,6 +702,7 @@ int tw28_set_ctrl_val(struct solo_dev *solo_dev, u32 ctrl, u8 ch, s32 val) break; case V4L2_CID_SATURATION: + /* 286x chips have a U and V component for saturation */ if (is_tw286x(solo_dev, chip_num)) { solo_i2c_writebyte(solo_dev, SOLO_I2C_TW, TW_CHIP_OFFSET_ADDR(chip_num), |