summaryrefslogtreecommitdiff
path: root/drivers/media/common
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/ir-functions.c26
-rw-r--r--drivers/media/common/ir-keymaps.c38
-rw-r--r--drivers/media/common/saa7146_core.c4
-rw-r--r--drivers/media/common/saa7146_hlp.c2
-rw-r--r--drivers/media/common/saa7146_i2c.c34
-rw-r--r--drivers/media/common/saa7146_video.c4
-rw-r--r--drivers/media/common/tuners/Kconfig2
-rw-r--r--drivers/media/common/tuners/mxl5005s.c4
-rw-r--r--drivers/media/common/tuners/tda18271-common.c14
-rw-r--r--drivers/media/common/tuners/tda18271-fe.c53
-rw-r--r--drivers/media/common/tuners/tda18271-maps.c2
-rw-r--r--drivers/media/common/tuners/tda827x.c4
-rw-r--r--drivers/media/common/tuners/tea5761.c2
-rw-r--r--drivers/media/common/tuners/tuner-i2c.h8
-rw-r--r--drivers/media/common/tuners/tuner-simple.c6
-rw-r--r--drivers/media/common/tuners/tuner-xc2028.c114
-rw-r--r--drivers/media/common/tuners/xc5000.c39
-rw-r--r--drivers/media/common/tuners/xc5000_priv.h1
18 files changed, 220 insertions, 137 deletions
diff --git a/drivers/media/common/ir-functions.c b/drivers/media/common/ir-functions.c
index 266505207925..16792a68a449 100644
--- a/drivers/media/common/ir-functions.c
+++ b/drivers/media/common/ir-functions.c
@@ -66,7 +66,6 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
if (ir_codes)
memcpy(ir->ir_codes, ir_codes, sizeof(ir->ir_codes));
-
dev->keycode = ir->ir_codes;
dev->keycodesize = sizeof(IR_KEYTAB_TYPE);
dev->keycodemax = IR_KEYTAB_SIZE;
@@ -78,6 +77,7 @@ void ir_input_init(struct input_dev *dev, struct ir_input_state *ir,
if (repeat)
set_bit(EV_REP, dev->evbit);
}
+EXPORT_SYMBOL_GPL(ir_input_init);
void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
{
@@ -86,6 +86,7 @@ void ir_input_nokey(struct input_dev *dev, struct ir_input_state *ir)
ir_input_key_event(dev,ir);
}
}
+EXPORT_SYMBOL_GPL(ir_input_nokey);
void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
u32 ir_key, u32 ir_raw)
@@ -104,6 +105,7 @@ void ir_input_keydown(struct input_dev *dev, struct ir_input_state *ir,
ir_input_key_event(dev,ir);
}
}
+EXPORT_SYMBOL_GPL(ir_input_keydown);
/* -------------------------------------------------------------------------- */
/* extract mask bits out of data and pack them into the result */
@@ -122,6 +124,7 @@ u32 ir_extract_bits(u32 data, u32 mask)
return value;
}
+EXPORT_SYMBOL_GPL(ir_extract_bits);
static int inline getbit(u32 *samples, int bit)
{
@@ -146,6 +149,7 @@ int ir_dump_samples(u32 *samples, int count)
printk("\n");
return 0;
}
+EXPORT_SYMBOL_GPL(ir_dump_samples);
/* decode raw samples, pulse distance coding used by NEC remotes */
int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
@@ -212,6 +216,7 @@ int ir_decode_pulsedistance(u32 *samples, int count, int low, int high)
return value;
}
+EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
/* decode raw samples, biphase coding, used by rc5 for example */
int ir_decode_biphase(u32 *samples, int count, int low, int high)
@@ -253,6 +258,7 @@ int ir_decode_biphase(u32 *samples, int count, int low, int high)
}
return value;
}
+EXPORT_SYMBOL_GPL(ir_decode_biphase);
/* RC5 decoding stuff, moved from bttv-input.c to share it with
* saa7134 */
@@ -353,6 +359,7 @@ void ir_rc5_timer_end(unsigned long data)
}
}
}
+EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
void ir_rc5_timer_keyup(unsigned long data)
{
@@ -361,21 +368,4 @@ void ir_rc5_timer_keyup(unsigned long data)
dprintk(1, "ir-common: key released\n");
ir_input_nokey(ir->dev, &ir->ir);
}
-
-EXPORT_SYMBOL_GPL(ir_input_init);
-EXPORT_SYMBOL_GPL(ir_input_nokey);
-EXPORT_SYMBOL_GPL(ir_input_keydown);
-
-EXPORT_SYMBOL_GPL(ir_extract_bits);
-EXPORT_SYMBOL_GPL(ir_dump_samples);
-EXPORT_SYMBOL_GPL(ir_decode_biphase);
-EXPORT_SYMBOL_GPL(ir_decode_pulsedistance);
-
-EXPORT_SYMBOL_GPL(ir_rc5_timer_end);
EXPORT_SYMBOL_GPL(ir_rc5_timer_keyup);
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c
index a3485817e46c..8fa91f846d59 100644
--- a/drivers/media/common/ir-keymaps.c
+++ b/drivers/media/common/ir-keymaps.c
@@ -2201,3 +2201,41 @@ IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE] = {
[0x25] = KEY_POWER, /* power */
};
EXPORT_SYMBOL_GPL(ir_codes_powercolor_real_angel);
+
+IR_KEYTAB_TYPE ir_codes_avermedia_a16d[IR_KEYTAB_SIZE] = {
+ [0x20] = KEY_LIST,
+ [0x00] = KEY_POWER,
+ [0x28] = KEY_1,
+ [0x18] = KEY_2,
+ [0x38] = KEY_3,
+ [0x24] = KEY_4,
+ [0x14] = KEY_5,
+ [0x34] = KEY_6,
+ [0x2c] = KEY_7,
+ [0x1c] = KEY_8,
+ [0x3c] = KEY_9,
+ [0x12] = KEY_SUBTITLE,
+ [0x22] = KEY_0,
+ [0x32] = KEY_REWIND,
+ [0x3a] = KEY_SHUFFLE,
+ [0x02] = KEY_PRINT,
+ [0x11] = KEY_CHANNELDOWN,
+ [0x31] = KEY_CHANNELUP,
+ [0x0c] = KEY_ZOOM,
+ [0x1e] = KEY_VOLUMEDOWN,
+ [0x3e] = KEY_VOLUMEUP,
+ [0x0a] = KEY_MUTE,
+ [0x04] = KEY_AUDIO,
+ [0x26] = KEY_RECORD,
+ [0x06] = KEY_PLAY,
+ [0x36] = KEY_STOP,
+ [0x16] = KEY_PAUSE,
+ [0x2e] = KEY_REWIND,
+ [0x0e] = KEY_FASTFORWARD,
+ [0x30] = KEY_TEXT,
+ [0x21] = KEY_GREEN,
+ [0x01] = KEY_BLUE,
+ [0x08] = KEY_EPG,
+ [0x2a] = KEY_MENU,
+};
+EXPORT_SYMBOL_GPL(ir_codes_avermedia_a16d);
diff --git a/drivers/media/common/saa7146_core.c b/drivers/media/common/saa7146_core.c
index 89c7660b85d6..d01965e96927 100644
--- a/drivers/media/common/saa7146_core.c
+++ b/drivers/media/common/saa7146_core.c
@@ -233,7 +233,7 @@ void saa7146_pgtable_free(struct pci_dev *pci, struct saa7146_pgtable *pt)
int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
{
- u32 *cpu;
+ __le32 *cpu;
dma_addr_t dma_addr;
cpu = pci_alloc_consistent(pci, PAGE_SIZE, &dma_addr);
@@ -250,7 +250,7 @@ int saa7146_pgtable_alloc(struct pci_dev *pci, struct saa7146_pgtable *pt)
int saa7146_pgtable_build_single(struct pci_dev *pci, struct saa7146_pgtable *pt,
struct scatterlist *list, int sglen )
{
- u32 *ptr, fill;
+ __le32 *ptr, fill;
int nr_pages = 0;
int i,p;
diff --git a/drivers/media/common/saa7146_hlp.c b/drivers/media/common/saa7146_hlp.c
index 9c905399a233..05bde9ccb770 100644
--- a/drivers/media/common/saa7146_hlp.c
+++ b/drivers/media/common/saa7146_hlp.c
@@ -338,7 +338,7 @@ static void calculate_clipping_registers_rect(struct saa7146_dev *dev, struct sa
struct saa7146_video_dma *vdma2, u32* clip_format, u32* arbtr_ctrl, enum v4l2_field field)
{
struct saa7146_vv *vv = dev->vv_data;
- u32 *clipping = vv->d_clipping.cpu_addr;
+ __le32 *clipping = vv->d_clipping.cpu_addr;
int width = fh->ov.win.w.width;
int height = fh->ov.win.w.height;
diff --git a/drivers/media/common/saa7146_i2c.c b/drivers/media/common/saa7146_i2c.c
index 35b01ec40a51..c11da4d09cd0 100644
--- a/drivers/media/common/saa7146_i2c.c
+++ b/drivers/media/common/saa7146_i2c.c
@@ -24,7 +24,7 @@ static inline u32 saa7146_i2c_status(struct saa7146_dev *dev)
sent through the saa7146. have a look at the specifications p. 122 ff
to understand this. it returns the number of u32s to send, or -1
in case of an error. */
-static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
+static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, __le32 *op)
{
int h1, h2;
int i, j, addr;
@@ -47,7 +47,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
}
/* be careful: clear out the i2c-mem first */
- memset(op,0,sizeof(u32)*mem);
+ memset(op,0,sizeof(__le32)*mem);
/* loop through all messages */
for(i = 0; i < num; i++) {
@@ -57,16 +57,16 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
so we have to perform a translation */
addr = (m[i].addr*2) + ( (0 != (m[i].flags & I2C_M_RD)) ? 1 : 0);
h1 = op_count/3; h2 = op_count%3;
- op[h1] |= ( (u8)addr << ((3-h2)*8));
- op[h1] |= (SAA7146_I2C_START << ((3-h2)*2));
+ op[h1] |= cpu_to_le32( (u8)addr << ((3-h2)*8));
+ op[h1] |= cpu_to_le32(SAA7146_I2C_START << ((3-h2)*2));
op_count++;
/* loop through all bytes of message i */
for(j = 0; j < m[i].len; j++) {
/* insert the data bytes */
h1 = op_count/3; h2 = op_count%3;
- op[h1] |= ( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
- op[h1] |= ( SAA7146_I2C_CONT << ((3-h2)*2));
+ op[h1] |= cpu_to_le32( (u32)((u8)m[i].buf[j]) << ((3-h2)*8));
+ op[h1] |= cpu_to_le32( SAA7146_I2C_CONT << ((3-h2)*2));
op_count++;
}
@@ -75,9 +75,9 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
/* have a look at the last byte inserted:
if it was: ...CONT change it to ...STOP */
h1 = (op_count-1)/3; h2 = (op_count-1)%3;
- if ( SAA7146_I2C_CONT == (0x3 & (op[h1] >> ((3-h2)*2))) ) {
- op[h1] &= ~(0x2 << ((3-h2)*2));
- op[h1] |= (SAA7146_I2C_STOP << ((3-h2)*2));
+ if ( SAA7146_I2C_CONT == (0x3 & (le32_to_cpu(op[h1]) >> ((3-h2)*2))) ) {
+ op[h1] &= ~cpu_to_le32(0x2 << ((3-h2)*2));
+ op[h1] |= cpu_to_le32(SAA7146_I2C_STOP << ((3-h2)*2));
}
/* return the number of u32s to send */
@@ -88,7 +88,7 @@ static int saa7146_i2c_msg_prepare(const struct i2c_msg *m, int num, u32 *op)
which bytes were read through the adapter and write them back to the corresponding
i2c-message. but instead, we simply write back all bytes.
fixme: this could be improved. */
-static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
+static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, __le32 *op)
{
int i, j;
int op_count = 0;
@@ -101,7 +101,7 @@ static int saa7146_i2c_msg_cleanup(const struct i2c_msg *m, int num, u32 *op)
/* loop throgh all bytes of message i */
for(j = 0; j < m[i].len; j++) {
/* write back all bytes that could have been read */
- m[i].buf[j] = (op[op_count/3] >> ((3-(op_count%3))*8));
+ m[i].buf[j] = (le32_to_cpu(op[op_count/3]) >> ((3-(op_count%3))*8));
op_count++;
}
}
@@ -174,7 +174,7 @@ static int saa7146_i2c_reset(struct saa7146_dev *dev)
/* this functions writes out the data-byte 'dword' to the i2c-device.
it returns 0 if ok, -1 if the transfer failed, -2 if the transfer
failed badly (e.g. address error) */
-static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_delay)
+static int saa7146_i2c_writeout(struct saa7146_dev *dev, __le32 *dword, int short_delay)
{
u32 status = 0, mc2 = 0;
int trial = 0;
@@ -186,7 +186,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
if( 0 != (SAA7146_USE_I2C_IRQ & dev->ext->flags)) {
saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
- saa7146_write(dev, I2C_TRANSFER, *dword);
+ saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
dev->i2c_op = 1;
SAA7146_ISR_CLEAR(dev, MASK_16|MASK_17);
@@ -209,7 +209,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
status = saa7146_read(dev, I2C_STATUS);
} else {
saa7146_write(dev, I2C_STATUS, dev->i2c_bitrate);
- saa7146_write(dev, I2C_TRANSFER, *dword);
+ saa7146_write(dev, I2C_TRANSFER, le32_to_cpu(*dword));
saa7146_write(dev, MC2, (MASK_00 | MASK_16));
/* do not poll for i2c-status before upload is complete */
@@ -282,7 +282,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
}
/* read back data, just in case we were reading ... */
- *dword = saa7146_read(dev, I2C_TRANSFER);
+ *dword = cpu_to_le32(saa7146_read(dev, I2C_TRANSFER));
DEB_I2C(("after: 0x%08x\n",*dword));
return 0;
@@ -291,7 +291,7 @@ static int saa7146_i2c_writeout(struct saa7146_dev *dev, u32* dword, int short_d
static int saa7146_i2c_transfer(struct saa7146_dev *dev, const struct i2c_msg *msgs, int num, int retries)
{
int i = 0, count = 0;
- u32* buffer = dev->d_i2c.cpu_addr;
+ __le32 *buffer = dev->d_i2c.cpu_addr;
int err = 0;
int address_err = 0;
int short_delay = 0;
@@ -376,7 +376,7 @@ out:
/* another bug in revision 0: the i2c-registers get uploaded randomly by other
uploads, so we better clear them out before continueing */
if( 0 == dev->revision ) {
- u32 zero = 0;
+ __le32 zero = 0;
saa7146_i2c_reset(dev);
if( 0 != saa7146_i2c_writeout(dev, &zero, short_delay)) {
INFO(("revision 0 error. this should never happen.\n"));
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c
index 3cbc6ebbe649..a5e62750eea3 100644
--- a/drivers/media/common/saa7146_video.c
+++ b/drivers/media/common/saa7146_video.c
@@ -605,8 +605,8 @@ static int saa7146_pgtable_build(struct saa7146_dev *dev, struct saa7146_buf *bu
struct saa7146_pgtable *pt1 = &buf->pt[0];
struct saa7146_pgtable *pt2 = &buf->pt[1];
struct saa7146_pgtable *pt3 = &buf->pt[2];
- u32 *ptr1, *ptr2, *ptr3;
- u32 fill;
+ __le32 *ptr1, *ptr2, *ptr3;
+ __le32 fill;
int size = buf->fmt->width*buf->fmt->height;
int i,p,m1,m2,m3,o1,o2;
diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig
index d6206540476b..850d5689b14d 100644
--- a/drivers/media/common/tuners/Kconfig
+++ b/drivers/media/common/tuners/Kconfig
@@ -21,6 +21,7 @@ config MEDIA_TUNER
tristate
default VIDEO_MEDIA && I2C
depends on VIDEO_MEDIA && I2C
+ select FW_LOADER if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG
select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE
@@ -33,6 +34,7 @@ config MEDIA_TUNER
menuconfig MEDIA_TUNER_CUSTOMIZE
bool "Customize analog and hybrid tuner modules to build"
depends on MEDIA_TUNER
+ default n
help
This allows the user to deselect tuner drivers unnecessary
for their hardware from the build. Use this option with care
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index 5d05b5390f66..0dc2bef9f6a3 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -101,7 +101,7 @@ enum {
MXL_QAM,
MXL_ANALOG_CABLE,
MXL_ANALOG_OTA
-} tuner_modu_type;
+};
/* MXL5005 Tuner Register Struct */
struct TunerReg {
@@ -194,7 +194,7 @@ enum {
RFSYN_DIVM, /* 88 */
DN_BYPASS_AGC_I2C /* 89 */
#endif
-} MXL5005_ControlName;
+};
/*
* The following context is source code provided by MaxLinear.
diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c
index 42b5f5d4bfe6..6fb5b4586569 100644
--- a/drivers/media/common/tuners/tda18271-common.c
+++ b/drivers/media/common/tuners/tda18271-common.c
@@ -648,11 +648,19 @@ int tda18271_calc_rf_cal(struct dvb_frontend *fe, u32 *freq)
unsigned char *regs = priv->tda18271_regs;
u8 val;
- tda18271_lookup_map(fe, RF_CAL, freq, &val);
+ int ret = tda18271_lookup_map(fe, RF_CAL, freq, &val);
+ /* The TDA18271HD/C1 rf_cal map lookup is expected to go out of range
+ * for frequencies above 61.1 MHz. In these cases, the internal RF
+ * tracking filters calibration mechanism is used.
+ *
+ * There is no need to warn the user about this.
+ */
+ if (ret < 0)
+ goto fail;
regs[R_EB14] = val;
-
- return 0;
+fail:
+ return ret;
}
/*
diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c
index 89c01fb1f859..93063c6fbbf6 100644
--- a/drivers/media/common/tuners/tda18271-fe.c
+++ b/drivers/media/common/tuners/tda18271-fe.c
@@ -45,6 +45,21 @@ static inline int charge_pump_source(struct dvb_frontend *fe, int force)
TDA18271_MAIN_PLL, force);
}
+static inline void tda18271_set_if_notch(struct dvb_frontend *fe)
+{
+ struct tda18271_priv *priv = fe->tuner_priv;
+ unsigned char *regs = priv->tda18271_regs;
+
+ switch (priv->mode) {
+ case TDA18271_ANALOG:
+ regs[R_MPD] &= ~0x80; /* IF notch = 0 */
+ break;
+ case TDA18271_DIGITAL:
+ regs[R_MPD] |= 0x80; /* IF notch = 1 */
+ break;
+ }
+}
+
static int tda18271_channel_configuration(struct dvb_frontend *fe,
struct tda18271_std_map_item *map,
u32 freq, u32 bw)
@@ -60,25 +75,18 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
regs[R_EP3] &= ~0x1f; /* clear std bits */
regs[R_EP3] |= (map->agc_mode << 3) | map->std;
- /* set rfagc to high speed mode */
- regs[R_EP3] &= ~0x04;
+ if (priv->id == TDA18271HDC2) {
+ /* set rfagc to high speed mode */
+ regs[R_EP3] &= ~0x04;
+ }
/* set cal mode to normal */
regs[R_EP4] &= ~0x03;
- /* update IF output level & IF notch frequency */
+ /* update IF output level */
regs[R_EP4] &= ~0x1c; /* clear if level bits */
regs[R_EP4] |= (map->if_lvl << 2);
- switch (priv->mode) {
- case TDA18271_ANALOG:
- regs[R_MPD] &= ~0x80; /* IF notch = 0 */
- break;
- case TDA18271_DIGITAL:
- regs[R_MPD] |= 0x80; /* IF notch = 1 */
- break;
- }
-
/* update FM_RFn */
regs[R_EP4] &= ~0x80;
regs[R_EP4] |= map->fm_rfn << 7;
@@ -95,6 +103,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
/* disable Power Level Indicator */
regs[R_EP1] |= 0x40;
+ /* make sure thermometer is off */
+ regs[R_TM] &= ~0x10;
+
/* frequency dependent parameters */
tda18271_calc_ir_measure(fe, &freq);
@@ -135,6 +146,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
switch (priv->role) {
case TDA18271_MASTER:
tda18271_calc_main_pll(fe, N);
+ tda18271_set_if_notch(fe);
tda18271_write_regs(fe, R_MPD, 4);
break;
case TDA18271_SLAVE:
@@ -142,6 +154,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
tda18271_write_regs(fe, R_CPD, 4);
regs[R_MPD] = regs[R_CPD] & 0x7f;
+ tda18271_set_if_notch(fe);
tda18271_write_regs(fe, R_MPD, 1);
break;
}
@@ -160,12 +173,14 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe,
msleep(20);
- /* set rfagc to normal speed mode */
- if (map->fm_rfn)
- regs[R_EP3] &= ~0x04;
- else
- regs[R_EP3] |= 0x04;
- ret = tda18271_write_regs(fe, R_EP3, 1);
+ if (priv->id == TDA18271HDC2) {
+ /* set rfagc to normal speed mode */
+ if (map->fm_rfn)
+ regs[R_EP3] &= ~0x04;
+ else
+ regs[R_EP3] |= 0x04;
+ ret = tda18271_write_regs(fe, R_EP3, 1);
+ }
fail:
return ret;
}
@@ -507,7 +522,7 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe)
/* set cal mode to normal */
regs[R_EP4] &= ~0x03;
- /* update IF output level & IF notch frequency */
+ /* update IF output level */
regs[R_EP4] &= ~0x1c; /* clear if level bits */
ret = tda18271_write_regs(fe, R_EP3, 2);
diff --git a/drivers/media/common/tuners/tda18271-maps.c b/drivers/media/common/tuners/tda18271-maps.c
index 83e7561960c1..ab14ceb9e0ce 100644
--- a/drivers/media/common/tuners/tda18271-maps.c
+++ b/drivers/media/common/tuners/tda18271-maps.c
@@ -1,5 +1,5 @@
/*
- tda18271-tables.c - driver for the Philips / NXP TDA18271 silicon tuner
+ tda18271-maps.c - driver for the Philips / NXP TDA18271 silicon tuner
Copyright (C) 2007, 2008 Michael Krufky <mkrufky@linuxtv.org>
diff --git a/drivers/media/common/tuners/tda827x.c b/drivers/media/common/tuners/tda827x.c
index d30d2c9094d9..8555d9cf9051 100644
--- a/drivers/media/common/tuners/tda827x.c
+++ b/drivers/media/common/tuners/tda827x.c
@@ -418,13 +418,13 @@ static void tda827xa_lna_gain(struct dvb_frontend *fe, int high,
unsigned char buf[] = {0x22, 0x01};
int arg;
int gp_func;
- struct i2c_msg msg = { .addr = priv->cfg->switch_addr, .flags = 0,
- .buf = buf, .len = sizeof(buf) };
+ struct i2c_msg msg = { .flags = 0, .buf = buf, .len = sizeof(buf) };
if (NULL == priv->cfg) {
dprintk("tda827x_config not defined, cannot set LNA gain!\n");
return;
}
+ msg.addr = priv->cfg->switch_addr;
if (priv->cfg->config) {
if (high)
dprintk("setting LNA to high gain\n");
diff --git a/drivers/media/common/tuners/tea5761.c b/drivers/media/common/tuners/tea5761.c
index b93cdef9ac73..b23dadeecd05 100644
--- a/drivers/media/common/tuners/tea5761.c
+++ b/drivers/media/common/tuners/tea5761.c
@@ -295,7 +295,7 @@ struct dvb_frontend *tea5761_attach(struct dvb_frontend *fe,
{
struct tea5761_priv *priv = NULL;
- if (tea5761_autodetection(i2c_adap, i2c_addr) == EINVAL)
+ if (tea5761_autodetection(i2c_adap, i2c_addr) != 0)
return NULL;
priv = kzalloc(sizeof(struct tea5761_priv), GFP_KERNEL);
diff --git a/drivers/media/common/tuners/tuner-i2c.h b/drivers/media/common/tuners/tuner-i2c.h
index 3ad6c8e0b04c..cb1c7141f0c6 100644
--- a/drivers/media/common/tuners/tuner-i2c.h
+++ b/drivers/media/common/tuners/tuner-i2c.h
@@ -170,4 +170,12 @@ __fail: \
__ret; \
})
+#define hybrid_tuner_report_instance_count(state) \
+({ \
+ int __ret = 0; \
+ if (state) \
+ __ret = state->i2c_props.count; \
+ __ret; \
+})
+
#endif /* __TUNER_I2C_H__ */
diff --git a/drivers/media/common/tuners/tuner-simple.c b/drivers/media/common/tuners/tuner-simple.c
index be8d903171b7..266c255cf0d8 100644
--- a/drivers/media/common/tuners/tuner-simple.c
+++ b/drivers/media/common/tuners/tuner-simple.c
@@ -1018,8 +1018,10 @@ struct dvb_frontend *simple_tuner_attach(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 1);
if (1 != i2c_transfer(i2c_adap, &msg, 1))
- tuner_warn("unable to probe %s, proceeding anyway.",
- tuners[type].name);
+ printk(KERN_WARNING "tuner-simple %d-%04x: "
+ "unable to probe %s, proceeding anyway.",
+ i2c_adapter_id(i2c_adap), i2c_addr,
+ tuners[type].name);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
diff --git a/drivers/media/common/tuners/tuner-xc2028.c b/drivers/media/common/tuners/tuner-xc2028.c
index 9e9003cffc7f..4dd1d2421cc5 100644
--- a/drivers/media/common/tuners/tuner-xc2028.c
+++ b/drivers/media/common/tuners/tuner-xc2028.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <media/tuner.h>
#include <linux/mutex.h>
+#include <asm/unaligned.h>
#include "tuner-i2c.h"
#include "tuner-xc2028.h"
#include "tuner-xc2028-types.h"
@@ -46,7 +47,7 @@ module_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0);
MODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the "
"default firmware name\n");
-static LIST_HEAD(xc2028_list);
+static LIST_HEAD(hybrid_tuner_instance_list);
static DEFINE_MUTEX(xc2028_list_mutex);
/* struct for storing firmware table */
@@ -68,12 +69,11 @@ struct firmware_properties {
};
struct xc2028_data {
- struct list_head xc2028_list;
+ struct list_head hybrid_tuner_instance_list;
struct tuner_i2c_props i2c_props;
int (*tuner_callback) (void *dev,
int command, int arg);
void *video_dev;
- int count;
__u32 frequency;
struct firmware_description *firm;
@@ -255,7 +255,7 @@ static int load_all_firmwares(struct dvb_frontend *fe)
{
struct xc2028_data *priv = fe->tuner_priv;
const struct firmware *fw = NULL;
- unsigned char *p, *endp;
+ const unsigned char *p, *endp;
int rc = 0;
int n, n_array;
char name[33];
@@ -293,10 +293,10 @@ static int load_all_firmwares(struct dvb_frontend *fe)
name[sizeof(name) - 1] = 0;
p += sizeof(name) - 1;
- priv->firm_version = le16_to_cpu(*(__u16 *) p);
+ priv->firm_version = get_unaligned_le16(p);
p += 2;
- n_array = le16_to_cpu(*(__u16 *) p);
+ n_array = get_unaligned_le16(p);
p += 2;
tuner_info("Loading %d firmware images from %s, type: %s, ver %d.%d\n",
@@ -325,26 +325,26 @@ static int load_all_firmwares(struct dvb_frontend *fe)
}
/* Checks if there's enough bytes to read */
- if (p + sizeof(type) + sizeof(id) + sizeof(size) > endp) {
- tuner_err("Firmware header is incomplete!\n");
- goto corrupt;
- }
+ if (endp - p < sizeof(type) + sizeof(id) + sizeof(size))
+ goto header;
- type = le32_to_cpu(*(__u32 *) p);
+ type = get_unaligned_le32(p);
p += sizeof(type);
- id = le64_to_cpu(*(v4l2_std_id *) p);
+ id = get_unaligned_le64(p);
p += sizeof(id);
if (type & HAS_IF) {
- int_freq = le16_to_cpu(*(__u16 *) p);
+ int_freq = get_unaligned_le16(p);
p += sizeof(int_freq);
+ if (endp - p < sizeof(size))
+ goto header;
}
- size = le32_to_cpu(*(__u32 *) p);
+ size = get_unaligned_le32(p);
p += sizeof(size);
- if ((!size) || (size + p > endp)) {
+ if (!size || size > endp - p) {
tuner_err("Firmware type ");
dump_firm_type(type);
printk("(%x), id %llx is corrupted "
@@ -383,6 +383,8 @@ static int load_all_firmwares(struct dvb_frontend *fe)
goto done;
+header:
+ tuner_err("Firmware header is incomplete!\n");
corrupt:
rc = -EINVAL;
tuner_err("Error: firmware file is corrupted!\n");
@@ -1072,20 +1074,19 @@ static int xc2028_dvb_release(struct dvb_frontend *fe)
mutex_lock(&xc2028_list_mutex);
- priv->count--;
-
- if (!priv->count) {
- list_del(&priv->xc2028_list);
-
+ /* only perform final cleanup if this is the last instance */
+ if (hybrid_tuner_report_instance_count(priv) == 1) {
kfree(priv->ctrl.fname);
-
free_firmware(priv);
- kfree(priv);
- fe->tuner_priv = NULL;
}
+ if (priv)
+ hybrid_tuner_release_state(priv);
+
mutex_unlock(&xc2028_list_mutex);
+ fe->tuner_priv = NULL;
+
return 0;
}
@@ -1150,7 +1151,7 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
struct xc2028_config *cfg)
{
struct xc2028_data *priv;
- void *video_dev;
+ int instance;
if (debug)
printk(KERN_DEBUG "xc2028: Xcv2028/3028 init called!\n");
@@ -1163,48 +1164,40 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
return NULL;
}
- video_dev = cfg->i2c_adap->algo_data;
-
- if (debug)
- printk(KERN_DEBUG "xc2028: video_dev =%p\n", video_dev);
-
mutex_lock(&xc2028_list_mutex);
- list_for_each_entry(priv, &xc2028_list, xc2028_list) {
- if (&priv->i2c_props.adap->dev == &cfg->i2c_adap->dev) {
- video_dev = NULL;
- if (debug)
- printk(KERN_DEBUG "xc2028: reusing device\n");
-
- break;
- }
- }
-
- if (video_dev) {
- priv = kzalloc(sizeof(*priv), GFP_KERNEL);
- if (priv == NULL) {
- mutex_unlock(&xc2028_list_mutex);
- return NULL;
- }
-
- priv->i2c_props.addr = cfg->i2c_addr;
- priv->i2c_props.adap = cfg->i2c_adap;
- priv->i2c_props.name = "xc2028";
-
- priv->video_dev = video_dev;
+ instance = hybrid_tuner_request_state(struct xc2028_data, priv,
+ hybrid_tuner_instance_list,
+ cfg->i2c_adap, cfg->i2c_addr,
+ "xc2028");
+ switch (instance) {
+ case 0:
+ /* memory allocation failure */
+ goto fail;
+ break;
+ case 1:
+ /* new tuner instance */
priv->tuner_callback = cfg->callback;
priv->ctrl.max_len = 13;
mutex_init(&priv->lock);
- list_add_tail(&priv->xc2028_list, &xc2028_list);
- }
-
- fe->tuner_priv = priv;
- priv->count++;
+ /* analog side (tuner-core) uses i2c_adap->algo_data.
+ * digital side is not guaranteed to have algo_data defined.
+ *
+ * digital side will always have fe->dvb defined.
+ * analog side (tuner-core) doesn't (yet) define fe->dvb.
+ */
+ priv->video_dev = ((fe->dvb) && (fe->dvb->priv)) ?
+ fe->dvb->priv : cfg->i2c_adap->algo_data;
- if (debug)
- printk(KERN_DEBUG "xc2028: usage count is %i\n", priv->count);
+ fe->tuner_priv = priv;
+ break;
+ case 2:
+ /* existing tuner instance */
+ fe->tuner_priv = priv;
+ break;
+ }
memcpy(&fe->ops.tuner_ops, &xc2028_dvb_tuner_ops,
sizeof(xc2028_dvb_tuner_ops));
@@ -1217,6 +1210,11 @@ struct dvb_frontend *xc2028_attach(struct dvb_frontend *fe,
mutex_unlock(&xc2028_list_mutex);
return fe;
+fail:
+ mutex_unlock(&xc2028_list_mutex);
+
+ xc2028_dvb_release(fe);
+ return NULL;
}
EXPORT_SYMBOL(xc2028_attach);
diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c
index ceae6db901ec..5f99de0ad612 100644
--- a/drivers/media/common/tuners/xc5000.c
+++ b/drivers/media/common/tuners/xc5000.c
@@ -36,6 +36,10 @@ static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
+static int xc5000_load_fw_on_attach;
+module_param_named(init_fw, xc5000_load_fw_on_attach, int, 0644);
+MODULE_PARM_DESC(init_fw, "Load firmware during driver initialization.");
+
#define dprintk(level,fmt, arg...) if (debug >= level) \
printk(KERN_INFO "%s: " fmt, "xc5000", ## arg)
@@ -177,6 +181,7 @@ static XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
{"FM Radio-INPUT1", 0x0208, 0x9002}
};
+static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
static int xc5000_writeregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static int xc5000_readregs(struct xc5000_priv *priv, u8 *buf, u8 len);
static void xc5000_TunerReset(struct dvb_frontend *fe);
@@ -277,7 +282,7 @@ static int xc_read_reg(struct xc5000_priv *priv, u16 regAddr, u16 *i2cData)
return result;
}
-static int xc_load_i2c_sequence(struct dvb_frontend *fe, u8 i2c_sequence[])
+static int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence)
{
struct xc5000_priv *priv = fe->tuner_priv;
@@ -352,7 +357,7 @@ static int xc_SetTVStandard(struct xc5000_priv *priv,
static int xc_shutdown(struct xc5000_priv *priv)
{
- return 0;
+ return XC_RESULT_SUCCESS;
/* Fixme: cannot bring tuner back alive once shutdown
* without reloading the driver modules.
* return xc_write_reg(priv, XREG_POWER_DOWN, 0);
@@ -685,6 +690,25 @@ static int xc5000_set_params(struct dvb_frontend *fe,
return 0;
}
+static int xc5000_is_firmware_loaded(struct dvb_frontend *fe)
+{
+ struct xc5000_priv *priv = fe->tuner_priv;
+ int ret;
+ u16 id;
+
+ ret = xc5000_readreg(priv, XREG_PRODUCT_ID, &id);
+ if (ret == XC_RESULT_SUCCESS) {
+ if (id == XC_PRODUCT_ID_FW_NOT_LOADED)
+ ret = XC_RESULT_RESET_FAILURE;
+ else
+ ret = XC_RESULT_SUCCESS;
+ }
+
+ dprintk(1, "%s() returns %s id = 0x%x\n", __func__,
+ ret == XC_RESULT_SUCCESS ? "True" : "False", id);
+ return ret;
+}
+
static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
static int xc5000_set_analog_params(struct dvb_frontend *fe,
@@ -693,7 +717,7 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
struct xc5000_priv *priv = fe->tuner_priv;
int ret;
- if(priv->fwloaded == 0)
+ if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS)
xc_load_fw_and_init_tuner(fe);
dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
@@ -808,11 +832,10 @@ static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
struct xc5000_priv *priv = fe->tuner_priv;
int ret = 0;
- if (priv->fwloaded == 0) {
+ if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
ret = xc5000_fwupload(fe);
if (ret != XC_RESULT_SUCCESS)
return ret;
- priv->fwloaded = 1;
}
/* Start the tuner self-calibration process */
@@ -852,7 +875,6 @@ static int xc5000_sleep(struct dvb_frontend *fe)
return -EREMOTEIO;
}
else {
- /* priv->fwloaded = 0; */
return XC_RESULT_SUCCESS;
}
}
@@ -933,7 +955,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
cfg->i2c_address);
printk(KERN_INFO
"xc5000: Firmware has been loaded previously\n");
- priv->fwloaded = 1;
break;
case XC_PRODUCT_ID_FW_NOT_LOADED:
printk(KERN_INFO
@@ -941,7 +962,6 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
cfg->i2c_address);
printk(KERN_INFO
"xc5000: Firmware has not been loaded previously\n");
- priv->fwloaded = 0;
break;
default:
printk(KERN_ERR
@@ -956,6 +976,9 @@ struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe,
fe->tuner_priv = priv;
+ if (xc5000_load_fw_on_attach)
+ xc5000_init(fe);
+
return fe;
}
EXPORT_SYMBOL(xc5000_attach);
diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h
index ecebfe4745ad..a72a9887fe7f 100644
--- a/drivers/media/common/tuners/xc5000_priv.h
+++ b/drivers/media/common/tuners/xc5000_priv.h
@@ -30,7 +30,6 @@ struct xc5000_priv {
u32 bandwidth;
u8 video_standard;
u8 rf_mode;
- u8 fwloaded;
void *devptr;
};