aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/common
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/common')
-rw-r--r--drivers/media/common/tuners/mxl5005s.c414
-rw-r--r--drivers/media/common/tuners/mxl5005s.h48
2 files changed, 248 insertions, 214 deletions
diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c
index aad88d5c0dc2..f7ed9a72db4a 100644
--- a/drivers/media/common/tuners/mxl5005s.c
+++ b/drivers/media/common/tuners/mxl5005s.c
@@ -1,26 +1,62 @@
1/* 1/*
2 * For the Realtek RTL chip RTL2831U 2 MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
3 * Realtek Release Date: 2008-03-14, ver 080314 3
4 * Realtek version RTL2831 Linux driver version 080314 4 Copyright (C) 2008 MaxLinear
5 * ver 080314 5 Copyright (C) 2006 Steven Toth <stoth@hauppauge.com>
6 * 6 Functions:
7 * for linux kernel version 2.6.21.4 - 2.6.22-14 7 mxl5005s_reset()
8 * support MXL5005s and MT2060 tuners (support tuner auto-detecting) 8 mxl5005s_writereg()
9 * support two IR types -- RC5 and NEC 9 mxl5005s_writeregs()
10 * 10 mxl5005s_init()
11 * Known boards with Realtek RTL chip RTL2821U 11 mxl5005s_reconfigure()
12 * Freecom USB stick 14aa:0160 (version 4) 12 mxl5005s_AssignTunerMode()
13 * Conceptronic CTVDIGRCU 13 mxl5005s_set_params()
14 * 14 mxl5005s_get_frequency()
15 * Copyright (c) 2008 Realtek 15 mxl5005s_get_bandwidth()
16 * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper 16 mxl5005s_release()
17 * This code is placed under the terms of the GNU General Public License 17 mxl5005s_attach()
18 * 18
19 * Released by Realtek under GPLv2. 19 Copyright (c) 2008 Realtek
20 * Thanks to Realtek for a lot of support we received ! 20 Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper
21 * 21 Functions:
22 * Revision: 080314 - original version 22 mxl5005s_SetRfFreqHz()
23 */ 23
24 This program is free software; you can redistribute it and/or modify
25 it under the terms of the GNU General Public License as published by
26 the Free Software Foundation; either version 2 of the License, or
27 (at your option) any later version.
28
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
33
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37
38*/
39
40/*
41 History of this driver (Steven Toth):
42 I was given a public release of a linux driver that included
43 support for the MaxLinear MXL5005S silicon tuner. Analysis of
44 the tuner driver showed clearly three things.
45
46 1. The tuner driver didn't support the LinuxTV tuner API
47 so the code Realtek added had to be removed.
48
49 2. A significant amount of the driver is reference driver code
50 from MaxLinear, I felt it was important to identify and
51 preserve this.
52
53 3. New code has to be added to interface correctly with the
54 LinuxTV API, as a regular kernel module.
55
56 Other than the reference driver enum's, I've clearly marked
57 sections of the code and retained the copyright of the
58 respective owners.
59*/
24 60
25#include "mxl5005s.h" 61#include "mxl5005s.h"
26 62
@@ -250,9 +286,12 @@ struct mxl5005s_state
250 struct mxl5005s_config *config; 286 struct mxl5005s_config *config;
251 struct dvb_frontend *frontend; 287 struct dvb_frontend *frontend;
252 struct i2c_adapter *i2c; 288 struct i2c_adapter *i2c;
289
290 /* Cache values */
291 u32 current_mode;
292
253}; 293};
254 294
255// funcs
256u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); 295u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value);
257u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); 296u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value);
258u16 MXL_GetMasterControl(u8 *MasterReg, int state); 297u16 MXL_GetMasterControl(u8 *MasterReg, int state);
@@ -269,9 +308,22 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq);
269void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); 308void MXL_SynthIFLO_Calc(struct dvb_frontend *fe);
270void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); 309void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe);
271u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); 310u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count);
272int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen); 311int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len);
273u16 MXL_IFSynthInit(struct dvb_frontend *fe); 312u16 MXL_IFSynthInit(struct dvb_frontend *fe);
274int mxl5005s_AssignTunerMode(struct dvb_frontend *fe); 313int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth);
314int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth);
315
316/* ----------------------------------------------------------------
317 * Begin: Custom code salvaged from the Realtek driver.
318 * Copyright (c) 2008 Realtek
319 * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper
320 * This code is placed under the terms of the GNU General Public License
321 *
322 * Released by Realtek under GPLv2.
323 * Thanks to Realtek for a lot of support we received !
324 *
325 * Revision: 080314 - original version
326 */
275 327
276int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) 328int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
277{ 329{
@@ -292,7 +344,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
292 AddrTable[0] = MASTER_CONTROL_ADDR; 344 AddrTable[0] = MASTER_CONTROL_ADDR;
293 ByteTable[0] |= state->config->AgcMasterByte; 345 ByteTable[0] |= state->config->AgcMasterByte;
294 346
295 mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); 347 mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
296 348
297 // Tuner RF frequency setting stage 1 349 // Tuner RF frequency setting stage 1
298 MXL_TuneRF(fe, RfFreqHz); 350 MXL_TuneRF(fe, RfFreqHz);
@@ -309,7 +361,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
309 ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte; 361 ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte;
310 TableLen += 1; 362 TableLen += 1;
311 363
312 mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); 364 mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
313 365
314 // Wait 30 ms. 366 // Wait 30 ms.
315 msleep(150); 367 msleep(150);
@@ -324,118 +376,18 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz)
324 ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ; 376 ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ;
325 TableLen += 1; 377 TableLen += 1;
326 378
327 mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); 379 mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
328 380
329 msleep(100); 381 msleep(100);
330 382
331 return 0; 383 return 0;
332} 384}
385/* End: Custom code taken from the Realtek driver */
333 386
334static int mxl5005s_reset(struct dvb_frontend *fe) 387/* ----------------------------------------------------------------
335{ 388 * Begin: Reference driver code found in the Realtek driver.
336 struct mxl5005s_state *state = fe->tuner_priv; 389 * Copyright (c) 2008 MaxLinear
337 int ret = 0; 390 */
338
339 u8 buf[2] = { 0xff, 0x00 };
340 struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
341 .buf = buf, .len = 2 };
342
343 dprintk(2, "%s()\n", __func__);
344
345 if (fe->ops.i2c_gate_ctrl)
346 fe->ops.i2c_gate_ctrl(fe, 1);
347
348 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
349 printk(KERN_WARNING "mxl5005s I2C reset failed\n");
350 ret = -EREMOTEIO;
351 }
352
353 if (fe->ops.i2c_gate_ctrl)
354 fe->ops.i2c_gate_ctrl(fe, 0);
355
356 return ret;
357}
358
359/* Write a single byte to a single reg */
360static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch)
361{
362 struct mxl5005s_state *state = fe->tuner_priv;
363 u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE };
364 struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
365 .buf = buf, .len = 3 };
366
367 if(latch == 0)
368 msg.len = 2;
369
370 dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr);
371
372 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
373 printk(KERN_WARNING "mxl5005s I2C write failed\n");
374 return -EREMOTEIO;
375 }
376 return 0;
377}
378
379int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen)
380{
381 int i, ret = 0;
382
383 if (fe->ops.i2c_gate_ctrl)
384 fe->ops.i2c_gate_ctrl(fe, 1);
385
386 for( i = 0 ; i < TableLen - 1 ; i++)
387 {
388 ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 0);
389 if (ret < 0)
390 break;
391 }
392
393 ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 1);
394
395 if (fe->ops.i2c_gate_ctrl)
396 fe->ops.i2c_gate_ctrl(fe, 0);
397
398 return ret;
399}
400
401int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe,
402 unsigned char RegAddr,
403 unsigned char Msb,
404 unsigned char Lsb,
405 const unsigned char WritingValue
406 )
407{
408 int i;
409
410 unsigned char Mask;
411 unsigned char Shift;
412 unsigned char RegByte;
413
414 /* Generate mask and shift according to MSB and LSB. */
415 Mask = 0;
416 for(i = Lsb; i < (unsigned char)(Msb + 1); i++)
417 Mask |= 0x1 << i;
418
419 Shift = Lsb;
420
421 /* Get tuner register byte according to register adddress. */
422 MXL_RegRead(fe, RegAddr, &RegByte);
423
424 /* Reserve register byte unmask bit with mask and inlay writing value into it. */
425 RegByte &= ~Mask;
426 RegByte |= (WritingValue << Shift) & Mask;
427
428 /* Update tuner register byte table. */
429 MXL_RegWrite(fe, RegAddr, RegByte);
430
431 /* Write tuner register byte with writing byte. */
432 return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1);
433}
434
435
436// The following context is source code provided by MaxLinear.
437// MaxLinear source code - MXL5005_Initialize.cpp
438// DONE
439u16 MXL5005_RegisterInit(struct dvb_frontend *fe) 391u16 MXL5005_RegisterInit(struct dvb_frontend *fe)
440{ 392{
441 struct mxl5005s_state *state = fe->tuner_priv; 393 struct mxl5005s_state *state = fe->tuner_priv;
@@ -757,7 +709,6 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe)
757 return 0 ; 709 return 0 ;
758} 710}
759 711
760// DONE
761u16 MXL5005_ControlInit(struct dvb_frontend *fe) 712u16 MXL5005_ControlInit(struct dvb_frontend *fe)
762{ 713{
763 struct mxl5005s_state *state = fe->tuner_priv; 714 struct mxl5005s_state *state = fe->tuner_priv;
@@ -1701,7 +1652,6 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe)
1701// MaxLinear source code - MXL5005_c.cpp 1652// MaxLinear source code - MXL5005_c.cpp
1702// MXL5005.cpp : Defines the initialization routines for the DLL. 1653// MXL5005.cpp : Defines the initialization routines for the DLL.
1703// 2.6.12 1654// 2.6.12
1704// DONE
1705void InitTunerControls(struct dvb_frontend *fe) 1655void InitTunerControls(struct dvb_frontend *fe)
1706{ 1656{
1707 MXL5005_RegisterInit(fe); 1657 MXL5005_RegisterInit(fe);
@@ -1744,7 +1694,6 @@ void InitTunerControls(struct dvb_frontend *fe)
1744// > 0 : Failed // 1694// > 0 : Failed //
1745// // 1695// //
1746/////////////////////////////////////////////////////////////////////////////// 1696///////////////////////////////////////////////////////////////////////////////
1747// DONE
1748u16 MXL5005_TunerConfig(struct dvb_frontend *fe, 1697u16 MXL5005_TunerConfig(struct dvb_frontend *fe,
1749 u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ 1698 u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */
1750 u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ 1699 u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */
@@ -1814,7 +1763,6 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe,
1814// > 0 : Failed // 1763// > 0 : Failed //
1815// // 1764// //
1816/////////////////////////////////////////////////////////////////////////////// 1765///////////////////////////////////////////////////////////////////////////////
1817// DONE
1818void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) 1766void MXL_SynthIFLO_Calc(struct dvb_frontend *fe)
1819{ 1767{
1820 struct mxl5005s_state *state = fe->tuner_priv; 1768 struct mxl5005s_state *state = fe->tuner_priv;
@@ -1853,7 +1801,6 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe)
1853// > 0 : Failed // 1801// > 0 : Failed //
1854// // 1802// //
1855/////////////////////////////////////////////////////////////////////////////// 1803///////////////////////////////////////////////////////////////////////////////
1856// DONE
1857void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) 1804void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe)
1858{ 1805{
1859 struct mxl5005s_state *state = fe->tuner_priv; 1806 struct mxl5005s_state *state = fe->tuner_priv;
@@ -1892,7 +1839,6 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe)
1892// > 0 : Failed // 1839// > 0 : Failed //
1893// // 1840// //
1894/////////////////////////////////////////////////////////////////////////////// 1841///////////////////////////////////////////////////////////////////////////////
1895// DONE
1896u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) 1842u16 MXL_OverwriteICDefault(struct dvb_frontend *fe)
1897{ 1843{
1898 u16 status = 0; 1844 u16 status = 0;
@@ -1930,7 +1876,6 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe)
1930// > 0 : Failed // 1876// > 0 : Failed //
1931// // 1877// //
1932/////////////////////////////////////////////////////////////////////////////// 1878///////////////////////////////////////////////////////////////////////////////
1933// DONE
1934u16 MXL_BlockInit(struct dvb_frontend *fe) 1879u16 MXL_BlockInit(struct dvb_frontend *fe)
1935{ 1880{
1936 struct mxl5005s_state *state = fe->tuner_priv; 1881 struct mxl5005s_state *state = fe->tuner_priv;
@@ -3687,7 +3632,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq)
3687 return status ; 3632 return status ;
3688} 3633}
3689 3634
3690// DONE
3691u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) 3635u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val)
3692{ 3636{
3693 u16 status = 0; 3637 u16 status = 0;
@@ -3754,7 +3698,6 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val)
3754// >0 : Value exceed maximum allowed for control number // 3698// >0 : Value exceed maximum allowed for control number //
3755// // 3699// //
3756/////////////////////////////////////////////////////////////////////////////// 3700///////////////////////////////////////////////////////////////////////////////
3757// DONE
3758u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) 3701u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value)
3759{ 3702{
3760 u16 status = 0; 3703 u16 status = 0;
@@ -3795,7 +3738,6 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value)
3795// 2 : Control name not found // 3738// 2 : Control name not found //
3796// // 3739// //
3797/////////////////////////////////////////////////////////////////////////////// 3740///////////////////////////////////////////////////////////////////////////////
3798// DONE
3799u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) 3741u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup)
3800{ 3742{
3801 struct mxl5005s_state *state = fe->tuner_priv; 3743 struct mxl5005s_state *state = fe->tuner_priv;
@@ -3902,7 +3844,6 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u
3902// -1 : Invalid Register Address // 3844// -1 : Invalid Register Address //
3903// // 3845// //
3904/////////////////////////////////////////////////////////////////////////////// 3846///////////////////////////////////////////////////////////////////////////////
3905// DONE
3906u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) 3847u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal)
3907{ 3848{
3908 struct mxl5005s_state *state = fe->tuner_priv; 3849 struct mxl5005s_state *state = fe->tuner_priv;
@@ -3942,7 +3883,6 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal)
3942// -1 : Invalid Register Address // 3883// -1 : Invalid Register Address //
3943// // 3884// //
3944/////////////////////////////////////////////////////////////////////////////// 3885///////////////////////////////////////////////////////////////////////////////
3945// DONE
3946u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) 3886u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal)
3947{ 3887{
3948 struct mxl5005s_state *state = fe->tuner_priv; 3888 struct mxl5005s_state *state = fe->tuner_priv;
@@ -3979,7 +3919,6 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal)
3979// -1 : Invalid control name // 3919// -1 : Invalid control name //
3980// // 3920// //
3981/////////////////////////////////////////////////////////////////////////////// 3921///////////////////////////////////////////////////////////////////////////////
3982// DONE
3983u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) 3922u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value)
3984{ 3923{
3985 struct mxl5005s_state *state = fe->tuner_priv; 3924 struct mxl5005s_state *state = fe->tuner_priv;
@@ -4051,7 +3990,6 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value)
4051// -1 : Invalid control name // 3990// -1 : Invalid control name //
4052// // 3991// //
4053/////////////////////////////////////////////////////////////////////////////// 3992///////////////////////////////////////////////////////////////////////////////
4054// DONE
4055u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count) 3993u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count)
4056{ 3994{
4057 struct mxl5005s_state *state = fe->tuner_priv; 3995 struct mxl5005s_state *state = fe->tuner_priv;
@@ -4157,7 +4095,6 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int
4157// NONE // 4095// NONE //
4158// // 4096// //
4159/////////////////////////////////////////////////////////////////////////////// 4097///////////////////////////////////////////////////////////////////////////////
4160// DONE
4161void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) 4098void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal)
4162{ 4099{
4163 struct mxl5005s_state *state = fe->tuner_priv; 4100 struct mxl5005s_state *state = fe->tuner_priv;
@@ -4205,7 +4142,6 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal)
4205// Computed value // 4142// Computed value //
4206// // 4143// //
4207/////////////////////////////////////////////////////////////////////////////// 4144///////////////////////////////////////////////////////////////////////////////
4208// DONE
4209u32 MXL_Ceiling(u32 value, u32 resolution) 4145u32 MXL_Ceiling(u32 value, u32 resolution)
4210{ 4146{
4211 return (value/resolution + (value % resolution > 0 ? 1 : 0)); 4147 return (value/resolution + (value % resolution > 0 ? 1 : 0));
@@ -4214,7 +4150,6 @@ u32 MXL_Ceiling(u32 value, u32 resolution)
4214// 4150//
4215// Retrieve the Initialzation Registers 4151// Retrieve the Initialzation Registers
4216// 4152//
4217// DONE
4218u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) 4153u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
4219{ 4154{
4220 u16 status = 0; 4155 u16 status = 0;
@@ -4237,7 +4172,6 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c
4237 return status; 4172 return status;
4238} 4173}
4239 4174
4240// DONE
4241u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) 4175u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
4242{ 4176{
4243 u16 status = 0; 4177 u16 status = 0;
@@ -4265,7 +4199,6 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou
4265 return status; 4199 return status;
4266} 4200}
4267 4201
4268// DONE
4269u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) 4202u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
4270{ 4203{
4271 u16 status = 0; 4204 u16 status = 0;
@@ -4283,7 +4216,6 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i
4283 return status; 4216 return status;
4284} 4217}
4285 4218
4286// DONE
4287u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) 4219u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count)
4288{ 4220{
4289 u16 status = 0; 4221 u16 status = 0;
@@ -4301,7 +4233,6 @@ u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, in
4301 return status; 4233 return status;
4302} 4234}
4303 4235
4304// DONE
4305u16 MXL_GetMasterControl(u8 *MasterReg, int state) 4236u16 MXL_GetMasterControl(u8 *MasterReg, int state)
4306{ 4237{
4307 if (state == 1) /* Load_Start */ 4238 if (state == 1) /* Load_Start */
@@ -4446,7 +4377,6 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range)
4446 return status; 4377 return status;
4447} 4378}
4448 4379
4449// DONE
4450u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) 4380u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
4451{ 4381{
4452 struct mxl5005s_state *state = fe->tuner_priv; 4382 struct mxl5005s_state *state = fe->tuner_priv;
@@ -4457,20 +4387,99 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis)
4457 4387
4458 return status; 4388 return status;
4459} 4389}
4460
4461#endif 4390#endif
4391/* End: Reference driver code found in the Realtek driver that
4392 * is copyright MaxLinear */
4393
4394/* ----------------------------------------------------------------
4395 * Begin: Everything after here is new code to adapt the
4396 * proprietary Realtek driver into a Linux API tuner.
4397 * Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
4398 */
4399static int mxl5005s_reset(struct dvb_frontend *fe)
4400{
4401 struct mxl5005s_state *state = fe->tuner_priv;
4402 int ret = 0;
4403
4404 u8 buf[2] = { 0xff, 0x00 };
4405 struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
4406 .buf = buf, .len = 2 };
4407
4408 dprintk(2, "%s()\n", __func__);
4409
4410 if (fe->ops.i2c_gate_ctrl)
4411 fe->ops.i2c_gate_ctrl(fe, 1);
4412
4413 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
4414 printk(KERN_WARNING "mxl5005s I2C reset failed\n");
4415 ret = -EREMOTEIO;
4416 }
4417
4418 if (fe->ops.i2c_gate_ctrl)
4419 fe->ops.i2c_gate_ctrl(fe, 0);
4420
4421 return ret;
4422}
4423
4424/* Write a single byte to a single reg, latch the value if required by
4425 * following the transaction with the latch byte.
4426 */
4427static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch)
4428{
4429 struct mxl5005s_state *state = fe->tuner_priv;
4430 u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE };
4431 struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0,
4432 .buf = buf, .len = 3 };
4433
4434 if (latch == 0)
4435 msg.len = 2;
4436
4437 dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr);
4438
4439 if (i2c_transfer(state->i2c, &msg, 1) != 1) {
4440 printk(KERN_WARNING "mxl5005s I2C write failed\n");
4441 return -EREMOTEIO;
4442 }
4443 return 0;
4444}
4445
4446int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len)
4447{
4448 int ret = 0, i;
4449
4450 if (fe->ops.i2c_gate_ctrl)
4451 fe->ops.i2c_gate_ctrl(fe, 1);
4452
4453 for (i = 0 ; i < len-1; i++) {
4454 ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0);
4455 if (ret < 0)
4456 break;
4457 }
4458
4459 ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1);
4460
4461 if (fe->ops.i2c_gate_ctrl)
4462 fe->ops.i2c_gate_ctrl(fe, 0);
4463
4464 return ret;
4465}
4462 4466
4463/* Linux driver related functions */
4464 4467
4465int mxl5005s_init(struct dvb_frontend *fe) 4468int mxl5005s_init(struct dvb_frontend *fe)
4466{ 4469{
4470 dprintk(1, "%s()\n", __func__);
4471 return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ);
4472}
4473
4474int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth)
4475{
4467 struct mxl5005s_state *state = fe->tuner_priv; 4476 struct mxl5005s_state *state = fe->tuner_priv;
4468 4477
4469 u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; 4478 u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
4470 u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; 4479 u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX];
4471 int TableLen; 4480 int TableLen;
4472 4481
4473 dprintk(1, "%s()\n", __func__); 4482 dprintk(1, "%s(type=%d, bw=%d)\n", __func__, mod_type, bandwidth);
4474 4483
4475 mxl5005s_reset(fe); 4484 mxl5005s_reset(fe);
4476 4485
@@ -4479,19 +4488,19 @@ int mxl5005s_init(struct dvb_frontend *fe)
4479 AddrTable[0] = MASTER_CONTROL_ADDR; 4488 AddrTable[0] = MASTER_CONTROL_ADDR;
4480 ByteTable[0] |= state->config->AgcMasterByte; 4489 ByteTable[0] |= state->config->AgcMasterByte;
4481 4490
4482 mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); 4491 mxl5005s_writeregs(fe, AddrTable, ByteTable, 1);
4483 4492
4484 mxl5005s_AssignTunerMode(fe); // tunre_config 4493 mxl5005s_AssignTunerMode(fe, mod_type, bandwidth);
4485 4494
4486 /* Tuner initialization stage 1 */ 4495 /* Tuner initialization stage 1 */
4487 MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); 4496 MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen);
4488 4497
4489 mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); 4498 mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen);
4490 4499
4491 return 0; 4500 return 0;
4492} 4501}
4493 4502
4494int mxl5005s_AssignTunerMode(struct dvb_frontend *fe) 4503int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth)
4495{ 4504{
4496 struct mxl5005s_state *state = fe->tuner_priv; 4505 struct mxl5005s_state *state = fe->tuner_priv;
4497 struct mxl5005s_config *c = state->config; 4506 struct mxl5005s_config *c = state->config;
@@ -4503,7 +4512,7 @@ int mxl5005s_AssignTunerMode(struct dvb_frontend *fe)
4503 fe, 4512 fe,
4504 c->mod_mode, 4513 c->mod_mode,
4505 c->if_mode, 4514 c->if_mode,
4506 MXL5005S_BANDWIDTH_6MHZ, 4515 bandwidth,
4507 c->if_freq, 4516 c->if_freq,
4508 c->xtal_freq, 4517 c->xtal_freq,
4509 c->agc_mode, 4518 c->agc_mode,
@@ -4513,7 +4522,7 @@ int mxl5005s_AssignTunerMode(struct dvb_frontend *fe)
4513 c->div_out, 4522 c->div_out,
4514 c->cap_select, 4523 c->cap_select,
4515 c->rssi_enable, 4524 c->rssi_enable,
4516 MXL_QAM, 4525 mod_type,
4517 c->tracking_filter); 4526 c->tracking_filter);
4518 4527
4519 return 0; 4528 return 0;
@@ -4522,22 +4531,62 @@ int mxl5005s_AssignTunerMode(struct dvb_frontend *fe)
4522static int mxl5005s_set_params(struct dvb_frontend *fe, 4531static int mxl5005s_set_params(struct dvb_frontend *fe,
4523 struct dvb_frontend_parameters *params) 4532 struct dvb_frontend_parameters *params)
4524{ 4533{
4525 u32 freq; 4534 struct mxl5005s_state *state = fe->tuner_priv;
4526 u32 bw; 4535 u32 req_mode, req_bw = 0;
4536 int ret;
4527 4537
4528 if (fe->ops.info.type == FE_OFDM) 4538 dprintk(1, "%s()\n", __func__);
4529 bw = params->u.ofdm.bandwidth; 4539
4530 else 4540 if (fe->ops.info.type == FE_ATSC) {
4531 bw = MXL5005S_BANDWIDTH_6MHZ; 4541 switch (params->u.vsb.modulation) {
4542 case VSB_8:
4543 req_mode = MXL_ATSC; break;
4544 default:
4545 case QAM_64:
4546 case QAM_256:
4547 case QAM_AUTO:
4548 req_mode = MXL_QAM; break;
4549 }
4550 }
4551 else req_mode = MXL_DVBT;
4552
4553 /* Change tuner for new modulation type if reqd */
4554 if (req_mode != state->current_mode) {
4555 switch (req_mode) {
4556 case VSB_8:
4557 case QAM_64:
4558 case QAM_256:
4559 case QAM_AUTO:
4560 req_bw = MXL5005S_BANDWIDTH_6MHZ;
4561 break;
4562 default:
4563 /* Assume DVB-T */
4564 switch (params->u.ofdm.bandwidth) {
4565 case BANDWIDTH_6_MHZ:
4566 req_bw = MXL5005S_BANDWIDTH_6MHZ;
4567 break;
4568 case BANDWIDTH_7_MHZ:
4569 req_bw = MXL5005S_BANDWIDTH_7MHZ;
4570 break;
4571 case BANDWIDTH_AUTO:
4572 case BANDWIDTH_8_MHZ:
4573 req_bw = MXL5005S_BANDWIDTH_8MHZ;
4574 break;
4575 }
4576 }
4532 4577
4533 freq = params->frequency; /* Hz */ 4578 state->current_mode = req_mode;
4534 dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw); 4579 ret = mxl5005s_reconfigure(fe, req_mode, req_bw);
4535 4580
4536 mxl5005s_SetRfFreqHz(fe, freq); 4581 } else
4582 ret = 0;
4537 4583
4538 msleep(350); 4584 if (ret == 0) {
4585 dprintk(1, "%s() freq=%d\n", __func__, params->frequency);
4586 ret = mxl5005s_SetRfFreqHz(fe, params->frequency);
4587 }
4539 4588
4540 return 0; 4589 return ret;
4541} 4590}
4542 4591
4543static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) 4592static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency)
@@ -4560,16 +4609,6 @@ static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
4560 return 0; 4609 return 0;
4561} 4610}
4562 4611
4563static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status)
4564{
4565 dprintk(1, "%s()\n", __func__);
4566
4567 *status = 0;
4568 // *status = TUNER_STATUS_LOCKED;
4569
4570 return 0;
4571}
4572
4573static int mxl5005s_release(struct dvb_frontend *fe) 4612static int mxl5005s_release(struct dvb_frontend *fe)
4574{ 4613{
4575 dprintk(1, "%s()\n", __func__); 4614 dprintk(1, "%s()\n", __func__);
@@ -4592,7 +4631,6 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = {
4592 .set_params = mxl5005s_set_params, 4631 .set_params = mxl5005s_set_params,
4593 .get_frequency = mxl5005s_get_frequency, 4632 .get_frequency = mxl5005s_get_frequency,
4594 .get_bandwidth = mxl5005s_get_bandwidth, 4633 .get_bandwidth = mxl5005s_get_bandwidth,
4595 .get_status = mxl5005s_get_status
4596}; 4634};
4597 4635
4598struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, 4636struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
@@ -4609,6 +4647,7 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
4609 state->frontend = fe; 4647 state->frontend = fe;
4610 state->config = config; 4648 state->config = config;
4611 state->i2c = i2c; 4649 state->i2c = i2c;
4650 state->current_mode = MXL_QAM;
4612 4651
4613 printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address); 4652 printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address);
4614 4653
@@ -4620,8 +4659,5 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
4620EXPORT_SYMBOL(mxl5005s_attach); 4659EXPORT_SYMBOL(mxl5005s_attach);
4621 4660
4622MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver"); 4661MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver");
4623MODULE_AUTHOR("Jan Hoogenraad");
4624MODULE_AUTHOR("Barnaby Shearer");
4625MODULE_AUTHOR("Andy Hasper");
4626MODULE_AUTHOR("Steven Toth"); 4662MODULE_AUTHOR("Steven Toth");
4627MODULE_LICENSE("GPL"); 4663MODULE_LICENSE("GPL");
diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h
index 2777ecc20d19..7658401f3cdd 100644
--- a/drivers/media/common/tuners/mxl5005s.h
+++ b/drivers/media/common/tuners/mxl5005s.h
@@ -1,27 +1,24 @@
1/* 1/*
2 * For the Realtek RTL chip RTL2831U 2 MaxLinear MXL5005S VSB/QAM/DVBT tuner driver
3 * Realtek Release Date: 2008-03-14, ver 080314
4 * Realtek version RTL2831 Linux driver version 080314
5 * ver 080314
6 *
7 * for linux kernel version 2.6.21.4 - 2.6.22-14
8 * support MXL5005s and MT2060 tuners (support tuner auto-detecting)
9 * support two IR types -- RC5 and NEC
10 *
11 * Known boards with Realtek RTL chip RTL2821U
12 * Freecom USB stick 14aa:0160 (version 4)
13 * Conceptronic CTVDIGRCU
14 *
15 * Copyright (c) 2008 Realtek
16 * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper
17 * This code is placed under the terms of the GNU General Public License
18 *
19 * Released by Realtek under GPLv2.
20 * Thanks to Realtek for a lot of support we received !
21 *
22 * Revision: 080314 - original version
23 */
24 3
4 Copyright (C) 2008 MaxLinear
5 Copyright (C) 2008 Steven Toth <stoth@hauppauge.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21*/
25 22
26#ifndef __MXL5005S_H 23#ifndef __MXL5005S_H
27#define __MXL5005S_H 24#define __MXL5005S_H
@@ -112,14 +109,15 @@ struct mxl5005s_config
112 u8 AgcMasterByte; 109 u8 AgcMasterByte;
113}; 110};
114 111
115#if defined(CONFIG_DVB_TUNER_MXL5005S) || (defined(CONFIG_DVB_TUNER_MXL5005S_MODULE) && defined(MODULE)) 112#if defined(CONFIG_DVB_TUNER_MXL5005S) || \
113 (defined(CONFIG_DVB_TUNER_MXL5005S_MODULE) && defined(MODULE))
116extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, 114extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
117 struct i2c_adapter *i2c, 115 struct i2c_adapter *i2c,
118 struct mxl5005s_config *config); 116 struct mxl5005s_config *config)
119#else 117#else
120static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, 118static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
121 struct i2c_adapter *i2c, 119 struct i2c_adapter *i2c,
122 struct mxl5005s_config *config); 120 struct mxl5005s_config *config)
123{ 121{
124 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 122 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
125 return NULL; 123 return NULL;