// SPDX-License-Identifier: GPL-2.0-only
/* DVB USB compliant linux driver for
*
* DM04/QQBOX DVB-S USB BOX LME2510C + SHARP:BS2F7HZ7395
* LME2510C + LG TDQY-P001F
* LME2510C + BS2F7HZ0194
* LME2510 + LG TDQY-P001F
* LME2510 + BS2F7HZ0194
*
* MVB7395 (LME2510C+SHARP:BS2F7HZ7395)
* SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V)
*
* MV001F (LME2510+LGTDQY-P001F)
* LG TDQY - P001F =(TDA8263 + TDA10086H)
*
* MVB0001F (LME2510C+LGTDQT-P001F)
*
* MV0194 (LME2510+SHARP:BS2F7HZ0194)
* SHARP:BS2F7HZ0194 = (STV0299+IX2410)
*
* MVB0194 (LME2510C+SHARP0194)
*
* LME2510C + M88RS2000
*
* For firmware see Documentation/admin-guide/media/lmedm04.rst
*
* I2C addresses:
* 0xd0 - STV0288 - Demodulator
* 0xc0 - Sharp IX2505V - Tuner
* --
* 0x1c - TDA10086 - Demodulator
* 0xc0 - TDA8263 - Tuner
* --
* 0xd0 - STV0299 - Demodulator
* 0xc0 - IX2410 - Tuner
*
* VID = 3344 PID LME2510=1122 LME2510C=1120
*
* Copyright (C) 2010 Malcolm Priestley (tvboxspy@gmail.com)
* LME2510(C)(C) Leaguerme (Shenzhen) MicroElectronics Co., Ltd.
*
* see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
*
* Known Issues :
* LME2510: Non Intel USB chipsets fail to maintain High Speed on
* Boot or Hot Plug.
*
* QQbox suffers from noise on LNB voltage.
*
* LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
* with other tuners. After a cold reset streaming will not start.
*
* M88RS2000 suffers from loss of lock.
*/
#define DVB_USB_LOG_PREFIX "LME2510(C)"
#include <linux/usb.h>
#include <linux/usb/input.h>
#include <media/rc-core.h>
#include "dvb_usb.h"
#include "lmedm04.h"
#include "tda826x.h"
#include "tda10086.h"
#include "stv0288.h"
#include "ix2505v.h"
#include "stv0299.h"
#include "dvb-pll.h"
#include "z0194a.h"
#include "m88rs2000.h"
#include "ts2020.h"
#define LME2510_C_S7395 "dvb-usb-lme2510c-s7395.fw";
#define LME2510_C_LG "dvb-usb-lme2510c-lg.fw";
#define LME2510_C_S0194 "dvb-usb-lme2510c-s0194.fw";
#define LME2510_C_RS2000 "dvb-usb-lme2510c-rs2000.fw";
#define LME2510_LG "dvb-usb-lme2510-lg.fw";
#define LME2510_S0194 "dvb-usb-lme2510-s0194.fw";
/* debug */
static int dvb_usb_lme2510_debug;
#define lme_debug(var, level, args...) do { \
if ((var >= level)) \
pr_debug(DVB_USB_LOG_PREFIX": " args); \
} while (0)
#define deb_info(level, args...) lme_debug(dvb_usb_lme2510_debug, level, args)
#define debug_data_snipet(level, name, p) \
deb_info(level, name" (%8phN)", p);
#define info(args...) pr_info(DVB_USB_LOG_PREFIX": "args)
module_param_named(debug, dvb_usb_lme2510_debug, int, 0644);
MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
static int dvb_usb_lme2510_firmware;
module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644);
MODULE_PARM_DESC(firmware, "set default firmware 0=Sharp7395 1=LG");
static int pid_filter;
module_param_named(pid, pid_filter, int, 0644);
MODULE_PARM_DESC(pid, "set default 0=default 1=off 2=on");
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define TUNER_DEFAULT 0x0
#define TUNER_LG 0x1
#define TUNER_S7395 0x2
#define TUNER_S0194 0x3
#define TUNER_RS2000 0x4
struct lme2510_state {
unsigned long int_urb_due;
enum fe_status lock_status;
u8 id;
u8 tuner_config;
u8 signal_level;
u8 signal_sn;
u8 time_key;
u8 i2c_talk_onoff;
u8 i2c_gate;
u8 i2c_tuner_gate_w;
u8 i2c_tuner_gate_r;
u8 i2c_tuner_addr;
u8 stream_on;
u8 pid_size;
u8 pid_off;
u8 int_buffer[128];
struct urb *lme_urb;
u8 usb_buffer[64];
/* Frontend original calls */
int (*fe_read_status)(struct dvb_frontend *, enum fe_status *);
int (*fe_read_signal_strength)(struct dvb_frontend *, u16 *);
int (*fe_read_snr)(struct dvb_frontend *, u16 *);
int (*fe_read_ber)(struct dvb_frontend *, u32 *);
int (*fe_read_ucblocks)(struct dvb_frontend *, u32 *);
int (*fe_set_voltage)(struct dvb_frontend *, enum fe_sec_voltage);
u8 dvb_usb_lme2510_firmware;
};
static int lme2510_usb_talk(struct dvb_usb_device *d,
u8 *wbuf, int wlen, u8 *rbuf, int rlen)
{
struct lme2510_state *st = d->priv;
int ret = 0;
if (max(wlen, rlen) > sizeof(st-><