/*
* mxl5007t.c - driver for the MaxLinear MxL5007T silicon tuner
*
* Copyright (C) 2008 Michael Krufky <mkrufky@linuxtv.org>
*
* 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.
*/
#include <linux/i2c.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include "tuner-i2c.h"
#include "mxl5007t.h"
static DEFINE_MUTEX(mxl5007t_list_mutex);
static LIST_HEAD(hybrid_tuner_instance_list);
static int mxl5007t_debug;
module_param_named(debug, mxl5007t_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debug level");
/* ------------------------------------------------------------------------- */
#define mxl_printk(kern, fmt, arg...) \
printk(kern "%s: " fmt "\n", __func__, ##arg)
#define mxl_err(fmt, arg...) \
mxl_printk(KERN_ERR, "%d: " fmt, __LINE__, ##arg)
#define mxl_warn(fmt, arg...) \
mxl_printk(KERN_WARNING, fmt, ##arg)
#define mxl_info(fmt, arg...) \
mxl_printk(KERN_INFO, fmt, ##arg)
#define mxl_debug(fmt, arg...) \
({ \
if (mxl5007t_debug) \
mxl_printk(KERN_DEBUG, fmt, ##arg); \
})
#define mxl_fail(ret) \
({ \
int __ret; \
__ret = (ret < 0); \
if (__ret) \
mxl_printk(KERN_ERR, "error %d on line %d", \
ret, __LINE__); \
__ret; \
})
/* ------------------------------------------------------------------------- */
#define MHz 1000000
enum mxl5007t_mode {
MxL_MODE_OTA_DVBT_ATSC = 0,
MxL_MODE_OTA_NTSC_PAL_GH = 1,
MxL_MODE_OTA_PAL_IB = 2,
MxL_MODE_OTA_PAL_D_SECAM_KL = 3,
MxL_MODE_OTA_ISDBT = 4,
MxL_MODE_CABLE_DIGITAL = 0x10,
MxL_MODE_CABLE_NTSC_PAL_GH = 0x11,
MxL_MODE_CABLE_PAL_IB = 0x12,
MxL_MODE_CABLE_PAL_D_SECAM_KL = 0x13,
MxL_MODE_CABLE_SCTE40 = 0x14,
};
enum mxl5007t_chip_version {
MxL_UNKNOWN_ID = 0x00,
MxL_5007_V1_F1 = 0x11,
MxL_5007_V1_F2 = 0x12,
MxL_5007_V2_100_F1 = 0x21,
MxL_5007_V2_100_F2 = 0x22,
MxL_5007_V2_200_F1 = 0x23,
MxL_5007_V2_200_F2 = 0x24,
};
struct reg_pair_t {
u8 reg;
u8 val;
};
/* ------------------------------------------------------------------------- */
static struct reg_pair_t init_tab[] = {
{ 0x0b, 0x44 }, /* XTAL */
{ 0x0c, 0x60 }, /* IF */
{ 0x10, 0x00 }, /* MISC */
{ 0x12, 0xca }, /* IDAC */
{ 0x16, 0x90 }, /* MODE */
{ 0x32, 0x38 }, /* MODE Analog/Digital */
{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
{ 0x2c, 0x34 }, /* OVERRIDE */
{ 0x4d, 0x40 }, /* OVERRIDE */
{ 0x7f, 0x02 }, /* OVERRIDE */
{ 0x9a, 0x52 }, /* OVERRIDE */
{ 0x48, 0x5a }, /* OVERRIDE */
{ 0x76, 0x1a }, /* OVERRIDE */
{ 0x6a, 0x48 }, /* OVERRIDE */
{ 0x64, 0x28 }, /* OVERRIDE */
{ 0x66, 0xe6 }, /* OVERRIDE */
{ 0x35, 0x0e }, /* OVERRIDE */
{ 0x7e, 0x01 }, /* OVERRIDE */
{ 0x83, 0x00 }, /* OVERRIDE */
{ 0x04, 0x0b }, /* OVERRIDE */
{ 0x05, 0x01 }, /* TOP_MASTER_ENABLE */
{ 0, 0 }
};
static struct reg_pair_t init_tab_cable[] = {
{ 0x0b, 0x44 }, /* XTAL */
{ 0x0c, 0x60 }, /* IF */
{ 0x10, 0x00 }, /* MISC */
{ 0x12, 0xca }, /* IDAC */
{ 0x16, 0x90 }, /* MODE */
{ 0x32, 0x38 }, /* MODE A/D */
{ 0x71, 0x3f }, /* TOP1 */
{ 0x72, 0x3f }, /* TOP2 */
{ 0x74, 0x3f }, /* TOP3 */
{ 0xd8, 0x18 }, /* CLK_OUT_ENABLE */
{ 0x2c, 0x34 }, /* OVERRIDE */
{ 0x4d, 0x40 }, /* OVERRIDE */
{ 0x7f, 0x02 }, /* OVERRIDE */
{ 0x9a, 0x52 }, /* OVERRIDE */
{ 0x48, 0x5a }, /* OVERRIDE */
{ 0x76, 0x1a }, /* OVERRIDE */
{ 0x6a, 0x48 }, /* OVERRIDE */
{ 0x64, 0x28 }, /* OVERRIDE */
{ 0x66, 0xe6 }, /* OVERRIDE */
{ 0x35, 0x0e }, /* OVERRIDE */
{ 0x7e, 0x01 }, /* OVERRIDE */
{ 0x04, 0x0b