mirror of
https://github.com/LibreELEC/LibreELEC.tv
synced 2025-09-24 19:46:01 +07:00
1578 lines
56 KiB
Diff
Executable File
1578 lines
56 KiB
Diff
Executable File
http://patchwork.linuxtv.org/patch/10575/
|
|
modified for 3.7.10
|
|
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h
|
|
--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:23:44.824143495 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-common.h 2012-04-03 15:26:40.756140116 +0400
|
|
@@ -91,6 +91,8 @@
|
|
int feedcount;
|
|
int pid_filtering;
|
|
int fullts_streaming_state;
|
|
+ /* the stream will be activated by an externally (by the fe for example) */
|
|
+ int need_external_stream_control;
|
|
|
|
/* bus specific callbacks */
|
|
flexcop_ibi_value(*read_ibi_reg) (struct flexcop_device *,
|
|
@@ -177,6 +179,8 @@
|
|
struct dvb_demux_feed *dvbdmxfeed, int onoff);
|
|
void flexcop_hw_filter_init(struct flexcop_device *fc);
|
|
|
|
+extern void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff);
|
|
+
|
|
void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff);
|
|
|
|
void flexcop_set_mac_filter(struct flexcop_device *fc, u8 mac[6]);
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c
|
|
--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:23:44.828143388 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-fe-tuner.c 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -12,6 +12,7 @@
|
|
#include "cx24113.h"
|
|
#include "cx24123.h"
|
|
#include "isl6421.h"
|
|
+#include "cx24120.h"
|
|
#include "mt352.h"
|
|
#include "bcm3510.h"
|
|
#include "nxt200x.h"
|
|
@@ -26,6 +27,15 @@
|
|
#define FE_SUPPORTED(fe) (defined(CONFIG_DVB_##fe) || \
|
|
(defined(CONFIG_DVB_##fe##_MODULE) && defined(MODULE)))
|
|
|
|
+#if FE_SUPPORTED(BCM3510) || FE_SUPPORTED(CX24120)
|
|
+static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
|
|
+ const struct firmware **fw, char* name)
|
|
+{
|
|
+ struct flexcop_device *fc = fe->dvb->priv;
|
|
+ return request_firmware(fw, name, fc->dev);
|
|
+}
|
|
+#endif
|
|
+
|
|
/* lnb control */
|
|
#if FE_SUPPORTED(MT312) || FE_SUPPORTED(STV0299)
|
|
static int flexcop_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
|
@@ -445,13 +455,6 @@
|
|
|
|
/* AirStar ATSC 1st generation */
|
|
#if FE_SUPPORTED(BCM3510)
|
|
-static int flexcop_fe_request_firmware(struct dvb_frontend *fe,
|
|
- const struct firmware **fw, char* name)
|
|
-{
|
|
- struct flexcop_device *fc = fe->dvb->priv;
|
|
- return request_firmware(fw, name, fc->dev);
|
|
-}
|
|
-
|
|
static struct bcm3510_config air2pc_atsc_first_gen_config = {
|
|
.demod_address = 0x0f,
|
|
.request_firmware = flexcop_fe_request_firmware,
|
|
@@ -619,10 +622,40 @@
|
|
#define cablestar2_attach NULL
|
|
#endif
|
|
|
|
+/* SkyStar S2 PCI DVB-S/S2 card based on Conexant cx24120/cx24118 */
|
|
+#if FE_SUPPORTED(CX24120) && FE_SUPPORTED(ISL6421)
|
|
+static const struct cx24120_config skystar2_rev3_3_cx24120_config = {
|
|
+ .i2c_addr = 0x55,
|
|
+ .request_firmware = flexcop_fe_request_firmware,
|
|
+};
|
|
+
|
|
+static int skystarS2_rev33_attach(struct flexcop_device *fc, struct i2c_adapter *i2c)
|
|
+{
|
|
+// struct dvb_frontend_ops *ops;
|
|
+
|
|
+ fc->fe = dvb_attach(cx24120_attach,
|
|
+ &skystar2_rev3_3_cx24120_config, i2c);
|
|
+ if (fc->fe == NULL) return 0;
|
|
+ fc->dev_type = FC_SKYS2_REV33;
|
|
+ fc->fc_i2c_adap[2].no_base_addr = 1;
|
|
+ if ( (dvb_attach(isl6421_attach, fc->fe,
|
|
+ &fc->fc_i2c_adap[2].i2c_adap, 0x08, 0, 0, false) == NULL) ) {
|
|
+ err("ISL6421 could NOT be attached!");
|
|
+ return 0;
|
|
+ }
|
|
+ info("ISL6421 successfully attached.");
|
|
+// ops = &fc->fe->ops;
|
|
+ return 1;
|
|
+}
|
|
+#else
|
|
+#define skystarS2_rev33_attach NULL
|
|
+#endif
|
|
+
|
|
static struct {
|
|
flexcop_device_type_t type;
|
|
int (*attach)(struct flexcop_device *, struct i2c_adapter *);
|
|
} flexcop_frontends[] = {
|
|
+ { FC_SKYS2_REV33, skystarS2_rev33_attach },
|
|
{ FC_SKY_REV27, skystar2_rev27_attach },
|
|
{ FC_SKY_REV28, skystar2_rev28_attach },
|
|
{ FC_SKY_REV26, skystar2_rev26_attach },
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c
|
|
--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:23:44.828143388 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-hw-filter.c 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -11,6 +11,12 @@
|
|
deb_ts("rcv_data is now: '%s'\n", onoff ? "on" : "off");
|
|
}
|
|
|
|
+void flexcop_external_stream_control(struct dvb_frontend *fe, u8 onoff)
|
|
+{
|
|
+ struct flexcop_device *fc = fe->dvb->priv;
|
|
+ flexcop_rcv_data_ctrl(fc, onoff);
|
|
+}
|
|
+
|
|
void flexcop_smc_ctrl(struct flexcop_device *fc, int onoff)
|
|
{
|
|
flexcop_set_ibi_value(ctrl_208, SMC_Enable_sig, onoff);
|
|
@@ -199,6 +205,7 @@
|
|
|
|
/* if it was the first or last feed request change the stream-status */
|
|
if (fc->feedcount == onoff) {
|
|
+ if (!fc->need_external_stream_control)
|
|
flexcop_rcv_data_ctrl(fc, onoff);
|
|
if (fc->stream_control) /* device specific stream control */
|
|
fc->stream_control(fc, onoff);
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c
|
|
--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:23:44.832143280 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-misc.c 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -56,6 +56,7 @@
|
|
[FC_SKY_REV26] = "Sky2PC/SkyStar 2 DVB-S rev 2.6",
|
|
[FC_SKY_REV27] = "Sky2PC/SkyStar 2 DVB-S rev 2.7a/u",
|
|
[FC_SKY_REV28] = "Sky2PC/SkyStar 2 DVB-S rev 2.8",
|
|
+ [FC_SKYS2_REV33]= "Sky2PC/SkyStar S2 DVB-S/S2 rev 3.3",
|
|
};
|
|
|
|
static const char *flexcop_bus_names[] = {
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h
|
|
--- linux-3.4-r1/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:23:44.832143280 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/common/b2c2/flexcop-reg.h 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -24,6 +24,7 @@
|
|
FC_SKY_REV26,
|
|
FC_SKY_REV27,
|
|
FC_SKY_REV28,
|
|
+ FC_SKYS2_REV33,
|
|
} flexcop_device_type_t;
|
|
|
|
typedef enum {
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/common/b2c2/Kconfig linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig
|
|
--- linux-3.4-r1/drivers/media/common/b2c2/Kconfig 2012-04-03 15:23:44.824143495 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/common/b2c2/Kconfig 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -3,6 +3,7 @@
|
|
depends on DVB_CORE && I2C
|
|
depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB
|
|
default y
|
|
+ select DVB_CX24120 if !DVB_FE_CUSTOMISE
|
|
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
|
|
select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
|
|
select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c
|
|
--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.c 1970-01-01 03:00:00.000000000 +0300
|
|
+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.c 2012-04-03 16:10:59.000000000 +0400
|
|
@@ -0,0 +1,1053 @@
|
|
+/*
|
|
+ Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner driver
|
|
+ Version 0.0.4a 03.04.2012
|
|
+
|
|
+ Copyright (C) 2009 Sergey Tyurin <forum.free-x.de>
|
|
+ Updated 2012 by Jannis Achstetter <jannis_achstetter@web.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.
|
|
+*/
|
|
+
|
|
+#include <linux/slab.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/moduleparam.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/firmware.h>
|
|
+#include "dvb_frontend.h"
|
|
+#include "cx24120.h"
|
|
+#include "cx24120_const.h"
|
|
+
|
|
+//==========================
|
|
+#define dbginfo(args...) do { if(cx24120_debug) { printk(KERN_DEBUG "CX24120: %s: >>> ", __func__); \
|
|
+ printk(args); } } while (0)
|
|
+#define info(args...) do { printk(KERN_INFO "CX24120: %s: -> ", __func__); \
|
|
+ printk(args); } while (0)
|
|
+#define err(args...) do { printk(KERN_ERR "CX24120: %s: ### ERROR: ", __func__); \
|
|
+ printk(args); } while (0)
|
|
+//==========================
|
|
+
|
|
+static int cx24120_debug=0;
|
|
+static int reg_debug=0;
|
|
+MODULE_DESCRIPTION("DVB Frontend module for Conexant CX24120/CX24118 hardware");
|
|
+module_param(cx24120_debug, int, 0644);
|
|
+MODULE_PARM_DESC(cx24120_debug, "Activates frontend debugging (default:0)");
|
|
+
|
|
+// ##############################
|
|
+struct cx24120_state {
|
|
+ struct i2c_adapter *i2c;
|
|
+ const struct cx24120_config *config;
|
|
+ struct dvb_frontend frontend;
|
|
+ u8 need_set_mpeg_out;
|
|
+ u8 attached;
|
|
+ u8 dvb_s2_mode;
|
|
+ u8 cold_init;
|
|
+};
|
|
+// #####################################
|
|
+// #### Command message to firmware ####
|
|
+struct cx24120_cmd { // total size = 36
|
|
+ u8 id; // [00] - message id
|
|
+ u8 arg[30]; // [04] - message first byte
|
|
+ u8 len; // [34] - message lengh or first registers to read
|
|
+ u8 reg; // [35] - number of registers to read
|
|
+};
|
|
+
|
|
+//===================================================================
|
|
+static int cx24120_readreg(struct cx24120_state *state, u8 reg)
|
|
+{
|
|
+ int ret;
|
|
+ u8 buf = 0;
|
|
+ struct i2c_msg msg[] = {
|
|
+ { .addr = state->config->i2c_addr,
|
|
+ .flags = 0,
|
|
+ .len = 1,
|
|
+ .buf = ® },
|
|
+
|
|
+ { .addr = state->config->i2c_addr,
|
|
+ .flags = I2C_M_RD,
|
|
+ .len = 1,
|
|
+ .buf = &buf }
|
|
+ };
|
|
+ ret = i2c_transfer(state->i2c, msg, 2);
|
|
+ if (ret != 2) {
|
|
+ err("Read error: reg=0x%02x, ret=0x%02x)\n", reg, ret);
|
|
+ return ret;
|
|
+ }
|
|
+ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, buf);
|
|
+ return buf;
|
|
+} // end cx24120_readreg
|
|
+//===================================================================
|
|
+static int cx24120_writereg(struct cx24120_state *state, u8 reg, u8 data)
|
|
+{
|
|
+ u8 buf[] = { reg, data };
|
|
+ struct i2c_msg msg = {
|
|
+ .addr = state->config->i2c_addr,
|
|
+ .flags = 0,
|
|
+ .buf = buf,
|
|
+ .len = 2 };
|
|
+ int ret;
|
|
+ ret = i2c_transfer(state->i2c, &msg, 1);
|
|
+ if (ret != 1) {
|
|
+ err("Write error: i2c_write error(err == %i, 0x%02x: 0x%02x)\n", ret, reg, data);
|
|
+ return ret;
|
|
+ }
|
|
+ if (reg_debug) dbginfo("reg=0x%02x; data=0x%02x\n", reg, data);
|
|
+ return 0;
|
|
+} // end cx24120_writereg
|
|
+//===================================================================
|
|
+static int cx24120_writeregN(struct cx24120_state *state, u8 reg, const u8 *values, u16 len, u8 incr)
|
|
+{
|
|
+ u8 buf[5]; /* maximum 4 data bytes at once - flexcop limitation (very limited i2c-interface this one) */
|
|
+ struct i2c_msg msg = {
|
|
+ .addr = state->config->i2c_addr,
|
|
+ .flags = 0,
|
|
+ .buf = buf,
|
|
+ .len = len };
|
|
+ int ret;
|
|
+
|
|
+ do {
|
|
+ buf[0] = reg;
|
|
+ msg.len = len > 4 ? 4 : len;
|
|
+ memcpy(&buf[1], values, msg.len);
|
|
+ len -= msg.len; // data length revers counter
|
|
+ values += msg.len; // incr data pointer
|
|
+ if (incr) reg += msg.len;
|
|
+ msg.len++; /* don't forget the addr byte */
|
|
+ ret = i2c_transfer(state->i2c, &msg, 1);
|
|
+ if (ret != 1) {
|
|
+ err("i2c_write error(err == %i, 0x%02x)\n", ret, reg);
|
|
+ return ret;
|
|
+ }
|
|
+ if (reg_debug) {
|
|
+ if( !(reg == 0xFA) && !(reg == 0x20) && !(reg == 0x21)) { // Exclude firmware upload & diseqc messages
|
|
+ dbginfo("reg=0x%02x; data=0x%02x,0x%02x,0x%02x,0x%02x\n", // from debug
|
|
+ reg, buf[1], buf[2], buf[3], buf[4]);
|
|
+ }
|
|
+ }
|
|
+ } while (len);
|
|
+ return 0;
|
|
+} // end cx24120_writeregN
|
|
+//===================================================================
|
|
+static struct dvb_frontend_ops cx24120_ops;
|
|
+//===================================================================
|
|
+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config, struct i2c_adapter *i2c)
|
|
+{
|
|
+ struct cx24120_state *state = NULL;
|
|
+ int demod_rev;
|
|
+
|
|
+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner\n");
|
|
+ info("Driver version: 'SVT - 0.0.4a 03.04.2012'\n");
|
|
+ state = kzalloc(sizeof(struct cx24120_state),
|
|
+ GFP_KERNEL);
|
|
+ if (state == NULL) {
|
|
+ err("### Unable to allocate memory for cx24120_state structure. :(\n");
|
|
+ goto error;
|
|
+ }
|
|
+ /* setup the state */
|
|
+ state->config = config;
|
|
+ state->i2c = i2c;
|
|
+ /* check if the demod is present and has proper type */
|
|
+ demod_rev = cx24120_readreg(state, CX24120_REG_REVISION);
|
|
+ switch (demod_rev) {
|
|
+ case 0x07:
|
|
+ info("Demod CX24120 rev. 0x07 detected.\n");
|
|
+ break;
|
|
+ case 0x05:
|
|
+ info("Demod CX24120 rev. 0x05 detected.\n");
|
|
+ break;
|
|
+ default:
|
|
+ err("### Unsupported demod revision: 0x%x detected. Exit.\n", demod_rev);
|
|
+ goto error;
|
|
+ }
|
|
+ /* create dvb_frontend */
|
|
+ state->attached = 0x10; // set attached flag
|
|
+ state->cold_init=0;
|
|
+ memcpy(&state->frontend.ops, &cx24120_ops, sizeof(struct dvb_frontend_ops));
|
|
+ state->frontend.demodulator_priv = state;
|
|
+ info("Conexant cx24120/cx24118 - DVBS/S2 Satellite demod/tuner ATTACHED.\n");
|
|
+ return &state->frontend;
|
|
+
|
|
+error:
|
|
+ kfree(state);
|
|
+ return NULL;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_attach); // end cx24120_attach
|
|
+//===================================================================
|
|
+static int cx24120_test_rom(struct cx24120_state *state)
|
|
+{
|
|
+ int err, ret;
|
|
+ err = cx24120_readreg(state, 0xFD);
|
|
+ if (err & 4 )
|
|
+ {
|
|
+ ret = cx24120_readreg(state, 0xDF) & 0xFE;
|
|
+ err = cx24120_writereg(state, 0xDF, ret);
|
|
+ }
|
|
+ return err;
|
|
+} // end cx24120_test_rom
|
|
+//===================================================================
|
|
+static int cx24120_read_snr(struct dvb_frontend *fe, u16 *snr)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+
|
|
+ *snr = (cx24120_readreg(state, CX24120_REG_QUALITY_H)<<8) |
|
|
+ (cx24120_readreg(state, CX24120_REG_QUALITY_L));
|
|
+ dbginfo("read SNR index = %d\n", *snr);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_read_snr); // end cx24120_read_snr
|
|
+//===================================================================
|
|
+static int cx24120_read_ber(struct dvb_frontend *fe, u32 *ber)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+
|
|
+ *ber = (cx24120_readreg(state, CX24120_REG_BER_HH) << 24) | // BER high byte of high word
|
|
+ (cx24120_readreg(state, CX24120_REG_BER_HL) << 16) | // BER low byte of high word
|
|
+ (cx24120_readreg(state, CX24120_REG_BER_LH) << 8) | // BER high byte of low word
|
|
+ cx24120_readreg(state, CX24120_REG_BER_LL); // BER low byte of low word
|
|
+ dbginfo("read BER index = %d\n", *ber);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_read_ber); // end cx24120_read_ber
|
|
+//===================================================================
|
|
+static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd);
|
|
+//===================================================================
|
|
+static int cx24120_msg_mpeg_output_global_config(struct cx24120_state *state, u8 flag)
|
|
+{
|
|
+ u8 tristate;
|
|
+ struct cx24120_cmd cmd;
|
|
+
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+
|
|
+ cmd.id = 0x13; // (19) message Enable/Disable mpeg output ???
|
|
+ cmd.arg[0] = 1;
|
|
+ cmd.arg[1] = 0;
|
|
+ tristate = flag ? 0 : (u8)(-1);
|
|
+ cmd.arg[2] = tristate;
|
|
+ cmd.arg[3] = 1;
|
|
+ cmd.len = 4;
|
|
+
|
|
+ if(flag) dbginfo("MPEG output DISABLED\n");
|
|
+ else dbginfo("MPEG output ENABLED\n");
|
|
+
|
|
+ return cx24120_message_send(state, &cmd);
|
|
+} // end cx24120_msg_mpeg_output_global_config
|
|
+//===================================================================
|
|
+static int cx24120_message_send(struct cx24120_state *state, struct cx24120_cmd *cmd)
|
|
+{
|
|
+ u8 xxzz;
|
|
+ u32 msg_cmd_mask;
|
|
+ int ret, ficus;
|
|
+
|
|
+ if(state->dvb_s2_mode & 0x02) { // is MPEG enabled?
|
|
+ // if yes:
|
|
+ xxzz = cmd->id - 0x11; // look for specific message id
|
|
+ if ( xxzz <= 0x13 ) {
|
|
+ msg_cmd_mask = 1 << xxzz;
|
|
+ //0x0F8021 // if cmd_id 17 or 22 or 33-36, 42, 47, 57-61 etc. disable mpeg output
|
|
+ if ( msg_cmd_mask & 0x0F8021 ) { // 000011111000000000100001b
|
|
+ cx24120_msg_mpeg_output_global_config(state, 0);
|
|
+ msleep(100);
|
|
+ state->dvb_s2_mode &= 0xFD; // reset mpeg out enable flag
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ ret = cx24120_writereg(state, 0x00 /* reg id*/, cmd->id /* value */); // message start & target
|
|
+ ret = cx24120_writeregN(state, 0x01 /* reg msg*/, &cmd->arg[0], cmd->len /* len*/, 1 /* incr */); // message data
|
|
+ ret = cx24120_writereg(state, 0x1F /* reg msg_end */, 0x01 /* value */); // message end
|
|
+
|
|
+ ficus = 1000;
|
|
+ while ( cx24120_readreg(state, 0x1F)) { // is command done???
|
|
+ msleep(1);
|
|
+ if( !(--ficus)) {
|
|
+ err("Too long waiting 'done' state from reg(0x1F). :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ }
|
|
+ dbginfo("Successfully send message 0x%02x\n", cmd->id);
|
|
+
|
|
+ if ( cmd->reg > 30 ) {
|
|
+ err("Too much registers to read. cmd->reg = %d", cmd->reg);
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ ficus = 0;
|
|
+ if ( cmd->reg ) { // cmd->reg - qty consecutive regs to read
|
|
+ while ( ficus < cmd->reg ){ // starts from reg No cmd->len
|
|
+ // number of registers to read is cmd->reg
|
|
+ // and write results starts from cmd->arg[0].
|
|
+ cmd->arg[ficus] = cx24120_readreg(state, (cmd->len+ficus+1));
|
|
+ ++ficus;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+} // end cx24120_message_send
|
|
+//===================================================================
|
|
+static int cx24120_set_frontend(struct dvb_frontend *fe)
|
|
+{
|
|
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+ u32 srate, freq;
|
|
+ fe_code_rate_t fec;
|
|
+ fe_spectral_inversion_t inversion;
|
|
+ u8 smbr1, smbr2;
|
|
+ int ret;
|
|
+
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+
|
|
+ cmd.id = CMD_TUNEREQUEST; // 0x11 set tuner parametrs
|
|
+ cmd.len = 15;
|
|
+
|
|
+ freq = p->frequency;
|
|
+ srate = p->symbol_rate;
|
|
+ fec = p->fec_inner;
|
|
+ inversion = p->inversion;
|
|
+
|
|
+ // check symbol rate
|
|
+ if ( srate > 31000000 ) { // if symbol rate > 31 000
|
|
+ smbr1 = (-(srate < 31000001) & 3) + 2; // ebp
|
|
+ smbr2 = (-(srate < 31000001) & 6) + 4; // edi
|
|
+ } else {
|
|
+ smbr1 = 3;
|
|
+ smbr2 = 6;
|
|
+ }
|
|
+
|
|
+ ret = cx24120_writereg(state, 0xE6, smbr1);
|
|
+ ret = cx24120_readreg(state, 0xF0);
|
|
+ ret &= 0xFFFFFFF0;
|
|
+ ret |= smbr2;
|
|
+ ret = cx24120_writereg(state, 0xF0, ret);
|
|
+
|
|
+ cmd.arg[0] = 0; // CMD_TUNER_REQUEST
|
|
+
|
|
+ // Frequency
|
|
+ cmd.arg[1] = (freq & 0xFF0000) >> 16; /* intermediate frequency in kHz */
|
|
+ cmd.arg[2] = (freq & 0x00FF00) >> 8;
|
|
+ cmd.arg[3] = (freq & 0x0000FF);
|
|
+
|
|
+ // Symbol Rate
|
|
+ cmd.arg[4] = ((srate/1000) & 0xFF00) >> 8;
|
|
+ cmd.arg[5] = ((srate/1000) & 0x00FF);
|
|
+
|
|
+ // Inversion
|
|
+ if ( inversion ) {
|
|
+ if ( inversion == 1 ) cmd.arg[6] = 4;
|
|
+ else cmd.arg[6] = 0x0C;
|
|
+ } else {
|
|
+ cmd.arg[6] = 0;
|
|
+ }
|
|
+
|
|
+ // FEC
|
|
+ switch ( fec ) // fec = p->u.qpsk.fec_inner
|
|
+ {
|
|
+ case 1: // FEC_1_2
|
|
+ cmd.arg[7] = 0x2E; break; // [11] = 0 by memset
|
|
+ case 2: // FEC_2_3
|
|
+ cmd.arg[7] = 0x2F; break;
|
|
+ case 3: // FEC_3_4
|
|
+ cmd.arg[7] = 0x30; break;
|
|
+ case 5: // FEC_5_6
|
|
+ cmd.arg[7] = 0x31; break;
|
|
+ case 7: // FEC_7_8
|
|
+ cmd.arg[7] = 0x32; break;
|
|
+ default: // FEC_NONE, FEC_4_5, FEC_6_7, FEC_8_9,
|
|
+ // FEC_AUTO, FEC_3_5, FEC_9_10
|
|
+ if ( state->dvb_s2_mode & 1 ) { // if DVB-S2 mode
|
|
+ cmd.arg[7] = 0;
|
|
+ cmd.arg[11] = 0;
|
|
+ } else {
|
|
+ cmd.arg[7] = 0x2E;
|
|
+ cmd.arg[11] = 0xAC;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ cmd.arg[8] = 0x13;
|
|
+ cmd.arg[9] = 0x88;
|
|
+ cmd.arg[10] = 0;
|
|
+ cmd.arg[12] = smbr2;
|
|
+ cmd.arg[13] = smbr1;
|
|
+ cmd.arg[14] = 0;
|
|
+
|
|
+ state->need_set_mpeg_out |= 0x01; // after tune we need restart mpeg out ?????
|
|
+
|
|
+ return cx24120_message_send(state, &cmd);
|
|
+
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_set_frontend); // end cx24120_set_frontend
|
|
+//===================================================================
|
|
+void cx24120_message_fill(struct cx24120_cmd *cmd,
|
|
+ u8 msg_id,
|
|
+ u8 *msg_addr,
|
|
+ u8 msg_len,
|
|
+ u8 num_regs)
|
|
+{
|
|
+ cmd->id = msg_id;
|
|
+ memcpy(&cmd->arg[0], msg_addr, msg_len);
|
|
+ cmd->len = msg_len;
|
|
+ cmd->reg = num_regs;
|
|
+} // end cx24120_message_fill
|
|
+//===================================================================
|
|
+static int cx24120_read_signal_strength(struct dvb_frontend *fe, u16 *signal_strength)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+ int result, sigstr_h, sigstr_l;
|
|
+
|
|
+ cx24120_message_fill(&cmd, 0x1A/*msg_id*/, &cx24120_msg_read_sigstr[0], 1/*msg_len*/, 0/*num_regs*/);
|
|
+
|
|
+ if( !(cx24120_message_send(state, &cmd)) ) {
|
|
+ sigstr_h = (cx24120_readreg(state, CX24120_REG_SIGSTR_H) >> 6) << 8;
|
|
+ sigstr_l = cx24120_readreg(state, CX24120_REG_SIGSTR_L );
|
|
+ dbginfo("Signal strength from firmware= 0x%x\n", (sigstr_h | sigstr_l));
|
|
+ *signal_strength = ((sigstr_h | sigstr_l) << 5) & 0x0000FFFF;
|
|
+ dbginfo("Signal strength= 0x%x\n", *signal_strength);
|
|
+ result = 0;
|
|
+ } else {
|
|
+ err("error reading signal strength\n");
|
|
+ result = -EREMOTEIO;
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_read_signal_strength); // end cx24120_read_signal_strength
|
|
+//===================================================================
|
|
+static int cx24120_msg_mpeg_output_config(struct cx24120_state *state, u8 num,
|
|
+ struct cx24120_skystar2_mpeg_config *config_msg)
|
|
+{
|
|
+ struct cx24120_cmd cmd;
|
|
+
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+
|
|
+ cmd.id = CMD_MPEG_INIT; // cmd->id=20 - message id
|
|
+ cmd.len = 7;
|
|
+ cmd.arg[0] = num; // sequental number - can be 0,1,2
|
|
+ cmd.arg[1] = ((config_msg->x1 & 0x01) << 1) |
|
|
+ ((config_msg->x1 >> 1) & 0x01);
|
|
+ cmd.arg[2] = 0x05;
|
|
+ cmd.arg[3] = 0x02;
|
|
+ cmd.arg[4] = ((config_msg->x2 >> 1) & 0x01);
|
|
+ cmd.arg[5] = (config_msg->x2 & 0xF0) | (config_msg->x3 & 0x0F);
|
|
+ cmd.arg[6] = state->attached; /* 0x10 if succesfully attached */
|
|
+
|
|
+ return cx24120_message_send(state, &cmd);
|
|
+} // end cx24120_msg_mpeg_output_config
|
|
+//===================================================================
|
|
+static int cx24120_diseqc_send_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t burst)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+
|
|
+ cmd.id = CMD_DISEQC_BURST;
|
|
+ cmd.arg[0] = 0x00;
|
|
+ if (burst)
|
|
+ cmd.arg[1] = 0x01;
|
|
+ dbginfo("burst sent.\n");
|
|
+
|
|
+ return cx24120_message_send(state, &cmd);
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_diseqc_send_burst); // end cx24120_diseqc_send_burst
|
|
+//===================================================================
|
|
+static int cx24120_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+
|
|
+ dbginfo("cmd(0x23,4) - tone = %d\n", tone);
|
|
+ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) {
|
|
+ err("Invalid tone=%d\n", tone);
|
|
+ return -EINVAL;
|
|
+ }
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+ cmd.id = CMD_SETTONE; // 0x23
|
|
+ cmd.len = 4;
|
|
+ if (!tone)
|
|
+ cmd.arg[3] = 0x01;
|
|
+ return cx24120_message_send(state, &cmd);
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_set_tone); // end cx24120_set_tone
|
|
+//===================================================================
|
|
+static int cx24120_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+ cmd.id = CMD_SETVOLTAGE; //
|
|
+ cmd.len = 2;
|
|
+ if (!(voltage - 1))
|
|
+ cmd.arg[1] = 0x01;
|
|
+ return cx24120_message_send(state, &cmd);
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_set_voltage); // end cx24120_set_voltage
|
|
+//===================================================================
|
|
+static int cx24120_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *d)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+ int back_count;
|
|
+
|
|
+ dbginfo("Start sending diseqc sequence===============\n");
|
|
+
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+
|
|
+ cmd.id = CMD_DISEQC_MSG1; // 0x20
|
|
+ cmd.len = 11;
|
|
+ cmd.arg[0] = 0x00;
|
|
+ cmd.arg[1] = 0x00;
|
|
+ cmd.arg[2] = 0x03;
|
|
+ cmd.arg[3] = 0x16;
|
|
+ cmd.arg[4] = 0x28;
|
|
+ cmd.arg[5] = 0x01;
|
|
+ cmd.arg[6] = 0x01;
|
|
+ cmd.arg[7] = 0x14;
|
|
+ cmd.arg[8] = 0x19;
|
|
+ cmd.arg[9] = 0x14;
|
|
+ cmd.arg[10] = 0x1E;
|
|
+ if ( cx24120_message_send(state, &cmd) ) {
|
|
+ err("send 1st message(0x%x) filed==========\n", cmd.id);
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ cmd.id = CMD_DISEQC_MSG2; // 0x21
|
|
+ cmd.len = d->msg_len + 6;
|
|
+ cmd.arg[0] = 0x00;
|
|
+ cmd.arg[1] = 0x01;
|
|
+ cmd.arg[2] = 0x02;
|
|
+ cmd.arg[3] = 0x00;
|
|
+ cmd.arg[4] = 0x00;
|
|
+ cmd.arg[5] = d->msg_len;
|
|
+
|
|
+ memcpy(&cmd.arg[6], &d->msg, d->msg_len);
|
|
+
|
|
+ if ( cx24120_message_send(state, &cmd) ) {
|
|
+ err("send 2d message(0x%x) filed========\n", cmd.id);
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ back_count = 100;
|
|
+ do {
|
|
+ if ( !(cx24120_readreg(state, 0x93) & 0x01) ) {
|
|
+ dbginfo("diseqc sequence sent success==========.\n");
|
|
+ return 0;
|
|
+ }
|
|
+ msleep(5);
|
|
+ --back_count;
|
|
+ } while ( back_count );
|
|
+ err("Too long waiting for diseqc.=============\n");
|
|
+ return -ETIMEDOUT;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_send_diseqc_msg); // end cx24120_send_diseqc_msg
|
|
+//===================================================================
|
|
+static int cx24120_read_status(struct dvb_frontend *fe, fe_status_t *status)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+ int ret, clock_seq_num, GettedFEC;
|
|
+ u8 mode_code, mode_8PSK_flag, attached_flag, clock_id;
|
|
+
|
|
+ ret = cx24120_readreg(state, CX24120_REG_STATUS); //0x3A
|
|
+ dbginfo("status = 0x%x\n", ret);
|
|
+ *status = 0;
|
|
+ if ( ret & CX24120_HAS_SIGNAL ) *status = FE_HAS_SIGNAL;
|
|
+ if ( ret & CX24120_HAS_CARRIER) *status |= FE_HAS_CARRIER;
|
|
+ if ( ret & CX24120_HAS_VITERBI) *status |= (FE_HAS_VITERBI + FE_HAS_SYNC);
|
|
+
|
|
+ if ( ret & CX24120_HAS_LOCK ) { // 0x08
|
|
+ *status |= FE_HAS_LOCK;
|
|
+ if ( state->need_set_mpeg_out & 1 ) { // just tuned???
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+ cmd.id = CMD_CLOCK_READ;
|
|
+ cmd.arg[0] = 0x00;
|
|
+ cmd.len = 1; // cmd.reg != 0, so it is first register to read
|
|
+ cmd.reg = 6; // number of registers to read (0x01-0x06)
|
|
+ if ( !cx24120_message_send(state, &cmd) ) { // in cmd[0]-[5] - result
|
|
+ // 0x02-0x07
|
|
+ ret = cx24120_readreg(state, CX24120_REG_FECMODE) & 0x3F; // ntv - 0x8E(142) & 3F = 14
|
|
+ GettedFEC = ret; // 0x0d= 13
|
|
+ dbginfo("Get FEC: %d\n", ret);
|
|
+ if ( state->dvb_s2_mode & 0x01 ) { // is DVB-S2?
|
|
+ switch (ret-4) {
|
|
+ case 0:
|
|
+ mode_code = 0x01; goto mode_QPSK; // FEC_1_2 - qpsk only
|
|
+ case 1:
|
|
+ case 8:
|
|
+ mode_code = 0x64; goto mode_8PSK; // FEC_3_5 (10)- 8PSK only
|
|
+ case 2:
|
|
+ case 9:
|
|
+ mode_code = 0x02; goto mode_8PSK; // FEC_2_3
|
|
+ case 3:
|
|
+ case 10:
|
|
+ mode_code = 0x03; goto mode_8PSK; // FEC_3_4 // 14-4=10 - ntv+
|
|
+ case 4:
|
|
+ mode_code = 0x04; goto mode_QPSK; // FEC_4_5 - qpsk only
|
|
+ case 5:
|
|
+ case 11:
|
|
+ mode_code = 0x05; goto mode_8PSK; // FEC_5_6
|
|
+ case 6:
|
|
+ case 12:
|
|
+ mode_code = 0x08; goto mode_8PSK; // FEC_8_9
|
|
+ case 7:
|
|
+ case 13:
|
|
+ mode_code = 0x65; goto mode_8PSK; // FEC_9_10 (11)- 8PSK only
|
|
+ default:
|
|
+ info("Unknown DVB-S2 modefec (not QPSK or 8PSK): %d\n", ret-4);
|
|
+ mode_code = 0x01; // set like for mode 0
|
|
+ mode_8PSK:
|
|
+ if ( ret > 11 ) { // 14
|
|
+ mode_8PSK_flag = 0x63; // DVB-S2-8PSK flag
|
|
+ dbginfo("DVB-S2: 8PSK mode: %d, mode_code= 0x%x\n", ret-4, mode_code);
|
|
+ } else {
|
|
+ mode_QPSK:
|
|
+ mode_8PSK_flag = 0x00;
|
|
+ dbginfo("DVB-S2: QPSK mode: %d\n", ret-4);
|
|
+ }
|
|
+ break;
|
|
+ } // end switch
|
|
+ } // end if dvb_s2_mode // dvb-s2
|
|
+ else { // state->dvb_s2_mode & 1 = 0 -> #### DVB-S
|
|
+ switch ( ret - 2 ) {
|
|
+ case 0:
|
|
+ mode_code = 2; break; // FEC_2_3
|
|
+ case 1:
|
|
+ mode_code = 3; break; // FEC_3_4
|
|
+ case 2:
|
|
+ mode_code = 4; break; // FEC_4_5
|
|
+ case 3:
|
|
+ mode_code = 5; break; // FEC_5_6
|
|
+ case 4:
|
|
+ mode_code = 6; break; // FEC_6_7
|
|
+ case 5:
|
|
+ mode_code = 7; break; // FEC_7_8
|
|
+ default:
|
|
+ mode_code = 1;break; // FEC_1_2
|
|
+ }
|
|
+ mode_8PSK_flag = 0;
|
|
+ } // end of switch for dvb-s
|
|
+
|
|
+ attached_flag = 0x10;
|
|
+ if (state->attached == 0x10) // must be 0x10 if successfully attached in flexcop_fe_tuner
|
|
+ attached_flag = 0;
|
|
+ ret = 0;
|
|
+ if ( state->dvb_s2_mode & 0x01 ) // if dvb-s2
|
|
+ ret = (cx24120_readreg(state, CX24120_REG_FECMODE) >> 7) & 0x01; // QPSK or 8PSK ???
|
|
+ // bit 4 bit 5 bit 0 bit 3
|
|
+ clock_id = (ret << 3) | attached_flag | (state->dvb_s2_mode & 1) | 4; // possible id: 4, 5, 13. 12-impossible,
|
|
+ // ntv S2 = 0x8E -> 8 | 1 | 4 = 13 // because 7th bit of ret - is S2 flag
|
|
+ // 1/2 S2 = 0x0d -> 0 | 1 | 4 = 5
|
|
+ dbginfo("Check clock table for: clock_id=0x%x, 8PSK_mask=0x%x, mode_code=0x%x\n",
|
|
+ clock_id, mode_8PSK_flag, mode_code);
|
|
+
|
|
+ clock_seq_num = 0;
|
|
+ while ( (clock_ratios_table[clock_seq_num].ratio_id != clock_id) ||
|
|
+ (clock_ratios_table[clock_seq_num].mode_xPSK != mode_8PSK_flag) ||
|
|
+ (clock_ratios_table[clock_seq_num].fec_mode != mode_code) )
|
|
+ {
|
|
+ /* dbginfo("Check table string(%d): clock_id=%d, 8PSK_flag=%d, mode_code=%d\n", clock_seq_num,
|
|
+ * clock_ratios_table[clock_seq_num].ratio_id,
|
|
+ * clock_ratios_table[clock_seq_num].mode_xPSK,
|
|
+ * clock_ratios_table[clock_seq_num].fec_mode);
|
|
+ */
|
|
+ ++clock_seq_num;
|
|
+ if ( clock_seq_num == ARRAY_SIZE(clock_ratios_table) ) {
|
|
+ info("Check in clock table filed: unsupported modulation tuned - data reception in danger. :(\n");
|
|
+ goto settings_end;
|
|
+ }
|
|
+ }
|
|
+ //###############################
|
|
+ dbginfo("Check succesful: GetFEC: %d; post lock: m=%d, n=%d; clock_seq_idx: %d m=%d, n=%d, rate=%d\n",
|
|
+ GettedFEC,
|
|
+ cmd.arg[2] | (cmd.arg[1] << 8) | (cmd.arg[0] << 16), // registers was readed early
|
|
+ cmd.arg[5] | (cmd.arg[4] << 8) | (cmd.arg[3] << 16), // in message with id = 0x16
|
|
+ clock_seq_num,
|
|
+ clock_ratios_table[clock_seq_num].m_rat,
|
|
+ clock_ratios_table[clock_seq_num].n_rat,
|
|
+ clock_ratios_table[clock_seq_num].rate);
|
|
+ //###############################
|
|
+ cmd.id = CMD_CLOCK_SET;
|
|
+ cmd.len = 10;
|
|
+ cmd.reg = 0;
|
|
+ cmd.arg[0] = 0;
|
|
+ cmd.arg[1] = state->attached; // must be 0x10 if successfully attached in flexcop_fe_tuner
|
|
+
|
|
+ cmd.arg[2] = (clock_ratios_table[clock_seq_num].m_rat >> 16) & 0xFF;
|
|
+ cmd.arg[3] = (clock_ratios_table[clock_seq_num].m_rat >> 8) & 0xFF;
|
|
+ cmd.arg[4] = (clock_ratios_table[clock_seq_num].m_rat >> 0) & 0xFF;
|
|
+
|
|
+ cmd.arg[5] = (clock_ratios_table[clock_seq_num].n_rat >> 16) & 0xFF;
|
|
+ cmd.arg[6] = (clock_ratios_table[clock_seq_num].n_rat >> 8) & 0xFF;
|
|
+ cmd.arg[7] = (clock_ratios_table[clock_seq_num].n_rat >> 0) & 0xFF;
|
|
+
|
|
+ cmd.arg[8] = (clock_ratios_table[clock_seq_num].rate >> 8) & 0xFF;
|
|
+ cmd.arg[9] = (clock_ratios_table[clock_seq_num].rate >> 0) & 0xFF;
|
|
+
|
|
+ cx24120_message_send(state, &cmd);
|
|
+
|
|
+ settings_end:
|
|
+ msleep(200);
|
|
+ cx24120_msg_mpeg_output_global_config(state, 1);
|
|
+ state->dvb_s2_mode |= 0x02; // set mpeg flag
|
|
+ state->need_set_mpeg_out &= 0xFE; // clocks set done -> clear flag
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_read_status); // end cx24120_read_status
|
|
+//===================================================================
|
|
+int cx24120_init(struct dvb_frontend *fe)
|
|
+{
|
|
+ const struct firmware *fw;
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ struct cx24120_cmd cmd;
|
|
+ u8 ret, ret_EA, reg1, fL, fH;
|
|
+ u32 vco, xtal_khz;
|
|
+ u64 inv_vco, res, xxyyzz;
|
|
+ int reset_result;
|
|
+
|
|
+ if( state->cold_init ) return 0;
|
|
+
|
|
+ ret = cx24120_writereg(state, 0xEA, 0x00);
|
|
+ ret = cx24120_test_rom(state);
|
|
+ ret = cx24120_readreg(state, 0xFB) & 0xFE;
|
|
+ ret = cx24120_writereg(state, 0xFB, ret);
|
|
+ ret = cx24120_readreg(state, 0xFC) & 0xFE;
|
|
+ ret = cx24120_writereg(state, 0xFC, ret);
|
|
+ ret = cx24120_writereg(state, 0xC3, 0x04);
|
|
+ ret = cx24120_writereg(state, 0xC4, 0x04);
|
|
+ ret = cx24120_writereg(state, 0xCE, 0x00);
|
|
+ ret = cx24120_writereg(state, 0xCF, 0x00);
|
|
+ ret_EA = cx24120_readreg(state, 0xEA) & 0xFE;
|
|
+ ret = cx24120_writereg(state, 0xEA, ret_EA);
|
|
+ ret = cx24120_writereg(state, 0xEB, 0x0C);
|
|
+ ret = cx24120_writereg(state, 0xEC, 0x06);
|
|
+ ret = cx24120_writereg(state, 0xED, 0x05);
|
|
+ ret = cx24120_writereg(state, 0xEE, 0x03);
|
|
+ ret = cx24120_writereg(state, 0xEF, 0x05);
|
|
+ ret = cx24120_writereg(state, 0xF3, 0x03);
|
|
+ ret = cx24120_writereg(state, 0xF4, 0x44);
|
|
+
|
|
+ reg1 = 0xF0;
|
|
+ do {
|
|
+ cx24120_writereg(state, reg1, 0x04);
|
|
+ cx24120_writereg(state, reg1 - 10, 0x02);
|
|
+ ++reg1;
|
|
+ } while ( reg1 != 0xF3 );
|
|
+
|
|
+ ret = cx24120_writereg(state, 0xEA, (ret_EA | 0x01));
|
|
+ reg1 = 0xC5;
|
|
+ do {
|
|
+ ret = cx24120_writereg(state, reg1, 0x00);
|
|
+ ret = cx24120_writereg(state, reg1 + 1, 0x00);
|
|
+ reg1 += 2;
|
|
+ } while ( reg1 != 0xCB );
|
|
+
|
|
+ ret = cx24120_writereg(state, 0xE4, 0x03);
|
|
+ ret = cx24120_writereg(state, 0xEB, 0x0A);
|
|
+
|
|
+ dbginfo("Requesting firmware (%s) to download...\n", CX24120_FIRMWARE);
|
|
+ ret = state->config->request_firmware(fe, &fw, CX24120_FIRMWARE);
|
|
+ if (ret) {
|
|
+ err("Could not load firmware (%s): %d\n", CX24120_FIRMWARE, ret);
|
|
+ return ret;
|
|
+ }
|
|
+ dbginfo("Firmware found and it size is %d bytes (%02x %02x .. %02x %02x)\n",
|
|
+ (int)fw->size, // firmware_size in bytes u32*
|
|
+ fw->data[0], // fw 1st byte
|
|
+ fw->data[1], // fw 2d byte
|
|
+ fw->data[fw->size - 2], // fw before last byte
|
|
+ fw->data[fw->size - 1]); // fw last byte
|
|
+
|
|
+ ret = cx24120_test_rom(state);
|
|
+ ret = cx24120_readreg(state, 0xFB) & 0xFE;
|
|
+ ret = cx24120_writereg(state, 0xFB, ret);
|
|
+ ret = cx24120_writereg(state, 0xE0, 0x76);
|
|
+ ret = cx24120_writereg(state, 0xF7, 0x81);
|
|
+ ret = cx24120_writereg(state, 0xF8, 0x00);
|
|
+ ret = cx24120_writereg(state, 0xF9, 0x00);
|
|
+ ret = cx24120_writeregN(state, 0xFA, fw->data, (fw->size - 1), 0x00);
|
|
+ ret = cx24120_writereg(state, 0xF7, 0xC0);
|
|
+ ret = cx24120_writereg(state, 0xE0, 0x00);
|
|
+ ret = (fw->size - 2) & 0x00FF;
|
|
+ ret = cx24120_writereg(state, 0xF8, ret); // ret now is 0x7a
|
|
+ ret = ((fw->size - 2) >> 8) & 0x00FF;
|
|
+ ret = cx24120_writereg(state, 0xF9, ret); // ret now is 0xaf
|
|
+ ret = cx24120_writereg(state, 0xF7, 0x00);
|
|
+ ret = cx24120_writereg(state, 0xDC, 0x00);
|
|
+ ret = cx24120_writereg(state, 0xDC, 0x07);
|
|
+ msleep(500);
|
|
+
|
|
+ ret = cx24120_readreg(state, 0xE1); // now is 0xd5 - last byte of the firmware
|
|
+ if ( ret == fw->data[fw->size - 1] ) {
|
|
+ dbginfo("Firmware uploaded successfully\n");
|
|
+ reset_result = 0;
|
|
+ } else {
|
|
+ err("Firmware upload failed. Last byte returned=0x%x\n", ret );
|
|
+ reset_result = -EREMOTEIO;
|
|
+ }
|
|
+ ret = cx24120_writereg(state, 0xDC, 0x00);
|
|
+ release_firmware(fw);
|
|
+ if (reset_result)
|
|
+ return reset_result;
|
|
+
|
|
+ //================== Start tuner
|
|
+ cx24120_message_fill(&cmd, CMD_START_TUNER, &cx24120_msg_tuner_init[0], 3, 0); // 0x1B
|
|
+ if(cx24120_message_send(state, &cmd)) {
|
|
+ err("Error tuner start! :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+
|
|
+ cmd.id = CMD_VCO_SET; // 0x10
|
|
+ cmd.len = 12;
|
|
+
|
|
+ // ######################
|
|
+ // Calc VCO
|
|
+ xtal_khz = 10111;
|
|
+ xxyyzz = 0x400000000ULL; // 17179869184
|
|
+ vco = xtal_khz * 10 * 4; // 404440
|
|
+ inv_vco = xxyyzz / vco; // 42478 = 0x00A5EE
|
|
+ res = xxyyzz % vco; // 66864 = 0x010530
|
|
+
|
|
+ if( inv_vco > xtal_khz * 10 * 2) ++inv_vco;
|
|
+
|
|
+ fH = (inv_vco >> 8) & 0xFF;
|
|
+ fL = (inv_vco) & 0xFF;
|
|
+ dbginfo("vco= %d, inv_vco= %lld, res= %lld, fL= 0x%x, fH= 0x%x\n", vco, inv_vco, res, fL, fH);
|
|
+ // ######################
|
|
+
|
|
+ cmd.arg[0] = 0x06;
|
|
+ cmd.arg[1] = 0x2B;
|
|
+ cmd.arg[2] = 0xD8;
|
|
+ cmd.arg[3] = fH; // 0xA5
|
|
+ cmd.arg[4] = fL; // 0xEE
|
|
+ cmd.arg[5] = 0x03;
|
|
+ cmd.arg[6] = 0x9D;
|
|
+ cmd.arg[7] = 0xFC;
|
|
+ cmd.arg[8] = 0x06;
|
|
+ cmd.arg[9] = 0x03;
|
|
+ cmd.arg[10] = 0x27;
|
|
+ cmd.arg[11] = 0x7F;
|
|
+
|
|
+ if(cx24120_message_send(state, &cmd)) {
|
|
+ err("Error set VCO! :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ memset(&cmd, 0, sizeof(struct cx24120_cmd));
|
|
+ // set bandwidth
|
|
+ cmd.id = CMD_BANDWIDTH; // 0x15
|
|
+ cmd.len = 12;
|
|
+ cmd.arg[0] = 0x00;
|
|
+ cmd.arg[1] = 0x00;
|
|
+ cmd.arg[2] = 0x00;
|
|
+ cmd.arg[3] = 0x00;
|
|
+ cmd.arg[4] = 0x05;
|
|
+ cmd.arg[5] = 0x02;
|
|
+ cmd.arg[6] = 0x02;
|
|
+ cmd.arg[7] = 0x00;
|
|
+ cmd.arg[8] = 0x05;
|
|
+ cmd.arg[9] = 0x02;
|
|
+ cmd.arg[10] = 0x02;
|
|
+ cmd.arg[11] = 0x00;
|
|
+
|
|
+ if ( cx24120_message_send(state, &cmd) ) {
|
|
+ err("Error set bandwidth! :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ ret = cx24120_readreg(state, 0xBA);
|
|
+ if ( ret > 3) {
|
|
+ dbginfo("Reset-readreg 0xBA: %x\n", ret);
|
|
+ err("Error intitilizing tuner! :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ dbginfo("Tuner initialized correctly.\n");
|
|
+
|
|
+ ret = cx24120_writereg(state, 0xEB, 0x0A);
|
|
+ if (cx24120_msg_mpeg_output_global_config(state, 0) ||
|
|
+ cx24120_msg_mpeg_output_config(state, 0, &initial_mpeg_config) ||
|
|
+ cx24120_msg_mpeg_output_config(state, 1, &initial_mpeg_config) ||
|
|
+ cx24120_msg_mpeg_output_config(state, 2, &initial_mpeg_config) )
|
|
+ {
|
|
+ err("Error initilizing mpeg output. :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ } else {
|
|
+ cmd.id = 0x3C; // 60
|
|
+ cmd.len = 0x03;
|
|
+ cmd.arg[0] = 0x00;
|
|
+ cmd.arg[1] = 0x10;
|
|
+ cmd.arg[2] = 0x10;
|
|
+ if(cx24120_message_send(state, &cmd)) {
|
|
+ err("Error sending final init message. :(\n");
|
|
+ return -EREMOTEIO;
|
|
+ }
|
|
+ }
|
|
+ state->cold_init=1;
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_init); // end cx24120_reset
|
|
+//===================================================================
|
|
+static int cx24120_tune(struct dvb_frontend *fe, bool re_tune,
|
|
+ unsigned int mode_flags, unsigned int *delay, fe_status_t *p_status)
|
|
+{
|
|
+ struct dtv_frontend_properties *p = &fe->dtv_property_cache;
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ int delay_cnt, sd_idx = 0;
|
|
+ fe_status_t status;
|
|
+
|
|
+ if (re_tune) {
|
|
+
|
|
+// dbginfo("Compare symrate with table: symrate= %d, in table= %d\n",
|
|
+// p->u.qpsk.symbol_rate, symrates_pairs[sd_idx].symrate);
|
|
+
|
|
+ while ( p->symbol_rate > symrates_pairs[sd_idx].symrate ) {
|
|
+ ++sd_idx;
|
|
+ }
|
|
+ dbginfo("Found symrate delay = %d\n", symrates_pairs[sd_idx].delay);
|
|
+ state->dvb_s2_mode &= 0xFE; // clear bit -> try not DVB-S2
|
|
+ dbginfo("trying DVB-S =================\n");
|
|
+ cx24120_set_frontend(fe);
|
|
+
|
|
+ delay_cnt = symrates_pairs[sd_idx].delay;
|
|
+ dbginfo("Wait for LOCK for DVB-S =================\n");
|
|
+ while (delay_cnt >= 0) {
|
|
+ cx24120_read_status(fe, &status);
|
|
+ if (status & FE_HAS_LOCK) {
|
|
+ dbginfo("DVB-S LOCKED================\n");
|
|
+ break;
|
|
+ }
|
|
+ msleep(100);
|
|
+ delay_cnt -=100;
|
|
+ }
|
|
+ dbginfo("Waiting finished - NO lock for DVB-S =================\n");
|
|
+
|
|
+ cx24120_read_status(fe, &status);
|
|
+ if ( !(status & FE_HAS_LOCK) ) { // if no lock on S
|
|
+ dbginfo("trying DVB-S2 ++++++++++++++++++++++++++\n");
|
|
+ state->dvb_s2_mode |= 0x01; // may be it locked on S2 ?
|
|
+ p->fec_inner = FEC_AUTO;
|
|
+ cx24120_set_frontend(fe);
|
|
+ delay_cnt = symrates_pairs[sd_idx].delay;
|
|
+ dbginfo("Wait for LOCK for DVB-S2 ++++++++++++++++\n");
|
|
+ while (delay_cnt >= 0) {
|
|
+ cx24120_read_status(fe, &status);
|
|
+ if (status & FE_HAS_LOCK) {
|
|
+ dbginfo("DVB-S2 LOCKED++++++++++++++++\n");
|
|
+ break;
|
|
+ }
|
|
+ msleep(100);
|
|
+ delay_cnt -=100;
|
|
+ }
|
|
+ dbginfo("Waiting finished - NO lock for DVB-S2 ++++++++++++++++\n");
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_tune); // end of cx24120_tune
|
|
+//===================================================================
|
|
+static int cx24120_get_algo(struct dvb_frontend *fe)
|
|
+{
|
|
+ return DVBFE_ALGO_HW;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_get_algo);
|
|
+//===================================================================
|
|
+static int cx24120_sleep(struct dvb_frontend *fe)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_sleep);
|
|
+//===================================================================
|
|
+/*static int cx24120_wakeup(struct dvb_frontend *fe)
|
|
+ * {
|
|
+ * return 0;
|
|
+ * }
|
|
+ * EXPORT_SYMBOL(cx24120_wakeup);
|
|
+ */
|
|
+//===================================================================
|
|
+static int cx24120_get_frontend(struct dvb_frontend *fe)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_get_frontend);
|
|
+//===================================================================
|
|
+static void cx24120_release(struct dvb_frontend *fe)
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+ dbginfo("Clear state structure\n");
|
|
+ kfree(state);
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_release);
|
|
+//===================================================================
|
|
+static int cx24120_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) // UNCORRECTED_BLOCKS
|
|
+{
|
|
+ struct cx24120_state *state = fe->demodulator_priv;
|
|
+
|
|
+ *ucblocks = (cx24120_readreg(state, CX24120_REG_UCB_H) << 8) |
|
|
+ cx24120_readreg(state, CX24120_REG_UCB_L);
|
|
+ dbginfo("Blocks = %d\n", *ucblocks);
|
|
+ return 0;
|
|
+}
|
|
+EXPORT_SYMBOL(cx24120_read_ucblocks);
|
|
+// ########################################################################################
|
|
+static struct dvb_frontend_ops cx24120_ops = {
|
|
+
|
|
+ .delsys = { SYS_DVBS2 },
|
|
+ .info = {
|
|
+ .name = "Conexant CX24120/CX24118",
|
|
+ .frequency_min = 950000,
|
|
+ .frequency_max = 2150000,
|
|
+ .frequency_stepsize = 1011, /* kHz for QPSK frontends */
|
|
+ .frequency_tolerance = 5000,
|
|
+ .symbol_rate_min = 1000000,
|
|
+ .symbol_rate_max = 45000000,
|
|
+ .caps = // 0x500006ff
|
|
+ FE_CAN_INVERSION_AUTO | //0x00 000 001
|
|
+ FE_CAN_FEC_1_2 | //0x00 000 002
|
|
+ FE_CAN_FEC_2_3 | //0x00 000 004
|
|
+ FE_CAN_FEC_3_4 | //0x00 000 008
|
|
+ FE_CAN_FEC_4_5 | //0x00 000 010
|
|
+ FE_CAN_FEC_5_6 | //0x00 000 020
|
|
+ FE_CAN_FEC_6_7 | //0x00 000 040
|
|
+ FE_CAN_FEC_7_8 | //0x00 000 080
|
|
+ FE_CAN_FEC_AUTO | //0x00 000 200
|
|
+ FE_CAN_QPSK | //0x00 000 400
|
|
+//??? FE_HAS_EXTENDED_CAPS | //0x00 800 000 /* We need more bitspace for newer APIs, indicate this. */
|
|
+ FE_CAN_2G_MODULATION | //0x10 000 000 /* frontend supports "2nd generation modulation" (DVB-S2) */
|
|
+ FE_CAN_RECOVER //0x40 000 000 /* frontend can recover from a cable unplug automatically */
|
|
+ }, //sum=50 000 6FF
|
|
+ .release = cx24120_release,
|
|
+
|
|
+ .init = cx24120_init,
|
|
+ .sleep = cx24120_sleep,
|
|
+
|
|
+ .tune = cx24120_tune,
|
|
+ .get_frontend_algo = cx24120_get_algo,
|
|
+ .set_frontend = cx24120_set_frontend,
|
|
+
|
|
+ .get_frontend = cx24120_get_frontend,
|
|
+ .read_status = cx24120_read_status,
|
|
+ .read_ber = cx24120_read_ber,
|
|
+ .read_signal_strength = cx24120_read_signal_strength,
|
|
+ .read_snr = cx24120_read_snr,
|
|
+ .read_ucblocks = cx24120_read_ucblocks,
|
|
+
|
|
+ .diseqc_send_master_cmd = cx24120_send_diseqc_msg,
|
|
+
|
|
+ .diseqc_send_burst = cx24120_diseqc_send_burst,
|
|
+ .set_tone = cx24120_set_tone,
|
|
+ .set_voltage = cx24120_set_voltage,
|
|
+};
|
|
+//===================================================================
|
|
+MODULE_PARM_DESC(cx24120_debug, "prints some verbose debugging information (default:0)");
|
|
+MODULE_AUTHOR("Sergey Tyurin");
|
|
+MODULE_LICENSE("GPL");
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h
|
|
--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120_const.h 1970-01-01 03:00:00.000000000 +0300
|
|
+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120_const.h 2012-04-03 16:37:20.684139905 +0400
|
|
@@ -0,0 +1,259 @@
|
|
+/*
|
|
+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver
|
|
+ * DVBS/S2 Satellite demod/tuner driver static definitins
|
|
+ *
|
|
+ * Copyright (C) 2009 Sergey Tyurin <forum.free-x.de>
|
|
+ * Updated 2012 by Jannis Achstetter <jannis_achstetter@web.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.
|
|
+ */
|
|
+
|
|
+#define CX24120_FIRMWARE "dvb-fe-cx24120-1.20.58.2.fw"
|
|
+
|
|
+// ##############################
|
|
+// ### cx24120 i2c registers ###
|
|
+#define CX24120_REG_CMD_START (0x00) // write cmd_id, and then start write args to next register:
|
|
+#define CX24120_REG_CMD_ARGS (0x01) // write command arguments, max 4 at once, then next 4, etc.
|
|
+#define CX24120_REG_CMD_END (0x1F) // write 0x01 for end, and read it for command result
|
|
+
|
|
+#define CX24120_REG_FECMODE (0x39) // FEC status
|
|
+#define CX24120_REG_STATUS (0x3A) // Tuner status - signal, carrier, sync, lock ...
|
|
+#define CX24120_REG_QUALITY_H (0x40) // SNR high byte
|
|
+#define CX24120_REG_QUALITY_L (0x41) // SNR low byte
|
|
+
|
|
+#define CX24120_REG_BER_HH (0x47) // BER high byte of high word
|
|
+#define CX24120_REG_BER_HL (0x48) // BER low byte of high word
|
|
+#define CX24120_REG_BER_LH (0x49) // BER high byte of low word
|
|
+#define CX24120_REG_BER_LL (0x4A) // BER low byte of low word
|
|
+
|
|
+#define CX24120_REG_SIGSTR_H (0x3A) // Signal strength high byte & ??? status register ???
|
|
+#define CX24120_REG_SIGSTR_L (0x3B) // Signal strength low byte
|
|
+
|
|
+#define CX24120_REG_UCB_H (0x50) // UCB high byte
|
|
+#define CX24120_REG_UCB_L (0x51) // UCB low byte
|
|
+
|
|
+#define CX24120_REG_REVISION (0xFF) // Chip revision (ro). Must be 0x7 or 0x5
|
|
+
|
|
+// ##############################
|
|
+/* Command messages */
|
|
+enum command_message_id {
|
|
+ CMD_VCO_SET = 0x10, // cmdlen = 12;
|
|
+ CMD_TUNEREQUEST = 0x11, // cmd.len = 15;
|
|
+
|
|
+ CMD_MPEG_ONOFF = 0x13, // cmd.len = 4;
|
|
+ CMD_MPEG_INIT = 0x14, // cmd.len = 7;
|
|
+ CMD_BANDWIDTH = 0x15, // cmd.len = 12;
|
|
+ CMD_CLOCK_READ = 0x16, // read clock from registers 0x01-0x06
|
|
+ CMD_CLOCK_SET = 0x17, // cmd.len = 10;
|
|
+
|
|
+ CMD_DISEQC_MSG1 = 0x20, // cmd.len = 11;
|
|
+ CMD_DISEQC_MSG2 = 0x21, // cmd.len = d->msg_len + 6;
|
|
+ CMD_SETVOLTAGE = 0x22, // cmd.len = 2;
|
|
+ CMD_SETTONE = 0x23, // cmd.len = 4;
|
|
+ CMD_DISEQC_BURST = 0x24, // cmd.len not used !!!
|
|
+
|
|
+ CMD_READ_SNR = 0x1A, // Read signal strength
|
|
+ CMD_START_TUNER = 0x1B, // ???
|
|
+
|
|
+ CMD_TUNER_INIT = 0x3C, // cmd.len = 0x03;
|
|
+};
|
|
+// ##############################
|
|
+/* signal status */
|
|
+#define CX24120_HAS_SIGNAL (0x01)
|
|
+#define CX24120_HAS_CARRIER (0x02)
|
|
+#define CX24120_HAS_VITERBI (0x04)
|
|
+#define CX24120_HAS_LOCK (0x08)
|
|
+#define CX24120_HAS_UNK1 (0x10)
|
|
+#define CX24120_HAS_UNK2 (0x20)
|
|
+#define CX24120_STATUS_MASK (0x0f)
|
|
+#define CX24120_SIGNAL_MASK (0xc0)
|
|
+
|
|
+static u8 cx24120_msg_tuner_init[] = { 0,0,0,0,0,0 };
|
|
+static u8 cx24120_msg_read_sigstr[] = {0,0};
|
|
+
|
|
+static struct cx24120_skystar2_mpeg_config {
|
|
+ u8 x1;
|
|
+ u8 x2;
|
|
+ u8 x3;
|
|
+} initial_mpeg_config = {
|
|
+ 0xA1, // 10100001
|
|
+ 0x76, // 01110110
|
|
+ 0x07, // 00000111
|
|
+};
|
|
+
|
|
+static struct cx24120_symrate_delay {
|
|
+ u32 symrate;
|
|
+ u32 delay;
|
|
+} symrates_pairs[] = {
|
|
+ { 3000000, 15000 },
|
|
+ { 6000000, 10000 },
|
|
+ { 8000000, 5000 },
|
|
+ { 10000000, 2000 },
|
|
+ {0x0FFFFFFFF, 400 },
|
|
+};
|
|
+
|
|
+static struct cx24120_clock_ratios_table {
|
|
+ u32 ratio_id;
|
|
+ u32 mode_xPSK;
|
|
+ u32 fec_mode;
|
|
+ u32 m_rat;
|
|
+ u32 n_rat;
|
|
+ u32 rate;
|
|
+} clock_ratios_table[] = {
|
|
+{ 21 , 0 , 1 , 770068 , 763515 , 258 },
|
|
+{ 21 , 0 , 100 , 97409 , 80370 , 310 },
|
|
+{ 21 , 0 , 2 , 137293 , 101802 , 345 },
|
|
+{ 21 , 0 , 3 , 4633447 , 3054060 , 388 },
|
|
+{ 21 , 0 , 4 , 2472041 , 1527030 , 414 },
|
|
+{ 21 , 0 , 5 , 85904 , 50901 , 432 },
|
|
+{ 21 , 0 , 8 , 2751229 , 1527030 , 461 },
|
|
+{ 21 , 0 , 101 , 1392872 , 763515 , 467 },
|
|
+{ 21 , 99 , 100 , 1850771 , 1019430 , 464 },
|
|
+{ 21 , 99 , 2 , 137293 , 67962 , 517 },
|
|
+{ 21 , 99 , 3 , 4633447 , 2038860 , 581 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 21 , 99 , 5 , 85904 , 33981 , 647 },
|
|
+{ 21 , 99 , 8 , 2751229 , 1019430 , 690 },
|
|
+{ 21 , 99 , 101 , 1392872 , 509715 , 699 },
|
|
+{ 29 , 0 , 1 , 770068 , 782127 , 252 },
|
|
+{ 29 , 0 , 100 , 1850771 , 1564254 , 302 },
|
|
+{ 29 , 0 , 2 , 686465 , 521418 , 337 },
|
|
+{ 29 , 0 , 3 , 4633447 , 3128508 , 379 },
|
|
+{ 29 , 0 , 4 , 2472041 , 1564254 , 404 },
|
|
+{ 29 , 0 , 5 , 429520 , 260709 , 421 },
|
|
+{ 29 , 0 , 8 , 2751229 , 1564254 , 450 },
|
|
+{ 29 , 0 , 101 , 1392872 , 782127 , 455 },
|
|
+{ 29 , 99 , 100 , 1850771 , 1043118 , 454 },
|
|
+{ 29 , 99 , 2 , 686465 , 347706 , 505 },
|
|
+{ 29 , 99 , 3 , 4633447 , 2086236 , 568 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 29 , 99 , 5 , 429520 , 173853 , 632 },
|
|
+{ 29 , 99 , 8 , 2751229 , 1043118 , 675 },
|
|
+{ 29 , 99 , 101 , 1392872 , 521559 , 683 },
|
|
+{ 17 , 0 , 1 , 766052 , 763515 , 256 },
|
|
+{ 17 , 0 , 100 , 96901 , 80370 , 308 },
|
|
+{ 17 , 0 , 2 , 136577 , 101802 , 343 },
|
|
+{ 17 , 0 , 3 , 4609283 , 3054060 , 386 },
|
|
+{ 17 , 0 , 4 , 2459149 , 1527030 , 412 },
|
|
+{ 17 , 0 , 5 , 85456 , 50901 , 429 },
|
|
+{ 17 , 0 , 8 , 2736881 , 1527030 , 458 },
|
|
+{ 17 , 0 , 101 , 1385608 , 763515 , 464 },
|
|
+{ 17 , 99 , 100 , 1841119 , 1019430 , 462 },
|
|
+{ 17 , 99 , 2 , 136577 , 67962 , 514 },
|
|
+{ 17 , 99 , 3 , 4609283 , 2038860 , 578 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 17 , 99 , 5 , 85456 , 33981 , 643 },
|
|
+{ 17 , 99 , 8 , 2736881 , 1019430 , 687 },
|
|
+{ 17 , 99 , 101 , 1385608 , 509715 , 695 },
|
|
+{ 25 , 0 , 1 , 766052 , 782127 , 250 },
|
|
+{ 25 , 0 , 100 , 1841119 , 1564254 , 301 },
|
|
+{ 25 , 0 , 2 , 682885 , 521418 , 335 },
|
|
+{ 25 , 0 , 3 , 4609283 , 3128508 , 377 },
|
|
+{ 25 , 0 , 4 , 2459149 , 1564254 , 402 },
|
|
+{ 25 , 0 , 5 , 427280 , 260709 , 419 },
|
|
+{ 25 , 0 , 8 , 2736881 , 1564254 , 447 },
|
|
+{ 25 , 0 , 101 , 1385608 , 782127 , 453 },
|
|
+{ 25 , 99 , 100 , 1841119 , 1043118 , 451 },
|
|
+{ 25 , 99 , 2 , 682885 , 347706 , 502 },
|
|
+{ 25 , 99 , 3 , 4609283 , 2086236 , 565 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 25 , 99 , 5 , 427280 , 173853 , 629 },
|
|
+{ 25 , 99 , 8 , 2736881 , 1043118 , 671 },
|
|
+{ 25 , 99 , 101 , 1385608 , 521559 , 680 },
|
|
+{ 5 , 0 , 1 , 273088 , 254505 , 274 },
|
|
+{ 5 , 0 , 100 , 17272 , 13395 , 330 },
|
|
+{ 5 , 0 , 2 , 24344 , 16967 , 367 },
|
|
+{ 5 , 0 , 3 , 410788 , 254505 , 413 },
|
|
+{ 5 , 0 , 4 , 438328 , 254505 , 440 },
|
|
+{ 5 , 0 , 5 , 30464 , 16967 , 459 },
|
|
+{ 5 , 0 , 8 , 487832 , 254505 , 490 },
|
|
+{ 5 , 0 , 101 , 493952 , 254505 , 496 },
|
|
+{ 5 , 99 , 100 , 328168 , 169905 , 494 },
|
|
+{ 5 , 99 , 2 , 24344 , 11327 , 550 }, // work for 0x0d - 11278V - DVB-S2 - 8PSK MPEG-4/HD
|
|
+{ 5 , 99 , 3 , 410788 , 169905 , 618 }, // 0x0e S2 8psk // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 5 , 99 , 5 , 30464 , 11327 , 688 },
|
|
+{ 5 , 99 , 8 , 487832 , 169905 , 735 },
|
|
+{ 5 , 99 , 101 , 493952 , 169905 , 744 },
|
|
+{ 13 , 0 , 1 , 273088 , 260709 , 268 },
|
|
+{ 13 , 0 , 100 , 328168 , 260709 , 322 },
|
|
+{ 13 , 0 , 2 , 121720 , 86903 , 358 },
|
|
+{ 13 , 0 , 3 , 410788 , 260709 , 403 },
|
|
+{ 13 , 0 , 4 , 438328 , 260709 , 430 },
|
|
+{ 13 , 0 , 5 , 152320 , 86903 , 448 },
|
|
+{ 13 , 0 , 8 , 487832 , 260709 , 479 },
|
|
+{ 13 , 0 , 101 , 493952 , 260709 , 485 },
|
|
+{ 13 , 99 , 100 , 328168 , 173853 , 483 },
|
|
+{ 13 , 99 , 2 , 121720 , 57951 , 537 }, // work for 0x8d - dvb-s2 8psk
|
|
+{ 13 , 99 , 3 , 410788 , 173853 , 604 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 13 , 99 , 5 , 152320 , 57951 , 672 },
|
|
+{ 13 , 99 , 8 , 487832 , 173853 , 718 },
|
|
+{ 13 , 99 , 101 , 493952 , 173853 , 727 },
|
|
+{ 1 , 0 , 1 , 815248 , 763515 , 273 },
|
|
+{ 1 , 0 , 100 , 51562 , 40185 , 328 },
|
|
+{ 1 , 0 , 2 , 72674 , 50901 , 365 },
|
|
+{ 1 , 0 , 3 , 1226323 , 763515 , 411 },
|
|
+{ 1 , 0 , 4 , 1308538 , 763515 , 438 },
|
|
+{ 1 , 0 , 5 , 90944 , 50901 , 457 },
|
|
+{ 1 , 0 , 8 , 1456322 , 763515 , 488 },
|
|
+{ 1 , 0 , 101 , 1474592 , 763515 , 494 },
|
|
+{ 1 , 99 , 100 , 979678 , 509715 , 492 },
|
|
+{ 1 , 99 , 2 , 72674 , 33981 , 547 },
|
|
+{ 1 , 99 , 3 , 1226323 , 509715 , 615 }, // was 4 - ERRORR!? FEC_4_5 not in DVB-S2
|
|
+{ 1 , 99 , 5 , 90944 , 33981 , 685 },
|
|
+{ 1 , 99 , 8 , 1456322 , 509715 , 731 },
|
|
+{ 1 , 99 , 101 , 1474592 , 509715 , 740 },
|
|
+{ 9 , 0 , 1 , 815248 , 782127 , 266 },
|
|
+{ 9 , 0 , 100 , 979678 , 782127 , 320 },
|
|
+{ 9 , 0 , 2 , 363370 , 260709 , 356 },
|
|
+{ 9 , 0 , 3 , 1226323 , 782127 , 401 },
|
|
+{ 9 , 0 , 4 , 1308538 , 782127 , 428 },
|
|
+{ 9 , 0 , 5 , 454720 , 260709 , 446 },
|
|
+{ 9 , 0 , 8 , 1456322 , 782127 , 476 },
|
|
+{ 9 , 0 , 101 , 1474592 , 782127 , 482 },
|
|
+{ 9 , 99 , 100 , 979678 , 521559 , 480 },
|
|
+{ 9 , 99 , 2 , 363370 , 173853 , 535 },
|
|
+{ 9 , 99 , 3 , 1226323 , 521559 , 601 }, // was 4 - ERRORR! FEC_4_5 not in DVB-S2
|
|
+{ 9 , 99 , 5 , 454720 , 173853 , 669 },
|
|
+{ 9 , 99 , 8 , 1456322 , 521559 , 714 },
|
|
+{ 9 , 99 , 101 , 1474592 , 521559 , 723 },
|
|
+{ 18 , 0 , 1 , 535 , 588 , 233 },
|
|
+{ 18 , 0 , 2 , 1070 , 882 , 311 },
|
|
+{ 18 , 0 , 6 , 3210 , 2058 , 399 },
|
|
+{ 16 , 0 , 1 , 763 , 816 , 239 },
|
|
+{ 16 , 0 , 2 , 1526 , 1224 , 319 },
|
|
+{ 16 , 0 , 3 , 2289 , 1632 , 359 },
|
|
+{ 16 , 0 , 5 , 3815 , 2448 , 399 },
|
|
+{ 16 , 0 , 7 , 5341 , 3264 , 419 },
|
|
+{ 22 , 0 , 1 , 535 , 588 , 233 },
|
|
+{ 22 , 0 , 2 , 1070 , 882 , 311 },
|
|
+{ 22 , 0 , 6 , 3210 , 2058 , 399 },
|
|
+{ 20 , 0 , 1 , 143429 , 152592 , 241 },
|
|
+{ 20 , 0 , 2 , 286858 , 228888 , 321 },
|
|
+{ 20 , 0 , 3 , 430287 , 305184 , 361 },
|
|
+{ 20 , 0 , 5 , 717145 , 457776 , 401 },
|
|
+{ 20 , 0 , 7 , 1004003 , 610368 , 421 },
|
|
+{ 2 , 0 , 1 , 584 , 588 , 254 },
|
|
+{ 2 , 0 , 2 , 1169 , 882 , 339 },
|
|
+{ 2 , 0 , 6 , 3507 , 2058 , 436 },
|
|
+{ 0 , 0 , 1 , 812 , 816 , 255 },
|
|
+{ 0 , 0 , 2 , 1624 , 1224 , 340 },
|
|
+{ 0 , 0 , 3 , 2436 , 1632 , 382 },
|
|
+{ 0 , 0 , 5 , 4060 , 2448 , 425 },
|
|
+{ 0 , 0 , 7 , 5684 , 3264 , 446 },
|
|
+{ 6 , 0 , 1 , 584 , 588 , 254 },
|
|
+{ 6 , 0 , 2 , 1168 , 882 , 339 },
|
|
+{ 6 , 0 , 6 , 3504 , 2058 , 436 },
|
|
+{ 4 , 0 , 1 , 152592 , 152592 , 256 },
|
|
+{ 4 , 0 , 2 , 305184 , 228888 , 341 },
|
|
+{ 4 , 0 , 3 , 457776 , 305184 , 384 },
|
|
+{ 4 , 0 , 5 , 762960 , 457776 , 427 },
|
|
+{ 4 , 0 , 7 , 1068144 , 610368 , 448 },
|
|
+};
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h
|
|
--- linux-3.4-r1/drivers/media/dvb-frontends/cx24120.h 1970-01-01 03:00:00.000000000 +0300
|
|
+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/cx24120.h 2012-04-03 10:27:59.000000000 +0400
|
|
@@ -0,0 +1,59 @@
|
|
+/*
|
|
+ * Conexant CX24120/CX24118 - DVB-S/S2 demod/tuner driver
|
|
+ *
|
|
+ * Copyright (C) 2008 Patrick Boettcher <pb@linuxtv.org>
|
|
+ * Copyright (C) 2009 Sergey Tyurin <forum.free-x.de>
|
|
+ * Updated 2012 by Jannis Achstetter <jannis_achstetter@web.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 CX24120_H
|
|
+#define CX24120_H
|
|
+
|
|
+#include <linux/dvb/frontend.h>
|
|
+
|
|
+struct firmware;
|
|
+struct dvb_frontend;
|
|
+struct i2c_adapter;
|
|
+
|
|
+struct cx24120_config
|
|
+{
|
|
+ u8 i2c_addr;
|
|
+ int (*request_firmware)(struct dvb_frontend *fe, const struct firmware **fw, char *name);
|
|
+ void (*stream_control)(struct dvb_frontend *fe, u8 onoff);
|
|
+};
|
|
+
|
|
+#if defined(CONFIG_DVB_CX24120) || \
|
|
+ (defined(CONFIG_DVB_CX24120_MODULE) && defined(MODULE))
|
|
+extern struct dvb_frontend *cx24120_attach(const struct cx24120_config *config,
|
|
+ struct i2c_adapter *i2c);
|
|
+extern int cx24120_reset(struct dvb_frontend *fe);
|
|
+#else
|
|
+static inline
|
|
+struct dvb_frontend *cx24120_attach(const struct cx24120_config *config,
|
|
+ struct i2c_adapter *i2c)
|
|
+{
|
|
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
|
+ return NULL;
|
|
+}
|
|
+static inline int cx24120_reset(struct dvb_frontend *fe)
|
|
+{
|
|
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
|
|
+ return -ENODEV;
|
|
+}
|
|
+#endif
|
|
+
|
|
+#endif
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Kconfig linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig
|
|
--- linux-3.4-r1/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:23:44.976143444 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Kconfig 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -4,6 +4,13 @@
|
|
comment "Multistandard (satellite) frontends"
|
|
depends on DVB_CORE
|
|
|
|
+config DVB_CX24120
|
|
+ tristate "Conexant CX24120 based"
|
|
+ depends on DVB_CORE && I2C
|
|
+ default m if DVB_FE_CUSTOMISE
|
|
+ help
|
|
+ A DVB-S/DVB-S2 tuner module. Say Y when you want to support this frontend.
|
|
+
|
|
config DVB_STB0899
|
|
tristate "STB0899 based"
|
|
depends on DVB_CORE && I2C
|
|
diff -NurEbBw --strip-trailing-cr linux-3.4-r1/drivers/media/dvb-frontends/Makefile linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile
|
|
--- linux-3.4-r1/drivers/media/dvb-frontends/Makefile 2012-04-03 15:23:44.976143444 +0400
|
|
+++ linux-3.4-r1-S2/drivers/media/dvb-frontends/Makefile 2012-04-03 15:26:40.760141513 +0400
|
|
@@ -19,6 +19,10 @@
|
|
obj-$(CONFIG_DVB_CX22700) += cx22700.o
|
|
obj-$(CONFIG_DVB_S5H1432) += s5h1432.o
|
|
obj-$(CONFIG_DVB_CX24110) += cx24110.o
|
|
+
|
|
+# inserted by Custler
|
|
+obj-$(CONFIG_DVB_CX24120) += cx24120.o
|
|
+
|
|
obj-$(CONFIG_DVB_TDA8083) += tda8083.o
|
|
obj-$(CONFIG_DVB_L64781) += l64781.o
|
|
obj-$(CONFIG_DVB_DIB3000MB) += dib3000mb.o
|