diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 05:35:10 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-25 05:35:10 +0400 |
commit | 21fbd5809ad126b949206d78e0a0e07ec872ea11 (patch) | |
tree | a824045df99fc1f0690095a925cceb50207e332b /drivers/media/tuners/fc0012.c | |
parent | d9978ec5680059d727b39d6c706777c6973587f2 (diff) | |
parent | ed72d37a33fdf43dc47787fe220532cdec9da528 (diff) | |
download | linux-21fbd5809ad126b949206d78e0a0e07ec872ea11.tar.xz |
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:
- Some cleanups at V4L2 documentation
- new drivers: ts2020 frontend, ov9650 sensor, s5c73m3 sensor,
sh-mobile veu mem2mem driver, radio-ma901, davinci_vpfe staging
driver
- Lots of missing MAINTAINERS entries added
- several em28xx driver improvements, including its conversion to
videobuf2
- several fixups on drivers to make them to better comply with the API
- DVB core: add support for DVBv5 stats, allowing the implementation of
statistics for new standards like ISDB
- mb86a20s: add statistics to the driver
- lots of new board additions, cleanups, and driver improvements.
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (596 commits)
[media] media: Add 0x3009 USB PID to ttusb2 driver (fixed diff)
[media] rtl28xxu: Add USB IDs for Compro VideoMate U620F
[media] em28xx: add usb id for terratec h5 rev. 3
[media] media: rc: gpio-ir-recv: add support for device tree parsing
[media] mceusb: move check earlier to make smatch happy
[media] radio-si470x doc: add info about v4l2-ctl and sox+alsa
[media] staging: media: Remove unnecessary OOM messages
[media] sh_vou: Use vou_dev instead of vou_file wherever possible
[media] sh_vou: Use video_drvdata()
[media] drivers/media/platform/soc_camera/pxa_camera.c: use devm_ functions
[media] mt9t112: mt9t111 format set up differs from mt9t112
[media] sh-mobile-ceu-camera: fix SHARPNESS control default
Revert "[media] fc0011: Return early, if the frequency is already tuned"
[media] cx18/ivtv: fix regression: remove __init from a non-init function
[media] em28xx: fix analog streaming with USB bulk transfers
[media] stv0900: remove unnecessary null pointer check
[media] fc0011: Return early, if the frequency is already tuned
[media] fc0011: Add some sanity checks and cleanups
[media] fc0011: Fix xin value clamping
Revert "[media] [PATH,1/2] mxl5007 move reset to attach"
...
Diffstat (limited to 'drivers/media/tuners/fc0012.c')
-rw-r--r-- | drivers/media/tuners/fc0012.c | 113 |
1 files changed, 82 insertions, 31 deletions
diff --git a/drivers/media/tuners/fc0012.c b/drivers/media/tuners/fc0012.c index 308135abd54c..f4d0e797a6cc 100644 --- a/drivers/media/tuners/fc0012.c +++ b/drivers/media/tuners/fc0012.c @@ -25,11 +25,13 @@ static int fc0012_writereg(struct fc0012_priv *priv, u8 reg, u8 val) { u8 buf[2] = {reg, val}; struct i2c_msg msg = { - .addr = priv->addr, .flags = 0, .buf = buf, .len = 2 + .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 }; if (i2c_transfer(priv->i2c, &msg, 1) != 1) { - err("I2C write reg failed, reg: %02x, val: %02x", reg, val); + dev_err(&priv->i2c->dev, + "%s: I2C write reg failed, reg: %02x, val: %02x\n", + KBUILD_MODNAME, reg, val); return -EREMOTEIO; } return 0; @@ -38,12 +40,16 @@ static int fc0012_writereg(struct fc0012_priv *priv, u8 reg, u8 val) static int fc0012_readreg(struct fc0012_priv *priv, u8 reg, u8 *val) { struct i2c_msg msg[2] = { - { .addr = priv->addr, .flags = 0, .buf = ®, .len = 1 }, - { .addr = priv->addr, .flags = I2C_M_RD, .buf = val, .len = 1 }, + { .addr = priv->cfg->i2c_address, .flags = 0, + .buf = ®, .len = 1 }, + { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, + .buf = val, .len = 1 }, }; if (i2c_transfer(priv->i2c, msg, 2) != 2) { - err("I2C read reg failed, reg: %02x", reg); + dev_err(&priv->i2c->dev, + "%s: I2C read reg failed, reg: %02x\n", + KBUILD_MODNAME, reg); return -EREMOTEIO; } return 0; @@ -88,7 +94,7 @@ static int fc0012_init(struct dvb_frontend *fe) 0x04, /* reg. 0x15: Enable LNA COMPS */ }; - switch (priv->xtal_freq) { + switch (priv->cfg->xtal_freq) { case FC_XTAL_27_MHZ: case FC_XTAL_28_8_MHZ: reg[0x07] |= 0x20; @@ -98,9 +104,12 @@ static int fc0012_init(struct dvb_frontend *fe) break; } - if (priv->dual_master) + if (priv->cfg->dual_master) reg[0x0c] |= 0x02; + if (priv->cfg->loop_through) + reg[0x09] |= 0x01; + if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */ @@ -114,17 +123,12 @@ static int fc0012_init(struct dvb_frontend *fe) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ if (ret) - err("fc0012_writereg failed: %d", ret); + dev_err(&priv->i2c->dev, "%s: fc0012_writereg failed: %d\n", + KBUILD_MODNAME, ret); return ret; } -static int fc0012_sleep(struct dvb_frontend *fe) -{ - /* nothing to do here */ - return 0; -} - static int fc0012_set_params(struct dvb_frontend *fe) { struct fc0012_priv *priv = fe->tuner_priv; @@ -144,7 +148,7 @@ static int fc0012_set_params(struct dvb_frontend *fe) goto exit; } - switch (priv->xtal_freq) { + switch (priv->cfg->xtal_freq) { case FC_XTAL_27_MHZ: xtal_freq_khz_2 = 27000 / 2; break; @@ -256,7 +260,8 @@ static int fc0012_set_params(struct dvb_frontend *fe) break; } } else { - err("%s: modulation type not supported!", __func__); + dev_err(&priv->i2c->dev, "%s: modulation type not supported!\n", + KBUILD_MODNAME); return -EINVAL; } @@ -318,7 +323,8 @@ exit: if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ if (ret) - warn("%s: failed: %d", __func__, ret); + dev_warn(&priv->i2c->dev, "%s: %s failed: %d\n", + KBUILD_MODNAME, __func__, ret); return ret; } @@ -331,8 +337,7 @@ static int fc0012_get_frequency(struct dvb_frontend *fe, u32 *frequency) static int fc0012_get_if_frequency(struct dvb_frontend *fe, u32 *frequency) { - /* CHECK: always ? */ - *frequency = 0; + *frequency = 0; /* Zero-IF */ return 0; } @@ -408,7 +413,8 @@ err: fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */ exit: if (ret) - warn("%s: failed: %d", __func__, ret); + dev_warn(&priv->i2c->dev, "%s: %s failed: %d\n", + KBUILD_MODNAME, __func__, ret); return ret; } @@ -424,7 +430,6 @@ static const struct dvb_tuner_ops fc0012_tuner_ops = { .release = fc0012_release, .init = fc0012_init, - .sleep = fc0012_sleep, .set_params = fc0012_set_params, @@ -436,27 +441,73 @@ static const struct dvb_tuner_ops fc0012_tuner_ops = { }; struct dvb_frontend *fc0012_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, u8 i2c_address, int dual_master, - enum fc001x_xtal_freq xtal_freq) + struct i2c_adapter *i2c, const struct fc0012_config *cfg) { - struct fc0012_priv *priv = NULL; + struct fc0012_priv *priv; + int ret; + u8 chip_id; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); priv = kzalloc(sizeof(struct fc0012_priv), GFP_KERNEL); - if (priv == NULL) - return NULL; + if (!priv) { + ret = -ENOMEM; + dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME); + goto err; + } + priv->cfg = cfg; priv->i2c = i2c; - priv->dual_master = dual_master; - priv->addr = i2c_address; - priv->xtal_freq = xtal_freq; - info("Fitipower FC0012 successfully attached."); + /* check if the tuner is there */ + ret = fc0012_readreg(priv, 0x00, &chip_id); + if (ret < 0) + goto err; - fe->tuner_priv = priv; + dev_dbg(&i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id); + + switch (chip_id) { + case 0xa1: + break; + default: + ret = -ENODEV; + goto err; + } + + dev_info(&i2c->dev, "%s: Fitipower FC0012 successfully identified\n", + KBUILD_MODNAME); + + if (priv->cfg->loop_through) { + ret = fc0012_writereg(priv, 0x09, 0x6f); + if (ret < 0) + goto err; + } + + /* + * TODO: Clock out en or div? + * For dual tuner configuration clearing bit [0] is required. + */ + if (priv->cfg->clock_out) { + ret = fc0012_writereg(priv, 0x0b, 0x82); + if (ret < 0) + goto err; + } + fe->tuner_priv = priv; memcpy(&fe->ops.tuner_ops, &fc0012_tuner_ops, sizeof(struct dvb_tuner_ops)); +err: + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + if (ret) { + dev_dbg(&i2c->dev, "%s: failed: %d\n", __func__, ret); + kfree(priv); + return NULL; + } + return fe; } EXPORT_SYMBOL(fc0012_attach); |