diff options
Diffstat (limited to 'drivers/media/dvb/frontends')
21 files changed, 1453 insertions, 694 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 96b27016670e..ef3e43a03199 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -497,7 +497,7 @@ comment "ISDB-T (terrestrial) frontends" depends on DVB_CORE config DVB_S921 - tristate "Sharp S921 tuner" + tristate "Sharp S921 frontend" depends on DVB_CORE && I2C default m if DVB_FE_CUSTOMISE help @@ -512,6 +512,14 @@ config DVB_DIB8000 A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator. Say Y when you want to support this frontend. +config DVB_MB86A20S + tristate "Fujitsu mb86a20s" + depends on DVB_CORE && I2C + default m if DVB_FE_CUSTOMISE + help + A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator. + Say Y when you want to support this frontend. + comment "Digital terrestrial only tuners/PLL" depends on DVB_CORE diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile index 9a31985c0dfb..b1d9525aa7e3 100644 --- a/drivers/media/dvb/frontends/Makefile +++ b/drivers/media/dvb/frontends/Makefile @@ -5,7 +5,6 @@ EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ EXTRA_CFLAGS += -Idrivers/media/common/tuners/ -s921-objs := s921_module.o s921_core.o stb0899-objs = stb0899_drv.o stb0899_algo.o stv0900-objs = stv0900_core.o stv0900_sw.o au8522-objs = au8522_dig.o au8522_decoder.o @@ -82,4 +81,5 @@ obj-$(CONFIG_DVB_ISL6423) += isl6423.o obj-$(CONFIG_DVB_EC100) += ec100.o obj-$(CONFIG_DVB_DS3000) += ds3000.o obj-$(CONFIG_DVB_MB86A16) += mb86a16.o +obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o obj-$(CONFIG_DVB_IX2505V) += ix2505v.o diff --git a/drivers/media/dvb/frontends/af9013.c b/drivers/media/dvb/frontends/af9013.c index e2a95c07bab4..ce222055526d 100644 --- a/drivers/media/dvb/frontends/af9013.c +++ b/drivers/media/dvb/frontends/af9013.c @@ -964,7 +964,7 @@ error: static int af9013_update_signal_strength(struct dvb_frontend *fe) { struct af9013_state *state = fe->demodulator_priv; - int ret; + int ret = 0; u8 rf_gain, if_gain; int signal_strength; diff --git a/drivers/media/dvb/frontends/atbm8830.c b/drivers/media/dvb/frontends/atbm8830.c index 43aac2f85c2e..1539ea1f81ac 100644 --- a/drivers/media/dvb/frontends/atbm8830.c +++ b/drivers/media/dvb/frontends/atbm8830.c @@ -50,8 +50,7 @@ static int atbm8830_write_reg(struct atbm_state *priv, u16 reg, u8 data) msg2.addr = dev_addr; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n", - __func__, reg, data); + dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, data); ret = i2c_transfer(priv->i2c, &msg1, 1); if (ret != 1) @@ -77,8 +76,7 @@ static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data) ret = i2c_transfer(priv->i2c, &msg1, 1); if (ret != 1) { - dprintk(KERN_DEBUG "%s: error reg=0x%04x, ret=%i\n", - __func__, reg, ret); + dprintk("%s: error reg=0x%04x, ret=%i\n", __func__, reg, ret); return -EIO; } @@ -88,7 +86,7 @@ static int atbm8830_read_reg(struct atbm_state *priv, u16 reg, u8 *p_data) *p_data = buf2[0]; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%04X, data=0x%02X\n", + dprintk("%s: reg=0x%04X, data=0x%02X\n", __func__, reg, buf2[0]); return 0; diff --git a/drivers/media/dvb/frontends/au8522_decoder.c b/drivers/media/dvb/frontends/au8522_decoder.c index 6d9c5943eb3d..b537891a4cc9 100644 --- a/drivers/media/dvb/frontends/au8522_decoder.c +++ b/drivers/media/dvb/frontends/au8522_decoder.c @@ -278,10 +278,18 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode) AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS); au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, - AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); - au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, - AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); + if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 || + input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) { + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, + AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, + AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO); + } else { + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH, + AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS); + au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH, + AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS); + } au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH, AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS); au8522_writereg(state, AU8522_TVDEC_UV_SEP_THR_REG06FH, @@ -347,9 +355,11 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state) au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); + /* PGA in automatic mode */ au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); - au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); - au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); + + /* Enable clamping control */ + au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1); @@ -366,14 +376,14 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state) au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H, AU8522_MODULE_CLOCK_CONTROL_REG0A3H_CVBS); - /* It's not clear why they turn off the PGA before enabling the clamp - control, but the Windows trace does it so we will too... */ + /* It's not clear why we have to have the PGA in automatic mode while + enabling clamp control, but it's what Windows does */ au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); /* Enable clamping control */ au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x0e); - /* Turn on the PGA */ + /* Disable automatic PGA (since the CVBS is coming from the tuner) */ au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10); /* Set input mode to CVBS on channel 4 with SIF audio input enabled */ @@ -396,7 +406,10 @@ static void au8522_setup_svideo_mode(struct au8522_state *state) au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13); - /* Disable clamping control (required for S-video) */ + /* PGA in automatic mode */ + au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00); + + /* Enable clamping control */ au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00); setup_decoder_defaults(state, @@ -410,29 +423,15 @@ static void au8522_setup_svideo_mode(struct au8522_state *state) static void disable_audio_input(struct au8522_state *state) { - /* This can probably be optimized */ au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x00); au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x00); au8522_writereg(state, AU8522_AUDIO_VOLUME_REG0F4H, 0x00); - au8522_writereg(state, AU8522_I2C_CONTROL_REG1_REG091H, 0x80); - au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84); - - au8522_writereg(state, AU8522_ENA_USB_REG101H, 0x00); - au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F); - au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F); - au8522_writereg(state, AU8522_REG0F9H, AU8522_REG0F9H_AUDIO); - au8522_writereg(state, AU8522_AUDIO_MODE_REG0F1H, 0x40); - - au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x11); - msleep(5); - au8522_writereg(state, AU8522_GPIO_DATA_REG0E2H, 0x00); au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_1_REG0A5H, 0x04); - au8522_writereg(state, AU8522_AUDIOFREQ_REG606H, 0x03); au8522_writereg(state, AU8522_I2S_CTRL_2_REG112H, 0x02); au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, - AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS); + AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_SVIDEO); } /* 0=disable, 1=SIF */ @@ -622,7 +621,7 @@ static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc) return v4l2_ctrl_query_fill(qc, 0, 255, 1, AU8522_TVDEC_CONTRAST_REG00BH_CVBS); case V4L2_CID_BRIGHTNESS: - return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); + return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109); case V4L2_CID_SATURATION: return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128); case V4L2_CID_HUE: diff --git a/drivers/media/dvb/frontends/au8522_priv.h b/drivers/media/dvb/frontends/au8522_priv.h index 609cf04bc312..751e17d692a9 100644 --- a/drivers/media/dvb/frontends/au8522_priv.h +++ b/drivers/media/dvb/frontends/au8522_priv.h @@ -397,7 +397,9 @@ void au8522_release_state(struct au8522_state *state); #define AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS 0x0A #define AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS 0x32 #define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_CVBS 0x34 +#define AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO 0x2a #define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_CVBS 0x05 +#define AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH_SVIDEO 0x15 #define AU8522_TVDEC_COMB_DCDIF_THR3_REG06EH_CVBS 0x6E #define AU8522_TVDEC_UV_SEP_THR_REG06FH_CVBS 0x0F #define AU8522_TVDEC_COMB_DC_THR1_NTSC_REG070H_CVBS 0x80 diff --git a/drivers/media/dvb/frontends/dib7000m.c b/drivers/media/dvb/frontends/dib7000m.c index 0f09fd31cb29..c7f5ccf54aa5 100644 --- a/drivers/media/dvb/frontends/dib7000m.c +++ b/drivers/media/dvb/frontends/dib7000m.c @@ -805,7 +805,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte value = 0; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (0 << 7); break; - case /* 4K MODE */ 255: value |= (2 << 7); break; + case TRANSMISSION_MODE_4K: value |= (2 << 7); break; default: case TRANSMISSION_MODE_8K: value |= (1 << 7); break; } @@ -866,7 +866,7 @@ static void dib7000m_set_channel(struct dib7000m_state *state, struct dvb_fronte /* P_dvsy_sync_wait */ switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_8K: value = 256; break; - case /* 4K MODE */ 255: value = 128; break; + case TRANSMISSION_MODE_4K: value = 128; break; case TRANSMISSION_MODE_2K: default: value = 64; break; } @@ -1020,7 +1020,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet value = (6 << 8) | 0x80; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (7 << 12); break; - case /* 4K MODE */ 255: value |= (8 << 12); break; + case TRANSMISSION_MODE_4K: value |= (8 << 12); break; default: case TRANSMISSION_MODE_8K: value |= (9 << 12); break; } @@ -1030,7 +1030,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet value = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= 0x6; break; - case /* 4K MODE */ 255: value |= 0x7; break; + case TRANSMISSION_MODE_4K: value |= 0x7; break; default: case TRANSMISSION_MODE_8K: value |= 0x8; break; } @@ -1040,7 +1040,7 @@ static int dib7000m_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet value = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= 0x6; break; - case /* 4K MODE */ 255: value |= 0x7; break; + case TRANSMISSION_MODE_4K: value |= 0x7; break; default: case TRANSMISSION_MODE_8K: value |= 0x8; break; } diff --git a/drivers/media/dvb/frontends/dib7000p.c b/drivers/media/dvb/frontends/dib7000p.c index 3aed0d433921..6aa02cb80733 100644 --- a/drivers/media/dvb/frontends/dib7000p.c +++ b/drivers/media/dvb/frontends/dib7000p.c @@ -717,7 +717,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte value = 0; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: value |= (0 << 7); break; - case /* 4K MODE */ 255: value |= (2 << 7); break; + case TRANSMISSION_MODE_4K: value |= (2 << 7); break; default: case TRANSMISSION_MODE_8K: value |= (1 << 7); break; } @@ -770,7 +770,7 @@ static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_fronte /* P_dvsy_sync_wait */ switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_8K: value = 256; break; - case /* 4K MODE */ 255: value = 128; break; + case TRANSMISSION_MODE_4K: value = 128; break; case TRANSMISSION_MODE_2K: default: value = 64; break; } @@ -994,7 +994,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet tmp = (6 << 8) | 0x80; switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break; - case /* 4K MODE */ 255: tmp |= (8 << 12); break; + case TRANSMISSION_MODE_4K: tmp |= (8 << 12); break; default: case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break; } @@ -1004,7 +1004,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet tmp = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tmp |= 0x6; break; - case /* 4K MODE */ 255: tmp |= 0x7; break; + case TRANSMISSION_MODE_4K: tmp |= 0x7; break; default: case TRANSMISSION_MODE_8K: tmp |= 0x8; break; } @@ -1014,7 +1014,7 @@ static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_paramet tmp = (0 << 4); switch (ch->u.ofdm.transmission_mode) { case TRANSMISSION_MODE_2K: tmp |= 0x6; break; - case /* 4K MODE */ 255: tmp |= 0x7; break; + case TRANSMISSION_MODE_4K: tmp |= 0x7; break; default: case TRANSMISSION_MODE_8K: tmp |= 0x8; break; } diff --git a/drivers/media/dvb/frontends/ix2505v.c b/drivers/media/dvb/frontends/ix2505v.c index 55f2eba7bc96..6360c681ded9 100644 --- a/drivers/media/dvb/frontends/ix2505v.c +++ b/drivers/media/dvb/frontends/ix2505v.c @@ -72,7 +72,7 @@ static int ix2505v_read_status_reg(struct ix2505v_state *state) ret = i2c_transfer(state->i2c, msg, 1); deb_i2c("Read %s ", __func__); - return (ret = 1) ? (int) b2[0] : -1; + return (ret == 1) ? (int) b2[0] : -1; } static int ix2505v_write(struct ix2505v_state *state, u8 buf[], u8 count) diff --git a/drivers/media/dvb/frontends/lgs8gxx.c b/drivers/media/dvb/frontends/lgs8gxx.c index 0fcddc4569d2..1172b54689f8 100644 --- a/drivers/media/dvb/frontends/lgs8gxx.c +++ b/drivers/media/dvb/frontends/lgs8gxx.c @@ -60,13 +60,12 @@ static int lgs8gxx_write_reg(struct lgs8gxx_state *priv, u8 reg, u8 data) msg.addr += 0x02; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", - __func__, reg, data); + dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, data); ret = i2c_transfer(priv->i2c, &msg, 1); if (ret != 1) - dprintk(KERN_DEBUG "%s: error reg=0x%x, data=0x%x, ret=%i\n", + dprintk("%s: error reg=0x%x, data=0x%x, ret=%i\n", __func__, reg, data, ret); return (ret != 1) ? -1 : 0; @@ -91,15 +90,13 @@ static int lgs8gxx_read_reg(struct lgs8gxx_state *priv, u8 reg, u8 *p_data) ret = i2c_transfer(priv->i2c, msg, 2); if (ret != 2) { - dprintk(KERN_DEBUG "%s: error reg=0x%x, ret=%i\n", - __func__, reg, ret); + dprintk("%s: error reg=0x%x, ret=%i\n", __func__, reg, ret); return -1; } *p_data = b1[0]; if (debug >= 2) - printk(KERN_DEBUG "%s: reg=0x%02X, data=0x%02X\n", - __func__, reg, b1[0]); + dprintk("%s: reg=0x%02X, data=0x%02X\n", __func__, reg, b1[0]); return 0; } diff --git a/drivers/media/dvb/frontends/mb86a20s.c b/drivers/media/dvb/frontends/mb86a20s.c new file mode 100644 index 000000000000..d3ad3e75a35a --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a20s.c @@ -0,0 +1,615 @@ +/* + * Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver + * + * Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com> + * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com> + * + * FIXME: Need to port to DVB v5.2 API + * + * 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 the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/kernel.h> +#include <asm/div64.h> + +#include "dvb_frontend.h" +#include "mb86a20s.h" + +static int debug = 1; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +#define rc(args...) do { \ + printk(KERN_ERR "mb86a20s: " args); \ +} while (0) + +#define dprintk(args...) \ + do { \ + if (debug) { \ + printk(KERN_DEBUG "mb86a20s: %s: ", __func__); \ + printk(args); \ + } \ + } while (0) + +struct mb86a20s_state { + struct i2c_adapter *i2c; + const struct mb86a20s_config *config; + + struct dvb_frontend frontend; +}; + +struct regdata { + u8 reg; + u8 data; +}; + +/* + * Initialization sequence: Use whatevere default values that PV SBTVD + * does on its initialisation, obtained via USB snoop + */ +static struct regdata mb86a20s_init[] = { + { 0x70, 0x0f }, + { 0x70, 0xff }, + { 0x08, 0x01 }, + { 0x09, 0x3e }, + { 0x50, 0xd1 }, + { 0x51, 0x22 }, + { 0x39, 0x01 }, + { 0x71, 0x00 }, + { 0x28, 0x2a }, + { 0x29, 0x00 }, + { 0x2a, 0xff }, + { 0x2b, 0x80 }, + { 0x28, 0x20 }, + { 0x29, 0x33 }, + { 0x2a, 0xdf }, + { 0x2b, 0xa9 }, + { 0x3b, 0x21 }, + { 0x3c, 0x3a }, + { 0x01, 0x0d }, + { 0x04, 0x08 }, + { 0x05, 0x05 }, + { 0x04, 0x0e }, + { 0x05, 0x00 }, + { 0x04, 0x0f }, + { 0x05, 0x14 }, + { 0x04, 0x0b }, + { 0x05, 0x8c }, + { 0x04, 0x00 }, + { 0x05, 0x00 }, + { 0x04, 0x01 }, + { 0x05, 0x07 }, + { 0x04, 0x02 }, + { 0x05, 0x0f }, + { 0x04, 0x03 }, + { 0x05, 0xa0 }, + { 0x04, 0x09 }, + { 0x05, 0x00 }, + { 0x04, 0x0a }, + { 0x05, 0xff }, + { 0x04, 0x27 }, + { 0x05, 0x64 }, + { 0x04, 0x28 }, + { 0x05, 0x00 }, + { 0x04, 0x1e }, + { 0x05, 0xff }, + { 0x04, 0x29 }, + { 0x05, 0x0a }, + { 0x04, 0x32 }, + { 0x05, 0x0a }, + { 0x04, 0x14 }, + { 0x05, 0x02 }, + { 0x04, 0x04 }, + { 0x05, 0x00 }, + { 0x04, 0x05 }, + { 0x05, 0x22 }, + { 0x04, 0x06 }, + { 0x05, 0x0e }, + { 0x04, 0x07 }, + { 0x05, 0xd8 }, + { 0x04, 0x12 }, + { 0x05, 0x00 }, + { 0x04, 0x13 }, + { 0x05, 0xff }, + { 0x52, 0x01 }, + { 0x50, 0xa7 }, + { 0x51, 0x00 }, + { 0x50, 0xa8 }, + { 0x51, 0xff }, + { 0x50, 0xa9 }, + { 0x51, 0xff }, + { 0x50, 0xaa }, + { 0x51, 0x00 }, + { 0x50, 0xab }, + { 0x51, 0xff }, + { 0x50, 0xac }, + { 0x51, 0xff }, + { 0x50, 0xad }, + { 0x51, 0x00 }, + { 0x50, 0xae }, + { 0x51, 0xff }, + { 0x50, 0xaf }, + { 0x51, 0xff }, + { 0x5e, 0x07 }, + { 0x50, 0xdc }, + { 0x51, 0x01 }, + { 0x50, 0xdd }, + { 0x51, 0xf4 }, + { 0x50, 0xde }, + { 0x51, 0x01 }, + { 0x50, 0xdf }, + { 0x51, 0xf4 }, + { 0x50, 0xe0 }, + { 0x51, 0x01 }, + { 0x50, 0xe1 }, + { 0x51, 0xf4 }, + { 0x50, 0xb0 }, + { 0x51, 0x07 }, + { 0x50, 0xb2 }, + { 0x51, 0xff }, + { 0x50, 0xb3 }, + { 0x51, 0xff }, + { 0x50, 0xb4 }, + { 0x51, 0xff }, + { 0x50, 0xb5 }, + { 0x51, 0xff }, + { 0x50, 0xb6 }, + { 0x51, 0xff }, + { 0x50, 0xb7 }, + { 0x51, 0xff }, + { 0x50, 0x50 }, + { 0x51, 0x02 }, + { 0x50, 0x51 }, + { 0x51, 0x04 }, + { 0x45, 0x04 }, + { 0x48, 0x04 }, + { 0x50, 0xd5 }, + { 0x51, 0x01 }, /* Serial */ + { 0x50, 0xd6 }, + { 0x51, 0x1f }, + { 0x50, 0xd2 }, + { 0x51, 0x03 }, + { 0x50, 0xd7 }, + { 0x51, 0x3f }, + { 0x1c, 0x01 }, + { 0x28, 0x06 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x03 }, + { 0x28, 0x07 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x0d }, + { 0x28, 0x08 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x02 }, + { 0x28, 0x09 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x01 }, + { 0x28, 0x0a }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x21 }, + { 0x28, 0x0b }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x29 }, + { 0x28, 0x0c }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x16 }, + { 0x28, 0x0d }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x31 }, + { 0x28, 0x0e }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x0e }, + { 0x28, 0x0f }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x4e }, + { 0x28, 0x10 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x46 }, + { 0x28, 0x11 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x0f }, + { 0x28, 0x12 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x56 }, + { 0x28, 0x13 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x35 }, + { 0x28, 0x14 }, + { 0x29, 0x00 }, + { 0x2a, 0x01 }, + { 0x2b, 0xbe }, + { 0x28, 0x15 }, + { 0x29, 0x00 }, + { 0x2a, 0x01 }, + { 0x2b, 0x84 }, + { 0x28, 0x16 }, + { 0x29, 0x00 }, + { 0x2a, 0x03 }, + { 0x2b, 0xee }, + { 0x28, 0x17 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x98 }, + { 0x28, 0x18 }, + { 0x29, 0x00 }, + { 0x2a, 0x00 }, + { 0x2b, 0x9f }, + { 0x28, 0x19 }, + { 0x29, 0x00 }, + { 0x2a, 0x07 }, + { 0x2b, 0xb2 }, + { 0x28, 0x1a }, + { 0x29, 0x00 }, + { 0x2a, 0x06 }, + { 0x2b, 0xc2 }, + { 0x28, 0x1b }, + { 0x29, 0x00 }, + { 0x2a, 0x07 }, + { 0x2b, 0x4a }, + { 0x28, 0x1c }, + { 0x29, 0x00 }, + { 0x2a, 0x01 }, + { 0x2b, 0xbc }, + { 0x28, 0x1d }, + { 0x29, 0x00 }, + { 0x2a, 0x04 }, + { 0x2b, 0xba }, + { 0x28, 0x1e }, + { 0x29, 0x00 }, + { 0x2a, 0x06 }, + { 0x2b, 0x14 }, + { 0x50, 0x1e }, + { 0x51, 0x5d }, + { 0x50, 0x22 }, + { 0x51, 0x00 }, + { 0x50, 0x23 }, + { 0x51, 0xc8 }, + { 0x50, 0x24 }, + { 0x51, 0x00 }, + { 0x50, 0x25 }, + { 0x51, 0xf0 }, + { 0x50, 0x26 }, + { 0x51, 0x00 }, + { 0x50, 0x27 }, + { 0x51, 0xc3 }, + { 0x50, 0x39 }, + { 0x51, 0x02 }, + { 0x50, 0xd5 }, + { 0x51, 0x01 }, + { 0xd0, 0x00 }, +}; + +static struct regdata mb86a20s_reset_reception[] = { + { 0x70, 0xf0 }, + { 0x70, 0xff }, + { 0x08, 0x01 }, + { 0x08, 0x00 }, +}; + +static int mb86a20s_i2c_writereg(struct mb86a20s_state *state, + u8 i2c_addr, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 + }; + int rc; + + rc = i2c_transfer(state->i2c, &msg, 1); + if (rc != 1) { + printk("%s: writereg rcor(rc == %i, reg == 0x%02x," + " data == 0x%02x)\n", __func__, rc, reg, data); + return rc; + } + + return 0; +} + +static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state, + u8 i2c_addr, struct regdata *rd, int size) +{ + int i, rc; + + for (i = 0; i < size; i++) { + rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg, + rd[i].data); + if (rc < 0) + return rc; + } + return 0; +} + +static int mb86a20s_i2c_readreg(struct mb86a20s_state *state, + u8 i2c_addr, u8 reg) +{ + u8 val; + int rc; + struct i2c_msg msg[] = { + { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, + { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } + }; + + rc = i2c_transfer(state->i2c, msg, 2); + + if (rc != 2) { + rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc); + return rc; + } + + return val; +} + +#define mb86a20s_readreg(state, reg) \ + mb86a20s_i2c_readreg(state, state->config->demod_address, reg) +#define mb86a20s_writereg(state, reg, val) \ + mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val) +#define mb86a20s_writeregdata(state, regdata) \ + mb86a20s_i2c_writeregdata(state, state->config->demod_address, \ + regdata, ARRAY_SIZE(regdata)) + +static int mb86a20s_initfe(struct dvb_frontend *fe) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + int rc; + u8 regD5 = 1; + + dprintk("\n"); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + /* Initialize the frontend */ + rc = mb86a20s_writeregdata(state, mb86a20s_init); + if (rc < 0) + return rc; + + if (!state->config->is_serial) { + regD5 &= ~1; + + rc = mb86a20s_writereg(state, 0x50, 0xd5); + if (rc < 0) + return rc; + rc = mb86a20s_writereg(state, 0x51, regD5); + if (rc < 0) + return rc; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + return 0; +} + +static int mb86a20s_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + unsigned rf_max, rf_min, rf; + u8 val; + + dprintk("\n"); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + /* Does a binary search to get RF strength */ + rf_max = 0xfff; + rf_min = 0; + do { + rf = (rf_max + rf_min) / 2; + mb86a20s_writereg(state, 0x04, 0x1f); + mb86a20s_writereg(state, 0x05, rf >> 8); + mb86a20s_writereg(state, 0x04, 0x20); + mb86a20s_writereg(state, 0x04, rf); + + val = mb86a20s_readreg(state, 0x02); + if (val & 0x08) + rf_min = (rf_max + rf_min) / 2; + else + rf_max = (rf_max + rf_min) / 2; + if (rf_max - rf_min < 4) { + *strength = (((rf_max + rf_min) / 2) * 65535) / 4095; + break; + } + } while (1); + + dprintk("signal strength = %d\n", *strength); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + return 0; +} + +static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + u8 val; + + dprintk("\n"); + *status = 0; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + val = mb86a20s_readreg(state, 0x0a) & 0xf; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (val >= 2) + *status |= FE_HAS_SIGNAL; + + if (val >= 4) + *status |= FE_HAS_CARRIER; + + if (val >= 5) + *status |= FE_HAS_VITERBI; + + if (val >= 7) + *status |= FE_HAS_SYNC; + + if (val >= 8) /* Maybe 9? */ + *status |= FE_HAS_LOCK; + + dprintk("val = %d, status = 0x%02x\n", val, *status); + + return 0; +} + +static int mb86a20s_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + fe->ops.tuner_ops.set_params(fe, p); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + return rc; +} + +static int mb86a20s_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + + /* FIXME: For now, it does nothing */ + + fe->dtv_property_cache.bandwidth_hz = 6000000; + fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO; + fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO; + fe->dtv_property_cache.isdbt_partial_reception = 0; + + return 0; +} + +static int mb86a20s_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + unsigned int mode_flags, + unsigned int *delay, + fe_status_t *status) +{ + int rc = 0; + + dprintk("\n"); + + if (params != NULL) + rc = mb86a20s_set_frontend(fe, params); + + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + mb86a20s_read_status(fe, status); + + return rc; +} + +static void mb86a20s_release(struct dvb_frontend *fe) +{ + struct mb86a20s_state *state = fe->demodulator_priv; + + dprintk("\n"); + + kfree(state); +} + +static struct dvb_frontend_ops mb86a20s_ops; + +struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, + struct i2c_adapter *i2c) +{ + u8 rev; + + /* allocate memory for the internal state */ + struct mb86a20s_state *state = + kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL); + + dprintk("\n"); + if (state == NULL) { + rc("Unable to kzalloc\n"); + goto error; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &mb86a20s_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + /* Check if it is a mb86a20s frontend */ + rev = mb86a20s_readreg(state, 0); + + if (rev == 0x13) { + printk(KERN_INFO "Detected a Fujitsu mb86a20s frontend\n"); + } else { + printk(KERN_ERR "Frontend revision %d is unknown - aborting.\n", + rev); + goto error; + } + + return &state->frontend; + +error: + kfree(state); + return NULL; +} +EXPORT_SYMBOL(mb86a20s_attach); + +static struct dvb_frontend_ops mb86a20s_ops = { + /* Use dib8000 values per default */ + .info = { + .name = "Fujitsu mb86A20s", + .type = FE_OFDM, + .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | + FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, + /* Actually, those values depend on the used tuner */ + .frequency_min = 45000000, + .frequency_max = 864000000, + .frequency_stepsize = 62500, + }, + + .release = mb86a20s_release, + + .init = mb86a20s_initfe, + .set_frontend = mb86a20s_set_frontend, + .get_frontend = mb86a20s_get_frontend, + .read_status = mb86a20s_read_status, + .read_signal_strength = mb86a20s_read_signal_strength, + .tune = mb86a20s_tune, +}; + +MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/mb86a20s.h b/drivers/media/dvb/frontends/mb86a20s.h new file mode 100644 index 000000000000..bf22e77888b9 --- /dev/null +++ b/drivers/media/dvb/frontends/mb86a20s.h @@ -0,0 +1,52 @@ +/* + * Fujitsu mb86a20s driver + * + * Copyright (C) 2010 Mauro Carvalho Chehab <mchehab@redhat.com> + * + * 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 the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef MB86A20S_H +#define MB86A20S_H + +#include <linux/dvb/frontend.h> + +/** + * struct mb86a20s_config - Define the per-device attributes of the frontend + * + * @demod_address: the demodulator's i2c address + */ + +struct mb86a20s_config { + u8 demod_address; + bool is_serial; +}; + +#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, + struct i2c_adapter *i2c); +extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *); +#else +static inline struct dvb_frontend *mb86a20s_attach( + const struct mb86a20s_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static struct i2c_adapter * + mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* MB86A20S */ diff --git a/drivers/media/dvb/frontends/s921.c b/drivers/media/dvb/frontends/s921.c new file mode 100644 index 000000000000..ca0103d5f148 --- /dev/null +++ b/drivers/media/dvb/frontends/s921.c @@ -0,0 +1,548 @@ +/* + * Sharp VA3A5JZ921 One Seg Broadcast Module driver + * This device is labeled as just S. 921 at the top of the frontend can + * + * Copyright (C) 2009-2010 Mauro Carvalho Chehab <mchehab@redhat.com> + * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com> + * + * Developed for Leadership SBTVD 1seg device sold in Brazil + * + * Frontend module based on cx24123 driver, getting some info from + * the old s921 driver. + * + * FIXME: Need to port to DVB v5.2 API + * + * 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 the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/kernel.h> +#include <asm/div64.h> + +#include "dvb_frontend.h" +#include "s921.h" + +static int debug = 1; +module_param(debug, int, 0644); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); + +#define rc(args...) do { \ + printk(KERN_ERR "s921: " args); \ +} while (0) + +#define dprintk(args...) \ + do { \ + if (debug) { \ + printk(KERN_DEBUG "s921: %s: ", __func__); \ + printk(args); \ + } \ + } while (0) + +struct s921_state { + struct i2c_adapter *i2c; + const struct s921_config *config; + + struct dvb_frontend frontend; + + /* The Demod can't easily provide these, we cache them */ + u32 currentfreq; +}; + +/* + * Various tuner defaults need to be established for a given frequency kHz. + * fixme: The bounds on the bands do not match the doc in real life. + * fixme: Some of them have been moved, other might need adjustment. + */ +static struct s921_bandselect_val { + u32 freq_low; + u8 band_reg; +} s921_bandselect[] = { + { 0, 0x7b }, + { 485140000, 0x5b }, + { 515140000, 0x3b }, + { 545140000, 0x1b }, + { 599140000, 0xfb }, + { 623140000, 0xdb }, + { 659140000, 0xbb }, + { 713140000, 0x9b }, +}; + +struct regdata { + u8 reg; + u8 data; +}; + +static struct regdata s921_init[] = { + { 0x01, 0x80 }, /* Probably, a reset sequence */ + { 0x01, 0x40 }, + { 0x01, 0x80 }, + { 0x01, 0x40 }, + + { 0x02, 0x00 }, + { 0x03, 0x40 }, + { 0x04, 0x01 }, + { 0x05, 0x00 }, + { 0x06, 0x00 }, + { 0x07, 0x00 }, + { 0x08, 0x00 }, + { 0x09, 0x00 }, + { 0x0a, 0x00 }, + { 0x0b, 0x5a }, + { 0x0c, 0x00 }, + { 0x0d, 0x00 }, + { 0x0f, 0x00 }, + { 0x13, 0x1b }, + { 0x14, 0x80 }, + { 0x15, 0x40 }, + { 0x17, 0x70 }, + { 0x18, 0x01 }, + { 0x19, 0x12 }, + { 0x1a, 0x01 }, + { 0x1b, 0x12 }, + { 0x1c, 0xa0 }, + { 0x1d, 0x00 }, + { 0x1e, 0x0a }, + { 0x1f, 0x08 }, + { 0x20, 0x40 }, + { 0x21, 0xff }, + { 0x22, 0x4c }, + { 0x23, 0x4e }, + { 0x24, 0x4c }, + { 0x25, 0x00 }, + { 0x26, 0x00 }, + { 0x27, 0xf4 }, + { 0x28, 0x60 }, + { 0x29, 0x88 }, + { 0x2a, 0x40 }, + { 0x2b, 0x40 }, + { 0x2c, 0xff }, + { 0x2d, 0x00 }, + { 0x2e, 0xff }, + { 0x2f, 0x00 }, + { 0x30, 0x20 }, + { 0x31, 0x06 }, + { 0x32, 0x0c }, + { 0x34, 0x0f }, + { 0x37, 0xfe }, + { 0x38, 0x00 }, + { 0x39, 0x63 }, + { 0x3a, 0x10 }, + { 0x3b, 0x10 }, + { 0x47, 0x00 }, + { 0x49, 0xe5 }, + { 0x4b, 0x00 }, + { 0x50, 0xc0 }, + { 0x52, 0x20 }, + { 0x54, 0x5a }, + { 0x55, 0x5b }, + { 0x56, 0x40 }, + { 0x57, 0x70 }, + { 0x5c, 0x50 }, + { 0x5d, 0x00 }, + { 0x62, 0x17 }, + { 0x63, 0x2f }, + { 0x64, 0x6f }, + { 0x68, 0x00 }, + { 0x69, 0x89 }, + { 0x6a, 0x00 }, + { 0x6b, 0x00 }, + { 0x6c, 0x00 }, + { 0x6d, 0x00 }, + { 0x6e, 0x00 }, + { 0x70, 0x10 }, + { 0x71, 0x00 }, + { 0x75, 0x00 }, + { 0x76, 0x30 }, + { 0x77, 0x01 }, + { 0xaf, 0x00 }, + { 0xb0, 0xa0 }, + { 0xb2, 0x3d }, + { 0xb3, 0x25 }, + { 0xb4, 0x8b }, + { 0xb5, 0x4b }, + { 0xb6, 0x3f }, + { 0xb7, 0xff }, + { 0xb8, 0xff }, + { 0xb9, 0xfc }, + { 0xba, 0x00 }, + { 0xbb, 0x00 }, + { 0xbc, 0x00 }, + { 0xd0, 0x30 }, + { 0xe4, 0x84 }, + { 0xf0, 0x48 }, + { 0xf1, 0x19 }, + { 0xf2, 0x5a }, + { 0xf3, 0x8e }, + { 0xf4, 0x2d }, + { 0xf5, 0x07 }, + { 0xf6, 0x5a }, + { 0xf7, 0xba }, + { 0xf8, 0xd7 }, +}; + +static struct regdata s921_prefreq[] = { + { 0x47, 0x60 }, + { 0x68, 0x00 }, + { 0x69, 0x89 }, + { 0xf0, 0x48 }, + { 0xf1, 0x19 }, +}; + +static struct regdata s921_postfreq[] = { + { 0xf5, 0xae }, + { 0xf6, 0xb7 }, + { 0xf7, 0xba }, + { 0xf8, 0xd7 }, + { 0x68, 0x0a }, + { 0x69, 0x09 }, +}; + +static int s921_i2c_writereg(struct s921_state *state, + u8 i2c_addr, int reg, int data) +{ + u8 buf[] = { reg, data }; + struct i2c_msg msg = { + .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 + }; + int rc; + + rc = i2c_transfer(state->i2c, &msg, 1); + if (rc != 1) { + printk("%s: writereg rcor(rc == %i, reg == 0x%02x," + " data == 0x%02x)\n", __func__, rc, reg, data); + return rc; + } + + return 0; +} + +static int s921_i2c_writeregdata(struct s921_state *state, u8 i2c_addr, + struct regdata *rd, int size) +{ + int i, rc; + + for (i = 0; i < size; i++) { + rc = s921_i2c_writereg(state, i2c_addr, rd[i].reg, rd[i].data); + if (rc < 0) + return rc; + } + return 0; +} + +static int s921_i2c_readreg(struct s921_state *state, u8 i2c_addr, u8 reg) +{ + u8 val; + int rc; + struct i2c_msg msg[] = { + { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, + { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } + }; + + rc = i2c_transfer(state->i2c, msg, 2); + + if (rc != 2) { + rc("%s: reg=0x%x (rcor=%d)\n", __func__, reg, rc); + return rc; + } + + return val; +} + +#define s921_readreg(state, reg) \ + s921_i2c_readreg(state, state->config->demod_address, reg) +#define s921_writereg(state, reg, val) \ + s921_i2c_writereg(state, state->config->demod_address, reg, val) +#define s921_writeregdata(state, regdata) \ + s921_i2c_writeregdata(state, state->config->demod_address, \ + regdata, ARRAY_SIZE(regdata)) + +static int s921_pll_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct s921_state *state = fe->demodulator_priv; + int band, rc, i; + unsigned long f_offset; + u8 f_switch; + u64 offset; + + dprintk("frequency=%i\n", p->frequency); + + for (band = 0; band < ARRAY_SIZE(s921_bandselect); band++) + if (p->frequency < s921_bandselect[band].freq_low) + break; + band--; + + if (band < 0) { + rc("%s: frequency out of range\n", __func__); + return -EINVAL; + } + + f_switch = s921_bandselect[band].band_reg; + + offset = ((u64)p->frequency) * 258; + do_div(offset, 6000000); + f_offset = ((unsigned long)offset) + 2321; + + rc = s921_writeregdata(state, s921_prefreq); + if (rc < 0) + return rc; + + rc = s921_writereg(state, 0xf2, (f_offset >> 8) & 0xff); + if (rc < 0) + return rc; + + rc = s921_writereg(state, 0xf3, f_offset & 0xff); + if (rc < 0) + return rc; + + rc = s921_writereg(state, 0xf4, f_switch); + if (rc < 0) + return rc; + + rc = s921_writeregdata(state, s921_postfreq); + if (rc < 0) + return rc; + + for (i = 0 ; i < 6; i++) { + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + } + rc = s921_writereg(state, 0x01, 0x40); + if (rc < 0) + return rc; + + rc = s921_readreg(state, 0x01); + dprintk("status 0x01: %02x\n", rc); + + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + + rc = s921_readreg(state, 0x32); + dprintk("status 0x32: %02x\n", rc); + + dprintk("pll tune band=%d, pll=%d\n", f_switch, (int)f_offset); + + return 0; +} + +static int s921_initfe(struct dvb_frontend *fe) +{ + struct s921_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + rc = s921_writeregdata(state, s921_init); + if (rc < 0) + return rc; + + return 0; +} + +static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status) +{ + struct s921_state *state = fe->demodulator_priv; + int regstatus, rc; + + *status = 0; + + rc = s921_readreg(state, 0x81); + if (rc < 0) + return rc; + + regstatus = rc << 8; + + rc = s921_readreg(state, 0x82); + if (rc < 0) + return rc; + + regstatus |= rc; + + dprintk("status = %04x\n", regstatus); + + /* Full Sync - We don't know what each bit means on regs 0x81/0x82 */ + if ((regstatus & 0xff) == 0x40) { + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC | + FE_HAS_LOCK; + } else if (regstatus & 0x40) { + /* This is close to Full Sync, but not enough to get useful info */ + *status = FE_HAS_SIGNAL | + FE_HAS_CARRIER | + FE_HAS_VITERBI | + FE_HAS_SYNC; + } + + return 0; +} + +static int s921_read_signal_strength(struct dvb_frontend *fe, u16 *strength) +{ + fe_status_t status; + struct s921_state *state = fe->demodulator_priv; + int rc; + + /* FIXME: Use the proper register for it... 0x80? */ + rc = s921_read_status(fe, &status); + if (rc < 0) + return rc; + + *strength = (status & FE_HAS_LOCK) ? 0xffff : 0; + + dprintk("strength = 0x%04x\n", *strength); + + rc = s921_readreg(state, 0x01); + dprintk("status 0x01: %02x\n", rc); + + rc = s921_readreg(state, 0x80); + dprintk("status 0x80: %02x\n", rc); + + rc = s921_readreg(state, 0x32); + dprintk("status 0x32: %02x\n", rc); + + return 0; +} + +static int s921_set_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct s921_state *state = fe->demodulator_priv; + int rc; + + dprintk("\n"); + + /* FIXME: We don't know how to use non-auto mode */ + + rc = s921_pll_tune(fe, p); + if (rc < 0) + return rc; + + state->currentfreq = p->frequency; + + return 0; +} + +static int s921_get_frontend(struct dvb_frontend *fe, + struct dvb_frontend_parameters *p) +{ + struct s921_state *state = fe->demodulator_priv; + + /* FIXME: Probably it is possible to get it from regs f1 and f2 */ + p->frequency = state->currentfreq; + + return 0; +} + +static int s921_tune(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params, + unsigned int mode_flags, + unsigned int *delay, + fe_status_t *status) +{ + int rc = 0; + + dprintk("\n"); + + if (params != NULL) + rc = s921_set_frontend(fe, params); + + if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) + s921_read_status(fe, status); + + return rc; +} + +static int s921_get_algo(struct dvb_frontend *fe) +{ + return 1; /* FE_ALGO_HW */ +} + +static void s921_release(struct dvb_frontend *fe) +{ + struct s921_state *state = fe->demodulator_priv; + + dprintk("\n"); + kfree(state); +} + +static struct dvb_frontend_ops s921_ops; + +struct dvb_frontend *s921_attach(const struct s921_config *config, + struct i2c_adapter *i2c) +{ + /* allocate memory for the internal state */ + struct s921_state *state = + kzalloc(sizeof(struct s921_state), GFP_KERNEL); + + dprintk("\n"); + if (state == NULL) { + rc("Unable to kzalloc\n"); + goto rcor; + } + + /* setup the state */ + state->config = config; + state->i2c = i2c; + + /* create dvb_frontend */ + memcpy(&state->frontend.ops, &s921_ops, + sizeof(struct dvb_frontend_ops)); + state->frontend.demodulator_priv = state; + + return &state->frontend; + +rcor: + kfree(state); + + return NULL; +} +EXPORT_SYMBOL(s921_attach); + +static struct dvb_frontend_ops s921_ops = { + /* Use dib8000 values per default */ + .info = { + .name = "Sharp S921", + .type = FE_OFDM, + .frequency_min = 470000000, + /* + * Max should be 770MHz instead, according with Sharp docs, + * but Leadership doc says it works up to 806 MHz. This is + * required to get channel 69, used in Brazil + */ + .frequency_max = 806000000, + .frequency_tolerance = 0, + .caps = FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | + FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | + FE_CAN_HIERARCHY_AUTO, + }, + + .release = s921_release, + + .init = s921_initfe, + .set_frontend = s921_set_frontend, + .get_frontend = s921_get_frontend, + .read_status = s921_read_status, + .read_signal_strength = s921_read_signal_strength, + .tune = s921_tune, + .get_frontend_algo = s921_get_algo, +}; + +MODULE_DESCRIPTION("DVB Frontend module for Sharp S921 hardware"); +MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); +MODULE_AUTHOR("Douglas Landgraf <dougsland@redhat.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/s921.h b/drivers/media/dvb/frontends/s921.h new file mode 100644 index 000000000000..f220d8299c81 --- /dev/null +++ b/drivers/media/dvb/frontends/s921.h @@ -0,0 +1,47 @@ +/* + * Sharp s921 driver + * + * Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@redhat.com> + * Copyright (C) 2009 Douglas Landgraf <dougsland@redhat.com> + * + * 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 the Free Software Foundation version 2. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef S921_H +#define S921_H + +#include <linux/dvb/frontend.h> + +struct s921_config { + /* the demodulator's i2c address */ + u8 demod_address; +}; + +#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \ + && defined(MODULE)) +extern struct dvb_frontend *s921_attach(const struct s921_config *config, + struct i2c_adapter *i2c); +extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *); +#else +static inline struct dvb_frontend *s921_attach( + const struct s921_config *config, struct i2c_adapter *i2c) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +static struct i2c_adapter * + s921_get_tuner_i2c_adapter(struct dvb_frontend *fe) +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif + +#endif /* S921_H */ diff --git a/drivers/media/dvb/frontends/s921_core.c b/drivers/media/dvb/frontends/s921_core.c deleted file mode 100644 index 974b52be9aea..000000000000 --- a/drivers/media/dvb/frontends/s921_core.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Driver for Sharp s921 driver - * - * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de> - * - */ - - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include "s921_core.h" - -static int s921_isdb_init(struct s921_isdb_t *dev); -static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params); -static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params); -static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data); - -static u8 init_table[]={ 0x01, 0x40, 0x02, 0x00, 0x03, 0x40, 0x04, 0x01, - 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, - 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x5a, 0x0c, 0x00, - 0x0d, 0x00, 0x0f, 0x00, 0x13, 0x1b, 0x14, 0x80, - 0x15, 0x40, 0x17, 0x70, 0x18, 0x01, 0x19, 0x12, - 0x1a, 0x01, 0x1b, 0x12, 0x1c, 0xa0, 0x1d, 0x00, - 0x1e, 0x0a, 0x1f, 0x08, 0x20, 0x40, 0x21, 0xff, - 0x22, 0x4c, 0x23, 0x4e, 0x24, 0x4c, 0x25, 0x00, - 0x26, 0x00, 0x27, 0xf4, 0x28, 0x60, 0x29, 0x88, - 0x2a, 0x40, 0x2b, 0x40, 0x2c, 0xff, 0x2d, 0x00, - 0x2e, 0xff, 0x2f, 0x00, 0x30, 0x20, 0x31, 0x06, - 0x32, 0x0c, 0x34, 0x0f, 0x37, 0xfe, 0x38, 0x00, - 0x39, 0x63, 0x3a, 0x10, 0x3b, 0x10, 0x47, 0x00, - 0x49, 0xe5, 0x4b, 0x00, 0x50, 0xc0, 0x52, 0x20, - 0x54, 0x5a, 0x55, 0x5b, 0x56, 0x40, 0x57, 0x70, - 0x5c, 0x50, 0x5d, 0x00, 0x62, 0x17, 0x63, 0x2f, - 0x64, 0x6f, 0x68, 0x00, 0x69, 0x89, 0x6a, 0x00, - 0x6b, 0x00, 0x6c, 0x00, 0x6d, 0x00, 0x6e, 0x00, - 0x70, 0x00, 0x71, 0x00, 0x75, 0x00, 0x76, 0x30, - 0x77, 0x01, 0xaf, 0x00, 0xb0, 0xa0, 0xb2, 0x3d, - 0xb3, 0x25, 0xb4, 0x8b, 0xb5, 0x4b, 0xb6, 0x3f, - 0xb7, 0xff, 0xb8, 0xff, 0xb9, 0xfc, 0xba, 0x00, - 0xbb, 0x00, 0xbc, 0x00, 0xd0, 0x30, 0xe4, 0x84, - 0xf0, 0x48, 0xf1, 0x19, 0xf2, 0x5a, 0xf3, 0x8e, - 0xf4, 0x2d, 0xf5, 0x07, 0xf6, 0x5a, 0xf7, 0xba, - 0xf8, 0xd7 }; - -static u8 c_table[]={ 0x58, 0x8a, 0x7b, 0x59, 0x8c, 0x7b, 0x5a, 0x8e, 0x5b, - 0x5b, 0x90, 0x5b, 0x5c, 0x92, 0x5b, 0x5d, 0x94, 0x5b, - 0x5e, 0x96, 0x5b, 0x5f, 0x98, 0x3b, 0x60, 0x9a, 0x3b, - 0x61, 0x9c, 0x3b, 0x62, 0x9e, 0x3b, 0x63, 0xa0, 0x3b, - 0x64, 0xa2, 0x1b, 0x65, 0xa4, 0x1b, 0x66, 0xa6, 0x1b, - 0x67, 0xa8, 0x1b, 0x68, 0xaa, 0x1b, 0x69, 0xac, 0x1b, - 0x6a, 0xae, 0x1b, 0x6b, 0xb0, 0x1b, 0x6c, 0xb2, 0x1b, - 0x6d, 0xb4, 0xfb, 0x6e, 0xb6, 0xfb, 0x6f, 0xb8, 0xfb, - 0x70, 0xba, 0xfb, 0x71, 0xbc, 0xdb, 0x72, 0xbe, 0xdb, - 0x73, 0xc0, 0xdb, 0x74, 0xc2, 0xdb, 0x75, 0xc4, 0xdb, - 0x76, 0xc6, 0xdb, 0x77, 0xc8, 0xbb, 0x78, 0xca, 0xbb, - 0x79, 0xcc, 0xbb, 0x7a, 0xce, 0xbb, 0x7b, 0xd0, 0xbb, - 0x7c, 0xd2, 0xbb, 0x7d, 0xd4, 0xbb, 0x7e, 0xd6, 0xbb, - 0x7f, 0xd8, 0xbb, 0x80, 0xda, 0x9b, 0x81, 0xdc, 0x9b, - 0x82, 0xde, 0x9b, 0x83, 0xe0, 0x9b, 0x84, 0xe2, 0x9b, - 0x85, 0xe4, 0x9b, 0x86, 0xe6, 0x9b, 0x87, 0xe8, 0x9b, - 0x88, 0xea, 0x9b, 0x89, 0xec, 0x9b }; - -int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data) { - switch(cmd) { - case ISDB_T_CMD_INIT: - s921_isdb_init(dev); - break; - case ISDB_T_CMD_SET_PARAM: - s921_isdb_set_parameters(dev, data); - break; - case ISDB_T_CMD_TUNE: - s921_isdb_tune(dev, data); - break; - case ISDB_T_CMD_GET_STATUS: - s921_isdb_get_status(dev, data); - break; - default: - printk("unhandled command\n"); - return -EINVAL; - } - return 0; -} - -static int s921_isdb_init(struct s921_isdb_t *dev) { - unsigned int i; - unsigned int ret; - printk("isdb_init\n"); - for (i = 0; i < sizeof(init_table); i+=2) { - ret = dev->i2c_write(dev->priv_dev, init_table[i], init_table[i+1]); - if (ret != 0) { - printk("i2c write failed\n"); - return ret; - } - } - return 0; -} - -static int s921_isdb_set_parameters(struct s921_isdb_t *dev, struct s921_isdb_t_transmission_mode_params *params) { - - int ret; - /* auto is sufficient for now, lateron this should be reflected in an extra interface */ - - - - ret = dev->i2c_write(dev->priv_dev, 0xb0, 0xa0); //mod_b2); - ret = dev->i2c_write(dev->priv_dev, 0xb2, 0x3d); //mod_b2); - - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb3, 0x25); //mod_b3); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb4, 0x8b); //mod_b4); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb5, 0x4b); //mod_b5); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb6, 0x3f); //mod_b6); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xb7, 0x3f); //mod_b7); - if (ret < 0) - return -EINVAL; - - return E_OK; -} - -static int s921_isdb_tune(struct s921_isdb_t *dev, struct s921_isdb_t_tune_params *params) { - - int ret; - int index; - - index = (params->frequency - 473143000)/6000000; - - if (index > 48) { - return -EINVAL; - } - - dev->i2c_write(dev->priv_dev, 0x47, 0x60); - - ret = dev->i2c_write(dev->priv_dev, 0x68, 0x00); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0x69, 0x89); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf0, 0x48); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf1, 0x19); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf2, c_table[index*3]); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf3, c_table[index*3+1]); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf4, c_table[index*3+2]); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf5, 0xae); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf6, 0xb7); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf7, 0xba); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0xf8, 0xd7); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0x68, 0x0a); - if (ret < 0) - return -EINVAL; - - ret = dev->i2c_write(dev->priv_dev, 0x69, 0x09); - if (ret < 0) - return -EINVAL; - - dev->i2c_write(dev->priv_dev, 0x01, 0x40); - return 0; -} - -static int s921_isdb_get_status(struct s921_isdb_t *dev, void *data) { - unsigned int *ret = (unsigned int*)data; - u8 ifagc_dt; - u8 rfagc_dt; - - mdelay(10); - ifagc_dt = dev->i2c_read(dev->priv_dev, 0x81); - rfagc_dt = dev->i2c_read(dev->priv_dev, 0x82); - if (rfagc_dt == 0x40) { - *ret = 1; - } - return 0; -} diff --git a/drivers/media/dvb/frontends/s921_core.h b/drivers/media/dvb/frontends/s921_core.h deleted file mode 100644 index de2f10a44e72..000000000000 --- a/drivers/media/dvb/frontends/s921_core.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef _S921_CORE_H -#define _S921_CORE_H -//#define u8 unsigned int -//#define u32 unsigned int - - - -//#define EINVAL -1 -#define E_OK 0 - -struct s921_isdb_t { - void *priv_dev; - int (*i2c_write)(void *dev, u8 reg, u8 val); - int (*i2c_read)(void *dev, u8 reg); -}; - -#define ISDB_T_CMD_INIT 0 -#define ISDB_T_CMD_SET_PARAM 1 -#define ISDB_T_CMD_TUNE 2 -#define ISDB_T_CMD_GET_STATUS 3 - -struct s921_isdb_t_tune_params { - u32 frequency; -}; - -struct s921_isdb_t_status { -}; - -struct s921_isdb_t_transmission_mode_params { - u8 mode; - u8 layer_a_mode; -#define ISDB_T_LA_MODE_1 0 -#define ISDB_T_LA_MODE_2 1 -#define ISDB_T_LA_MODE_3 2 - u8 layer_a_carrier_modulation; -#define ISDB_T_LA_CM_DQPSK 0 -#define ISDB_T_LA_CM_QPSK 1 -#define ISDB_T_LA_CM_16QAM 2 -#define ISDB_T_LA_CM_64QAM 3 -#define ISDB_T_LA_CM_NOLAYER 4 - u8 layer_a_code_rate; -#define ISDB_T_LA_CR_1_2 0 -#define ISDB_T_LA_CR_2_3 1 -#define ISDB_T_LA_CR_3_4 2 -#define ISDB_T_LA_CR_5_6 4 -#define ISDB_T_LA_CR_7_8 8 -#define ISDB_T_LA_CR_NOLAYER 16 - u8 layer_a_time_interleave; -#define ISDB_T_LA_TI_0 0 -#define ISDB_T_LA_TI_1 1 -#define ISDB_T_LA_TI_2 2 -#define ISDB_T_LA_TI_4 4 -#define ISDB_T_LA_TI_8 8 -#define ISDB_T_LA_TI_16 16 -#define ISDB_T_LA_TI_32 32 - u8 layer_a_nseg; - - u8 layer_b_mode; -#define ISDB_T_LB_MODE_1 0 -#define ISDB_T_LB_MODE_2 1 -#define ISDB_T_LB_MODE_3 2 - u8 layer_b_carrier_modulation; -#define ISDB_T_LB_CM_DQPSK 0 -#define ISDB_T_LB_CM_QPSK 1 -#define ISDB_T_LB_CM_16QAM 2 -#define ISDB_T_LB_CM_64QAM 3 -#define ISDB_T_LB_CM_NOLAYER 4 - u8 layer_b_code_rate; -#define ISDB_T_LB_CR_1_2 0 -#define ISDB_T_LB_CR_2_3 1 -#define ISDB_T_LB_CR_3_4 2 -#define ISDB_T_LB_CR_5_6 4 -#define ISDB_T_LB_CR_7_8 8 -#define ISDB_T_LB_CR_NOLAYER 16 - u8 layer_b_time_interleave; -#define ISDB_T_LB_TI_0 0 -#define ISDB_T_LB_TI_1 1 -#define ISDB_T_LB_TI_2 2 -#define ISDB_T_LB_TI_4 4 -#define ISDB_T_LB_TI_8 8 -#define ISDB_T_LB_TI_16 16 -#define ISDB_T_LB_TI_32 32 - u8 layer_b_nseg; - - u8 layer_c_mode; -#define ISDB_T_LC_MODE_1 0 -#define ISDB_T_LC_MODE_2 1 -#define ISDB_T_LC_MODE_3 2 - u8 layer_c_carrier_modulation; -#define ISDB_T_LC_CM_DQPSK 0 -#define ISDB_T_LC_CM_QPSK 1 -#define ISDB_T_LC_CM_16QAM 2 -#define ISDB_T_LC_CM_64QAM 3 -#define ISDB_T_LC_CM_NOLAYER 4 - u8 layer_c_code_rate; -#define ISDB_T_LC_CR_1_2 0 -#define ISDB_T_LC_CR_2_3 1 -#define ISDB_T_LC_CR_3_4 2 -#define ISDB_T_LC_CR_5_6 4 -#define ISDB_T_LC_CR_7_8 8 -#define ISDB_T_LC_CR_NOLAYER 16 - u8 layer_c_time_interleave; -#define ISDB_T_LC_TI_0 0 -#define ISDB_T_LC_TI_1 1 -#define ISDB_T_LC_TI_2 2 -#define ISDB_T_LC_TI_4 4 -#define ISDB_T_LC_TI_8 8 -#define ISDB_T_LC_TI_16 16 -#define ISDB_T_LC_TI_32 32 - u8 layer_c_nseg; -}; - -int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data); -#endif diff --git a/drivers/media/dvb/frontends/s921_module.c b/drivers/media/dvb/frontends/s921_module.c deleted file mode 100644 index 0eefff61cc50..000000000000 --- a/drivers/media/dvb/frontends/s921_module.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Driver for Sharp s921 driver - * - * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de> - * - * All rights reserved. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include "dvb_frontend.h" -#include "s921_module.h" -#include "s921_core.h" - -static unsigned int debug = 0; -module_param(debug, int, 0644); -MODULE_PARM_DESC(debug,"s921 debugging (default off)"); - -#define dprintk(fmt, args...) if (debug) do {\ - printk("s921 debug: " fmt, ##args); } while (0) - -struct s921_state -{ - struct dvb_frontend frontend; - fe_modulation_t current_modulation; - __u32 snr; - __u32 current_frequency; - __u8 addr; - struct s921_isdb_t dev; - struct i2c_adapter *i2c; -}; - -static int s921_set_parameters(struct dvb_frontend *fe, struct dvb_frontend_parameters *param) { - struct s921_state *state = (struct s921_state *)fe->demodulator_priv; - struct s921_isdb_t_transmission_mode_params params; - struct s921_isdb_t_tune_params tune_params; - - tune_params.frequency = param->frequency; - s921_isdb_cmd(&state->dev, ISDB_T_CMD_SET_PARAM, ¶ms); - s921_isdb_cmd(&state->dev, ISDB_T_CMD_TUNE, &tune_params); - mdelay(100); - return 0; -} - -static int s921_init(struct dvb_frontend *fe) { - printk("s921 init\n"); - return 0; -} - -static int s921_sleep(struct dvb_frontend *fe) { - printk("s921 sleep\n"); - return 0; -} - -static int s921_read_status(struct dvb_frontend *fe, fe_status_t *status) -{ - struct s921_state *state = (struct s921_state *)fe->demodulator_priv; - unsigned int ret; - mdelay(5); - s921_isdb_cmd(&state->dev, ISDB_T_CMD_GET_STATUS, &ret); - *status = 0; - - printk("status: %02x\n", ret); - if (ret == 1) { - *status |= FE_HAS_CARRIER; - *status |= FE_HAS_VITERBI; - *status |= FE_HAS_LOCK; - *status |= FE_HAS_SYNC; - *status |= FE_HAS_SIGNAL; - } - - return 0; -} - -static int s921_read_ber(struct dvb_frontend *fe, __u32 *ber) -{ - dprintk("read ber\n"); - return 0; -} - -static int s921_read_snr(struct dvb_frontend *fe, __u16 *snr) -{ - dprintk("read snr\n"); - return 0; -} - -static int s921_read_ucblocks(struct dvb_frontend *fe, __u32 *ucblocks) -{ - dprintk("read ucblocks\n"); - return 0; -} - -static void s921_release(struct dvb_frontend *fe) -{ - struct s921_state *state = (struct s921_state *)fe->demodulator_priv; - kfree(state); -} - -static struct dvb_frontend_ops demod_s921={ - .info = { - .name = "SHARP S921", - .type = FE_OFDM, - .frequency_min = 473143000, - .frequency_max = 767143000, - .frequency_stepsize = 6000000, - .frequency_tolerance = 0, - .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | - FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | - FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER | - FE_CAN_MUTE_TS - }, - .init = s921_init, - .sleep = s921_sleep, - .set_frontend = s921_set_parameters, - .read_snr = s921_read_snr, - .read_ber = s921_read_ber, - .read_status = s921_read_status, - .read_ucblocks = s921_read_ucblocks, - .release = s921_release, -}; - -static int s921_write(void *dev, u8 reg, u8 val) { - struct s921_state *state = dev; - char buf[2]={reg,val}; - int err; - struct i2c_msg i2cmsgs = { - .addr = state->addr, - .flags = 0, - .len = 2, - .buf = buf - }; - - if((err = i2c_transfer(state->i2c, &i2cmsgs, 1))<0) { - printk("%s i2c_transfer error %d\n", __func__, err); - if (err < 0) - return err; - else - return -EREMOTEIO; - } - - return 0; -} - -static int s921_read(void *dev, u8 reg) { - struct s921_state *state = dev; - u8 b1; - int ret; - struct i2c_msg msg[2] = { { .addr = state->addr, - .flags = 0, - .buf = ®, .len = 1 }, - { .addr = state->addr, - .flags = I2C_M_RD, - .buf = &b1, .len = 1 } }; - - ret = i2c_transfer(state->i2c, msg, 2); - if (ret != 2) - return ret; - return b1; -} - -struct dvb_frontend* s921_attach(const struct s921_config *config, - struct i2c_adapter *i2c) -{ - - struct s921_state *state; - state = kzalloc(sizeof(struct s921_state), GFP_KERNEL); - if (state == NULL) - return NULL; - - state->addr = config->i2c_address; - state->i2c = i2c; - state->dev.i2c_write = &s921_write; - state->dev.i2c_read = &s921_read; - state->dev.priv_dev = state; - - s921_isdb_cmd(&state->dev, ISDB_T_CMD_INIT, NULL); - - memcpy(&state->frontend.ops, &demod_s921, sizeof(struct dvb_frontend_ops)); - state->frontend.demodulator_priv = state; - return &state->frontend; -} - -EXPORT_SYMBOL_GPL(s921_attach); -MODULE_AUTHOR("Markus Rechberger <mrechberger@empiatech.com>"); -MODULE_DESCRIPTION("Sharp S921 ISDB-T 1Seg"); -MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/s921_module.h b/drivers/media/dvb/frontends/s921_module.h deleted file mode 100644 index 78660424ba95..000000000000 --- a/drivers/media/dvb/frontends/s921_module.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Driver for DVB-T s921 demodulator - * - * Copyright (C) 2008 Markus Rechberger <mrechberger@sundtek.de> - * - * 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 - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.= - */ - -#ifndef S921_MODULE_H -#define S921_MODULE_H - -#include <linux/dvb/frontend.h> -#include "s921_core.h" - -int s921_isdb_init(struct s921_isdb_t *dev); -int s921_isdb_cmd(struct s921_isdb_t *dev, u32 cmd, void *data); - -struct s921_config -{ - /* demodulator's I2C address */ - u8 i2c_address; -}; - -#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) && defined(MODULE)) -extern struct dvb_frontend* s921_attach(const struct s921_config *config, - struct i2c_adapter *i2c); -#else -static inline struct dvb_frontend* s921_attach(const struct s921_config *config, - struct i2c_adapter *i2c) -{ - printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); - return NULL; -} -#endif /* CONFIG_DVB_S921 */ - -#endif /* S921_H */ diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 8e38fcee564e..37a222d9ddb3 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -714,7 +714,7 @@ static int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_ma reg = stb0899_read_reg(state, STB0899_DISCNTRL1); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); - + msleep(100); return 0; } diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index 80a9e4cba631..64673b8b64a2 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -51,7 +51,7 @@ module_param(verbose, int, 0644); if (x > y) \ printk(format, ##arg); \ } \ -} while(0) +} while (0) struct stb6100_lkup { u32 val_low; @@ -117,7 +117,10 @@ static const struct stb6100_regmask stb6100_template[] = { [STB6100_TEST3] = { 0x00, 0xde }, }; -static void stb6100_normalise_regs(u8 regs[]) +/* + * Currently unused. Some boards might need it in the future + */ +static inline void stb6100_normalise_regs(u8 regs[]) { int i; @@ -157,13 +160,25 @@ static int stb6100_read_reg(struct stb6100_state *state, u8 reg) u8 regs[STB6100_NUMREGS]; int rc; + struct i2c_msg msg = { + .addr = state->config->tuner_address + reg, + .flags = I2C_M_RD, + .buf = regs, + .len = 1 + }; + + rc = i2c_transfer(state->i2c, &msg, 1); + if (unlikely(reg >= STB6100_NUMREGS)) { dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg); return -EINVAL; } - if ((rc = stb6100_read_regs(state, regs)) < 0) - return rc; - return (unsigned int)regs[reg]; + if (unlikely(verbose > FE_DEBUG)) { + dprintk(verbose, FE_DEBUG, 1, " Read from 0x%02x", state->config->tuner_address); + dprintk(verbose, FE_DEBUG, 1, " %s: 0x%02x", stb6100_regnames[reg], regs[0]); + } + + return (unsigned int)regs[0]; } static int stb6100_write_reg_range(struct stb6100_state *state, u8 buf[], int start, int len) @@ -211,20 +226,17 @@ static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data) return stb6100_write_reg_range(state, &data, reg, 1); } -static int stb6100_write_regs(struct stb6100_state *state, u8 regs[]) -{ - stb6100_normalise_regs(regs); - return stb6100_write_reg_range(state, ®s[1], 1, STB6100_NUMREGS - 1); -} static int stb6100_get_status(struct dvb_frontend *fe, u32 *status) { int rc; struct stb6100_state *state = fe->tuner_priv; - if ((rc = stb6100_read_reg(state, STB6100_LD)) < 0) + rc = stb6100_read_reg(state, STB6100_LD); + if (rc < 0) { + dprintk(verbose, FE_ERROR, 1, "%s failed", __func__); return rc; - + } return (rc & STB6100_LD_LOCK) ? TUNER_STATUS_LOCKED : 0; } @@ -234,7 +246,8 @@ static int stb6100_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) u8 f; struct stb6100_state *state = fe->tuner_priv; - if ((rc = stb6100_read_reg(state, STB6100_F)) < 0) + rc = stb6100_read_reg(state, STB6100_F); + if (rc < 0) return rc; f = rc & STB6100_F_F; @@ -265,14 +278,21 @@ static int stb6100_set_bandwidth(struct dvb_frontend *fe, u32 bandwidth) /* Turn on LPF bandwidth setting clock control, * set bandwidth, wait 10ms, turn off. */ - if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK)) < 0) + rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d | STB6100_FCCK_FCCK); + if (rc < 0) return rc; - if ((rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp)) < 0) + rc = stb6100_write_reg(state, STB6100_F, 0xc0 | tmp); + if (rc < 0) return rc; - msleep(1); - if ((rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d)) < 0) + + msleep(5); /* This is dangerous as another (related) thread may start */ + + rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d); + if (rc < 0) return rc; + msleep(10); /* This is dangerous as another (related) thread may start */ + return 0; } @@ -284,7 +304,8 @@ static int stb6100_get_frequency(struct dvb_frontend *fe, u32 *frequency) struct stb6100_state *state = fe->tuner_priv; u8 regs[STB6100_NUMREGS]; - if ((rc = stb6100_read_regs(state, regs)) < 0) + rc = stb6100_read_regs(state, regs); + if (rc < 0) return rc; odiv = (regs[STB6100_VCO] & STB6100_VCO_ODIV) >> STB6100_VCO_ODIV_SHIFT; @@ -312,8 +333,7 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) u8 regs[STB6100_NUMREGS]; u8 g, psd2, odiv; - if ((rc = stb6100_read_regs(state, regs)) < 0) - return rc; + dprintk(verbose, FE_DEBUG, 1, "Version 2010-8-14 13:51"); if (fe->ops.get_frontend) { dprintk(verbose, FE_DEBUG, 1, "Get frontend parameters"); @@ -321,96 +341,140 @@ static int stb6100_set_frequency(struct dvb_frontend *fe, u32 frequency) } srate = p.u.qpsk.symbol_rate; - regs[STB6100_DLB] = 0xdc; - /* Disable LPEN */ - regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL Loop disabled */ + /* Set up tuner cleanly, LPF calibration on */ + rc = stb6100_write_reg(state, STB6100_FCCK, 0x4d | STB6100_FCCK_FCCK); + if (rc < 0) + return rc; /* allow LPF calibration */ - if ((rc = stb6100_write_regs(state, regs)) < 0) + /* PLL Loop disabled, bias on, VCO on, synth on */ + regs[STB6100_LPEN] = 0xeb; + rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]); + if (rc < 0) return rc; - /* Baseband gain. */ - if (srate >= 15000000) - g = 9; // +4 dB - else if (srate >= 5000000) - g = 11; // +8 dB - else - g = 14; // +14 dB - - regs[STB6100_G] = (regs[STB6100_G] & ~STB6100_G_G) | g; - regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */ - regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */ + /* Program the registers with their data values */ /* VCO divide ratio (LO divide ratio, VCO prescaler enable). */ if (frequency <= 1075000) odiv = 1; else odiv = 0; - regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_ODIV) | (odiv << STB6100_VCO_ODIV_SHIFT); - if ((frequency > 1075000) && (frequency <= 1325000)) - psd2 = 0; - else - psd2 = 1; - regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT); + /* VCO enabled, seach clock off as per LL3.7, 3.4.1 */ + regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT); /* OSM */ for (ptr = lkup; (ptr->val_high != 0) && !CHKRANGE(frequency, ptr->val_low, ptr->val_high); ptr++); + if (ptr->val_high == 0) { printk(KERN_ERR "%s: frequency out of range: %u kHz\n", __func__, frequency); return -EINVAL; } regs[STB6100_VCO] = (regs[STB6100_VCO] & ~STB6100_VCO_OSM) | ptr->reg; + rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]); + if (rc < 0) + return rc; + if ((frequency > 1075000) && (frequency <= 1325000)) + psd2 = 0; + else + psd2 = 1; /* F(VCO) = F(LO) * (ODIV == 0 ? 2 : 4) */ fvco = frequency << (1 + odiv); /* N(I) = floor(f(VCO) / (f(XTAL) * (PSD2 ? 2 : 1))) */ nint = fvco / (state->reference << psd2); /* N(F) = round(f(VCO) / f(XTAL) * (PSD2 ? 2 : 1) - N(I)) * 2 ^ 9 */ nfrac = DIV_ROUND_CLOSEST((fvco - (nint * state->reference << psd2)) - << (9 - psd2), - state->reference); + << (9 - psd2), state->reference); + + /* NI */ + regs[STB6100_NI] = nint; + rc = stb6100_write_reg(state, STB6100_NI, regs[STB6100_NI]); + if (rc < 0) + return rc; + + /* NF */ + regs[STB6100_NF_LSB] = nfrac; + rc = stb6100_write_reg(state, STB6100_NF_LSB, regs[STB6100_NF_LSB]); + if (rc < 0) + return rc; + + /* K */ + regs[STB6100_K] = (0x38 & ~STB6100_K_PSD2) | (psd2 << STB6100_K_PSD2_SHIFT); + regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB); + rc = stb6100_write_reg(state, STB6100_K, regs[STB6100_K]); + if (rc < 0) + return rc; + + /* G Baseband gain. */ + if (srate >= 15000000) + g = 9; /* +4 dB */ + else if (srate >= 5000000) + g = 11; /* +8 dB */ + else + g = 14; /* +14 dB */ + + regs[STB6100_G] = (0x10 & ~STB6100_G_G) | g; + regs[STB6100_G] &= ~STB6100_G_GCT; /* mask GCT */ + regs[STB6100_G] |= (1 << 5); /* 2Vp-p Mode */ + rc = stb6100_write_reg(state, STB6100_G, regs[STB6100_G]); + if (rc < 0) + return rc; + + /* F we don't write as it is set up in BW set */ + + /* DLB set DC servo loop BW to 160Hz (LLA 3.8 / 2.1) */ + regs[STB6100_DLB] = 0xcc; + rc = stb6100_write_reg(state, STB6100_DLB, regs[STB6100_DLB]); + if (rc < 0) + return rc; + dprintk(verbose, FE_DEBUG, 1, "frequency = %u, srate = %u, g = %u, odiv = %u, psd2 = %u, fxtal = %u, osm = %u, fvco = %u, N(I) = %u, N(F) = %u", frequency, srate, (unsigned int)g, (unsigned int)odiv, (unsigned int)psd2, state->reference, ptr->reg, fvco, nint, nfrac); - regs[STB6100_NI] = nint; - regs[STB6100_NF_LSB] = nfrac; - regs[STB6100_K] = (regs[STB6100_K] & ~STB6100_K_NF_MSB) | ((nfrac >> 8) & STB6100_K_NF_MSB); - regs[STB6100_VCO] |= STB6100_VCO_OSCH; /* VCO search enabled */ - regs[STB6100_VCO] |= STB6100_VCO_OCK; /* VCO search clock off */ - regs[STB6100_FCCK] |= STB6100_FCCK_FCCK; /* LPF BW setting clock enabled */ - regs[STB6100_LPEN] &= ~STB6100_LPEN_LPEN; /* PLL loop disabled */ - /* Power up. */ - regs[STB6100_LPEN] |= STB6100_LPEN_SYNP | STB6100_LPEN_OSCP | STB6100_LPEN_BEN; - msleep(2); - if ((rc = stb6100_write_regs(state, regs)) < 0) + /* Set up the test registers */ + regs[STB6100_TEST1] = 0x8f; + rc = stb6100_write_reg(state, STB6100_TEST1, regs[STB6100_TEST1]); + if (rc < 0) + return rc; + regs[STB6100_TEST3] = 0xde; + rc = stb6100_write_reg(state, STB6100_TEST3, regs[STB6100_TEST3]); + if (rc < 0) return rc; - msleep(2); - regs[STB6100_LPEN] |= STB6100_LPEN_LPEN; /* PLL loop enabled */ - if ((rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN])) < 0) + /* Bring up tuner according to LLA 3.7 3.4.1, step 2 */ + regs[STB6100_LPEN] = 0xfb; /* PLL Loop enabled, bias on, VCO on, synth on */ + rc = stb6100_write_reg(state, STB6100_LPEN, regs[STB6100_LPEN]); + if (rc < 0) return rc; + msleep(2); + + /* Bring up tuner according to LLA 3.7 3.4.1, step 3 */ regs[STB6100_VCO] &= ~STB6100_VCO_OCK; /* VCO fast search */ - if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0) + rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]); + if (rc < 0) return rc; - msleep(10); /* wait for LO to lock */ + msleep(10); /* This is dangerous as another (related) thread may start */ /* wait for LO to lock */ + regs[STB6100_VCO] &= ~STB6100_VCO_OSCH; /* vco search disabled */ regs[STB6100_VCO] |= STB6100_VCO_OCK; /* search clock off */ - if ((rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO])) < 0) - return rc; - regs[STB6100_FCCK] &= ~STB6100_FCCK_FCCK; /* LPF BW clock disabled */ - stb6100_normalise_regs(regs); - if ((rc = stb6100_write_reg_range(state, ®s[1], 1, STB6100_NUMREGS - 3)) < 0) + rc = stb6100_write_reg(state, STB6100_VCO, regs[STB6100_VCO]); + if (rc < 0) return rc; - msleep(100); + rc = stb6100_write_reg(state, STB6100_FCCK, 0x0d); + if (rc < 0) + return rc; /* Stop LPF calibration */ + msleep(10); /* This is dangerous as another (related) thread may start */ + /* wait for stabilisation, (should not be necessary) */ return 0; } @@ -433,8 +497,8 @@ static int stb6100_init(struct dvb_frontend *fe) state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ - /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, state->bandwidth); + /* Set default bandwidth. Modified, PN 13-May-10 */ + return 0; } static int stb6100_get_state(struct dvb_frontend *fe, diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index 425e7a43ae19..4e0fc2c8a41c 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c @@ -1483,8 +1483,8 @@ static int stv090x_start_search(struct stv090x_state *state) if (STV090x_WRITE_DEMOD(state, FFECFG, 0x41) < 0) goto err; - if ((state->search_mode == STV090x_DVBS1) || - (state->search_mode == STV090x_DSS) || + if ((state->search_mode == STV090x_SEARCH_DVBS1) || + (state->search_mode == STV090x_SEARCH_DSS) || (state->search_mode == STV090x_SEARCH_AUTO)) { if (STV090x_WRITE_DEMOD(state, VITSCALE, 0x82) < 0) @@ -2940,7 +2940,7 @@ static int stv090x_optimize_track(struct stv090x_state *state) STV090x_WRITE_DEMOD(state, ERRCTRL1, 0x67); /* PER */ break; - case STV090x_UNKNOWN: + case STV090x_ERROR: default: reg = STV090x_READ_DEMOD(state, DMDCFGMD); STV090x_SETFIELD_Px(reg, DVBS1_ENABLE_FIELD, 1); |