summaryrefslogtreecommitdiffstats
path: root/drivers/media/tuners/e4000.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 20:55:59 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2013-09-05 20:55:59 +0200
commit27c053aa8d18d1fa7b83041e36bad20bcdf55514 (patch)
treec59dce17a248dd8f4757eca3823032334c626dcd /drivers/media/tuners/e4000.c
parentMerge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux (diff)
parent[media] cx88: Fix regression: CX88_AUDIO_WM8775 can't be 0 (diff)
downloadlinux-27c053aa8d18d1fa7b83041e36bad20bcdf55514.tar.xz
linux-27c053aa8d18d1fa7b83041e36bad20bcdf55514.zip
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media updates from Mauro Carvalho Chehab: "This series contains: - Exynos s5p-mfc driver got support for VP8 encoder - Some SoC drivers gained support for asynchronous registration (needed for DT) - The RC subsystem gained support for RC activity LED; - New drivers added: a video decoder(adv7842), a video encoder (adv7511), a new GSPCA driver (stk1135) and support for Renesas R-Car (vsp1) - the first SDR kernel driver: mirics msi3101. Due to some troubles with the driver, and because the API is still under discussion, it will be merged at staging for 3.12. Need to rework on it - usual new boards additions, fixes, cleanups and driver improvements" * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (242 commits) [media] cx88: Fix regression: CX88_AUDIO_WM8775 can't be 0 [media] exynos4-is: Fix entity unregistration on error path [media] exynos-gsc: Register v4l2 device [media] exynos4-is: Fix fimc-lite bayer formats [media] em28xx: fix assignment of the eeprom data [media] hdpvr: fix iteration over uninitialized lists in hdpvr_probe() [media] usbtv: Throw corrupted frames away [media] usbtv: Fix deinterlacing [media] v4l2: added missing mutex.h include to v4l2-ctrls.h [media] DocBook: upgrade media_api DocBook version to 4.2 [media] ml86v7667: fix compile warning: 'ret' set but not used [media] s5p-g2d: Fix registration failure [media] media: coda: Fix DT driver data pointer for i.MX27 [media] s5p-mfc: Fix input/output format reporting [media] v4l: vsp1: Fix mutex double lock at streamon time [media] v4l: vsp1: Add support for RT clock [media] v4l: vsp1: Initialize media device bus_info field [media] davinci: vpif_capture: fix error return code in vpif_probe() [media] davinci: vpif_display: fix error return code in vpif_probe() [media] MAINTAINERS: add entries for adv7511 and adv7842 ...
Diffstat (limited to 'drivers/media/tuners/e4000.c')
-rw-r--r--drivers/media/tuners/e4000.c82
1 files changed, 60 insertions, 22 deletions
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
index 1b33ed368abe..ad9309da4a91 100644
--- a/drivers/media/tuners/e4000.c
+++ b/drivers/media/tuners/e4000.c
@@ -41,8 +41,9 @@ static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
if (ret == 1) {
ret = 0;
} else {
- dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
- "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+ dev_warn(&priv->i2c->dev,
+ "%s: i2c wr failed=%d reg=%02x len=%d\n",
+ KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
return ret;
@@ -72,8 +73,9 @@ static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
memcpy(val, buf, len);
ret = 0;
} else {
- dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
- "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+ dev_warn(&priv->i2c->dev,
+ "%s: i2c rd failed=%d reg=%02x len=%d\n",
+ KBUILD_MODNAME, ret, reg, len);
ret = -EREMOTEIO;
}
@@ -140,14 +142,12 @@ static int e4000_init(struct dvb_frontend *fe)
if (ret < 0)
goto err;
- /*
- * TODO: Implement DC offset control correctly.
- * DC offsets has quite much effect for received signal quality in case
- * of direct conversion tuners (Zero-IF). Surely we will now lose few
- * decimals or even decibels from SNR...
- */
/* DC offset control */
- ret = e4000_wr_reg(priv, 0x2d, 0x0c);
+ ret = e4000_wr_reg(priv, 0x2d, 0x1f);
+ if (ret < 0)
+ goto err;
+
+ ret = e4000_wr_regs(priv, 0x70, "\x01\x01", 2);
if (ret < 0)
goto err;
@@ -203,12 +203,13 @@ static int e4000_set_params(struct dvb_frontend *fe)
struct e4000_priv *priv = fe->tuner_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, i, sigma_delta;
- unsigned int f_VCO;
- u8 buf[5];
+ unsigned int f_vco;
+ u8 buf[5], i_data[4], q_data[4];
- dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
- "bandwidth_hz=%d\n", __func__,
- c->delivery_system, c->frequency, c->bandwidth_hz);
+ dev_dbg(&priv->i2c->dev,
+ "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
+ __func__, c->delivery_system, c->frequency,
+ c->bandwidth_hz);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@@ -228,19 +229,19 @@ static int e4000_set_params(struct dvb_frontend *fe)
goto err;
/*
- * Note: Currently f_VCO overflows when c->frequency is 1 073 741 824 Hz
+ * Note: Currently f_vco overflows when c->frequency is 1 073 741 824 Hz
* or more.
*/
- f_VCO = c->frequency * e4000_pll_lut[i].mul;
- sigma_delta = 0x10000UL * (f_VCO % priv->cfg->clock) / priv->cfg->clock;
- buf[0] = f_VCO / priv->cfg->clock;
+ f_vco = c->frequency * e4000_pll_lut[i].mul;
+ sigma_delta = 0x10000UL * (f_vco % priv->cfg->clock) / priv->cfg->clock;
+ buf[0] = f_vco / priv->cfg->clock;
buf[1] = (sigma_delta >> 0) & 0xff;
buf[2] = (sigma_delta >> 8) & 0xff;
buf[3] = 0x00;
buf[4] = e4000_pll_lut[i].div;
- dev_dbg(&priv->i2c->dev, "%s: f_VCO=%u pll div=%d sigma_delta=%04x\n",
- __func__, f_VCO, buf[0], sigma_delta);
+ dev_dbg(&priv->i2c->dev, "%s: f_vco=%u pll div=%d sigma_delta=%04x\n",
+ __func__, f_vco, buf[0], sigma_delta);
ret = e4000_wr_regs(priv, 0x09, buf, 5);
if (ret < 0)
@@ -292,6 +293,43 @@ static int e4000_set_params(struct dvb_frontend *fe)
if (ret < 0)
goto err;
+ /* DC offset */
+ for (i = 0; i < 4; i++) {
+ if (i == 0)
+ ret = e4000_wr_regs(priv, 0x15, "\x00\x7e\x24", 3);
+ else if (i == 1)
+ ret = e4000_wr_regs(priv, 0x15, "\x00\x7f", 2);
+ else if (i == 2)
+ ret = e4000_wr_regs(priv, 0x15, "\x01", 1);
+ else
+ ret = e4000_wr_regs(priv, 0x16, "\x7e", 1);
+
+ if (ret < 0)
+ goto err;
+
+ ret = e4000_wr_reg(priv, 0x29, 0x01);
+ if (ret < 0)
+ goto err;
+
+ ret = e4000_rd_regs(priv, 0x2a, buf, 3);
+ if (ret < 0)
+ goto err;
+
+ i_data[i] = (((buf[2] >> 0) & 0x3) << 6) | (buf[0] & 0x3f);
+ q_data[i] = (((buf[2] >> 4) & 0x3) << 6) | (buf[1] & 0x3f);
+ }
+
+ swap(q_data[2], q_data[3]);
+ swap(i_data[2], i_data[3]);
+
+ ret = e4000_wr_regs(priv, 0x50, q_data, 4);
+ if (ret < 0)
+ goto err;
+
+ ret = e4000_wr_regs(priv, 0x60, i_data, 4);
+ if (ret < 0)
+ goto err;
+
/* gain control auto */
ret = e4000_wr_reg(priv, 0x1a, 0x17);
if (ret < 0)