Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media update from Mauro Carvalho Chehab:

 - OF documentation and patches at core and drivers, to be used by for
   embedded media systems

 - some I2C drivers used on go7007 were rewritten/promoted from staging:
   sony-btf-mpx, tw2804, tw9903, tw9906, wis-ov7640, wis-uda1342

 - add fimc-is driver (Exynos)

 - add a new radio driver: radio-si476x

 - add a two new tuners: r820t and tuner_it913x

 - split camera code on em28xx driver and add more models

 - the cypress firmware load is used outside dvb usb drivers.  So, move
   it to a common directory to make easier to re-use it

 - siano media driver updated to work with sms2270 devices

 - several work done in order to promote go7007 and solo6x1x out of
   staging (still, there are some pending issues)

 - several API compliance fixes at v4l2 drivers that don't behave as
   expected

 - as usual, lots of driver fixes, improvements, cleanups and new device
   addition at the existing drivers.

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (831 commits)
  [media] cx88: make core less verbose
  [media] em28xx: fix oops at em28xx_dvb_bus_ctrl()
  [media] s5c73m3: fix indentation of the help section in Kconfig
  [media] cx25821-alsa: get rid of a __must_check warning
  [media] cx25821-video: declare cx25821_vidioc_s_std as static
  [media] cx25821-video: remove maxw from cx25821_vidioc_try_fmt_vid_cap
  [media] r820t: Remove a warning for an unused value
  [media] dib0090: Fix a warning at dib0090_set_EFUSE
  [media] dib8000: fix a warning
  [media] dib8000: Fix sub-channel range
  [media] dib8000: store dtv_property_cache in a temp var
  [media] dib8000: warning fix: declare internal functions as static
  [media] r820t: quiet gcc warning on n_ring
  [media] r820t: memory leak in release()
  [media] r820t: precendence bug in r820t_xtal_check()
  [media] videodev2.h: Remove the unused old V4L1 buffer types
  [media] anysee: Grammar s/report the/report to/
  [media] anysee: Initialize ret = 0 in anysee_frontend_attach()
  [media] media: videobuf2: fix the length check for mmap
  [media] em28xx: save isoc endpoint number for DVB only if endpoint has alt settings with xMaxPacketSize != 0
  ...
This commit is contained in:
Linus Torvalds 2013-04-30 09:58:16 -07:00
commit 240c3c3424
653 changed files with 40821 additions and 28643 deletions

View file

@ -16,6 +16,10 @@ config VIDEO_TVEEPROM
tristate
depends on I2C
config CYPRESS_FIRMWARE
tristate "Cypress firmware helper routines"
depends on USB
source "drivers/media/common/b2c2/Kconfig"
source "drivers/media/common/saa7146/Kconfig"
source "drivers/media/common/siano/Kconfig"

View file

@ -2,3 +2,4 @@ obj-y += b2c2/ saa7146/ siano/
obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
obj-$(CONFIG_VIDEO_BTCX) += btcx-risc.o
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
obj-$(CONFIG_CYPRESS_FIRMWARE) += cypress_firmware.o

View file

@ -325,7 +325,7 @@ static int skystar2_rev27_attach(struct flexcop_device *fc,
/* enable no_base_addr - no repeated start when reading */
fc->fc_i2c_adap[2].no_base_addr = 1;
if (!dvb_attach(isl6421_attach, fc->fe, &fc->fc_i2c_adap[2].i2c_adap,
0x08, 1, 1)) {
0x08, 1, 1, false)) {
err("ISL6421 could NOT be attached");
goto fail_isl;
}
@ -391,7 +391,7 @@ static int skystar2_rev28_attach(struct flexcop_device *fc,
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)) {
0x08, 0, 0, false)) {
err("ISL6421 could NOT be attached");
fc->fc_i2c_adap[2].no_base_addr = 0;
return 0;

View file

@ -8,7 +8,10 @@
*
*/
#include "dvb_usb.h"
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/firmware.h>
#include "cypress_firmware.h"
struct usb_cypress_controller {
@ -30,75 +33,12 @@ static const struct usb_cypress_controller cypress[] = {
static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data,
u8 len)
{
dvb_usb_dbg_usb_control_msg(udev,
0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len);
return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
}
int usbv2_cypress_load_firmware(struct usb_device *udev,
const struct firmware *fw, int type)
{
struct hexline *hx;
int ret, pos = 0;
hx = kmalloc(sizeof(struct hexline), GFP_KERNEL);
if (!hx) {
dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME);
return -ENOMEM;
}
/* stop the CPU */
hx->data[0] = 1;
ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1);
if (ret != 1) {
dev_err(&udev->dev, "%s: CPU stop failed=%d\n",
KBUILD_MODNAME, ret);
ret = -EIO;
goto err_kfree;
}
/* write firmware to memory */
for (;;) {
ret = dvb_usbv2_get_hexline(fw, hx, &pos);
if (ret < 0)
goto err_kfree;
else if (ret == 0)
break;
ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len);
if (ret < 0) {
goto err_kfree;
} else if (ret != hx->len) {
dev_err(&udev->dev, "%s: error while transferring " \
"firmware (transferred size=%d, " \
"block size=%d)\n",
KBUILD_MODNAME, ret, hx->len);
ret = -EIO;
goto err_kfree;
}
}
/* start the CPU */
hx->data[0] = 0;
ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1);
if (ret != 1) {
dev_err(&udev->dev, "%s: CPU start failed=%d\n",
KBUILD_MODNAME, ret);
ret = -EIO;
goto err_kfree;
}
ret = 0;
err_kfree:
kfree(hx);
return ret;
}
EXPORT_SYMBOL(usbv2_cypress_load_firmware);
int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx,
int *pos)
static int cypress_get_hexline(const struct firmware *fw,
struct hexline *hx, int *pos)
{
u8 *b = (u8 *) &fw->data[*pos];
int data_offs = 4;
@ -127,7 +67,65 @@ int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx,
return *pos;
}
EXPORT_SYMBOL(dvb_usbv2_get_hexline);
int cypress_load_firmware(struct usb_device *udev,
const struct firmware *fw, int type)
{
struct hexline *hx;
int ret, pos = 0;
hx = kmalloc(sizeof(struct hexline), GFP_KERNEL);
if (!hx) {
dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME);
return -ENOMEM;
}
/* stop the CPU */
hx->data[0] = 1;
ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1);
if (ret != 1) {
dev_err(&udev->dev, "%s: CPU stop failed=%d\n",
KBUILD_MODNAME, ret);
ret = -EIO;
goto err_kfree;
}
/* write firmware to memory */
for (;;) {
ret = cypress_get_hexline(fw, hx, &pos);
if (ret < 0)
goto err_kfree;
else if (ret == 0)
break;
ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len);
if (ret < 0) {
goto err_kfree;
} else if (ret != hx->len) {
dev_err(&udev->dev,
"%s: error while transferring firmware (transferred size=%d, block size=%d)\n",
KBUILD_MODNAME, ret, hx->len);
ret = -EIO;
goto err_kfree;
}
}
/* start the CPU */
hx->data[0] = 0;
ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1);
if (ret != 1) {
dev_err(&udev->dev, "%s: CPU start failed=%d\n",
KBUILD_MODNAME, ret);
ret = -EIO;
goto err_kfree;
}
ret = 0;
err_kfree:
kfree(hx);
return ret;
}
EXPORT_SYMBOL(cypress_load_firmware);
MODULE_AUTHOR("Antti Palosaari <[email protected]>");
MODULE_DESCRIPTION("Cypress firmware download");

View file

@ -1,5 +1,4 @@
/* cypress_firmware.h is part of the DVB USB library.
*
/*
* Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
* see dvb-usb-init.c for copyright information.
*
@ -23,9 +22,7 @@ struct hexline {
u8 data[255];
u8 chk;
};
extern int usbv2_cypress_load_firmware(struct usb_device *,
const struct firmware *, int);
extern int dvb_usbv2_get_hexline(const struct firmware *,
struct hexline *, int *);
int cypress_load_firmware(struct usb_device *, const struct firmware *, int);
#endif

View file

@ -832,7 +832,7 @@ static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
}
*/
static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id id)
{
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
struct saa7146_vv *vv = dev->vv_data;
@ -856,7 +856,7 @@ static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id *id)
}
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
if (*id & dev->ext_vv_data->stds[i].id)
if (id & dev->ext_vv_data->stds[i].id)
break;
if (i != dev->ext_vv_data->num_stds) {
vv->standard = &dev->ext_vv_data->stds[i];

View file

@ -17,3 +17,15 @@ config SMS_SIANO_RC
default y
---help---
Choose Y to select Remote Controller support for Siano driver.
config SMS_SIANO_DEBUGFS
bool "Enable debugfs for smsdvb"
depends on SMS_SIANO_MDTV
depends on DEBUG_FS
depends on SMS_USB_DRV
---help---
Choose Y to enable visualizing a dump of the frontend
statistics response packets via debugfs. Currently, works
only with Siano USB devices.
Useful only for developers. In doubt, say N.

View file

@ -1,4 +1,5 @@
smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o
smsdvb-objs := smsdvb-main.o
obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
@ -6,6 +7,10 @@ ifeq ($(CONFIG_SMS_SIANO_RC),y)
smsmdtv-objs += smsir.o
endif
ifeq ($(CONFIG_SMS_SIANO_DEBUGFS),y)
smsdvb-objs += smsdvb-debugfs.o
endif
ccflags-y += -Idrivers/media/dvb-core
ccflags-y += $(extra-cflags-y) $(extra-cflags-m)

View file

@ -28,43 +28,53 @@ MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))");
static struct sms_board sms_boards[] = {
[SMS_BOARD_UNKNOWN] = {
.name = "Unknown board",
.type = SMS_UNKNOWN_TYPE,
.default_mode = DEVICE_MODE_NONE,
},
[SMS1XXX_BOARD_SIANO_STELLAR] = {
.name = "Siano Stellar Digital Receiver",
.type = SMS_STELLAR,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_SIANO_NOVA_A] = {
.name = "Siano Nova A Digital Receiver",
.type = SMS_NOVA_A0,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_SIANO_NOVA_B] = {
.name = "Siano Nova B Digital Receiver",
.type = SMS_NOVA_B0,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_SIANO_VEGA] = {
.name = "Siano Vega Digital Receiver",
.type = SMS_VEGA,
.default_mode = DEVICE_MODE_CMMB,
},
[SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = {
.name = "Hauppauge Catamount",
.type = SMS_STELLAR,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw",
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_STELLAR,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = {
.name = "Hauppauge Okemo-A",
.type = SMS_NOVA_A0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw",
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_A,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = {
.name = "Hauppauge Okemo-B",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw",
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_NOVA_B,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = {
.name = "Hauppauge WinTV MiniStick",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw",
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
.fw[DEVICE_MODE_ISDBT_BDA] = SMS_FW_ISDBT_HCW_55XXX,
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
.default_mode = DEVICE_MODE_DVBT_BDA,
.rc_codes = RC_MAP_HAUPPAUGE,
.board_cfg.leds_power = 26,
.board_cfg.led0 = 27,
@ -77,7 +87,8 @@ static struct sms_board sms_boards[] = {
[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
.name = "Hauppauge WinTV MiniCard",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
.default_mode = DEVICE_MODE_DVBT_BDA,
.lna_ctrl = 29,
.board_cfg.foreign_lna0_ctrl = 29,
.rf_switch = 17,
@ -86,18 +97,65 @@ static struct sms_board sms_boards[] = {
[SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
.name = "Hauppauge WinTV MiniCard",
.type = SMS_NOVA_B0,
.fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
.fw[DEVICE_MODE_DVBT_BDA] = SMS_FW_DVBT_HCW_55XXX,
.default_mode = DEVICE_MODE_DVBT_BDA,
.lna_ctrl = -1,
},
[SMS1XXX_BOARD_SIANO_NICE] = {
/* 11 */
.name = "Siano Nice Digital Receiver",
.type = SMS_NOVA_B0,
.default_mode = DEVICE_MODE_DVBT_BDA,
},
[SMS1XXX_BOARD_SIANO_VENICE] = {
/* 12 */
.name = "Siano Venice Digital Receiver",
.type = SMS_VEGA,
.default_mode = DEVICE_MODE_CMMB,
},
[SMS1XXX_BOARD_SIANO_STELLAR_ROM] = {
.name = "Siano Stellar Digital Receiver ROM",
.type = SMS_STELLAR,
.default_mode = DEVICE_MODE_DVBT_BDA,
.intf_num = 1,
},
[SMS1XXX_BOARD_ZTE_DVB_DATA_CARD] = {
.name = "ZTE Data Card Digital Receiver",
.type = SMS_NOVA_B0,
.default_mode = DEVICE_MODE_DVBT_BDA,
.intf_num = 5,
.mtu = 15792,
},
[SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD] = {
.name = "ONDA Data Card Digital Receiver",
.type = SMS_NOVA_B0,
.default_mode = DEVICE_MODE_DVBT_BDA,
.intf_num = 6,
.mtu = 15792,
},
[SMS1XXX_BOARD_SIANO_MING] = {
.name = "Siano Ming Digital Receiver",
.type = SMS_MING,
.default_mode = DEVICE_MODE_CMMB,
},
[SMS1XXX_BOARD_SIANO_PELE] = {
.name = "Siano Pele Digital Receiver",
.type = SMS_PELE,
.default_mode = DEVICE_MODE_ISDBT_BDA,
},
[SMS1XXX_BOARD_SIANO_RIO] = {
.name = "Siano Rio Digital Receiver",
.type = SMS_RIO,
.default_mode = DEVICE_MODE_ISDBT_BDA,
},
[SMS1XXX_BOARD_SIANO_DENVER_1530] = {
.name = "Siano Denver (ATSC-M/H) Digital Receiver",
.type = SMS_DENVER_1530,
.default_mode = DEVICE_MODE_ATSC,
.crystal = 2400,
},
[SMS1XXX_BOARD_SIANO_DENVER_2160] = {
.name = "Siano Denver (TDMB) Digital Receiver",
.type = SMS_DENVER_2160,
.default_mode = DEVICE_MODE_DAB_TDMB,
},
};
@ -109,20 +167,21 @@ struct sms_board *sms_get_board(unsigned id)
}
EXPORT_SYMBOL_GPL(sms_get_board);
static inline void sms_gpio_assign_11xx_default_led_config(
struct smscore_gpio_config *pGpioConfig) {
pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT;
pGpioConfig->InputCharacteristics =
SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL;
pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA;
pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE;
struct smscore_config_gpio *p_gpio_config) {
p_gpio_config->direction = SMS_GPIO_DIRECTION_OUTPUT;
p_gpio_config->inputcharacteristics =
SMS_GPIO_INPUTCHARACTERISTICS_NORMAL;
p_gpio_config->outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA;
p_gpio_config->outputslewrate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS;
p_gpio_config->pullupdown = SMS_GPIO_PULLUPDOWN_NONE;
}
int sms_board_event(struct smscore_device_t *coredev,
enum SMS_BOARD_EVENTS gevent) {
struct smscore_gpio_config MyGpioConfig;
enum SMS_BOARD_EVENTS gevent)
{
struct smscore_config_gpio my_gpio_config;
sms_gpio_assign_11xx_default_led_config(&MyGpioConfig);
sms_gpio_assign_11xx_default_led_config(&my_gpio_config);
switch (gevent) {
case BOARD_EVENT_POWER_INIT: /* including hotplug */
@ -182,8 +241,8 @@ static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
.direction = SMS_GPIO_DIRECTION_OUTPUT,
.pullupdown = SMS_GPIO_PULLUPDOWN_NONE,
.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
.outputslewrate = SMS_GPIO_OUTPUTSLEWRATE_FAST,
.outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA,
.outputslewrate = SMS_GPIO_OUTPUT_SLEW_RATE_FAST,
.outputdriving = SMS_GPIO_OUTPUTDRIVING_S_4mA,
};
if (pin == 0)
@ -293,19 +352,7 @@ EXPORT_SYMBOL_GPL(sms_board_lna_control);
int sms_board_load_modules(int id)
{
switch (id) {
case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT:
case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A:
case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B:
case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
request_module("smsdvb");
break;
default:
/* do nothing */
break;
}
request_module("smsdvb");
return 0;
}
EXPORT_SYMBOL_GPL(sms_board_load_modules);

View file

@ -37,6 +37,14 @@
#define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10
#define SMS1XXX_BOARD_SIANO_NICE 11
#define SMS1XXX_BOARD_SIANO_VENICE 12
#define SMS1XXX_BOARD_SIANO_STELLAR_ROM 13
#define SMS1XXX_BOARD_ZTE_DVB_DATA_CARD 14
#define SMS1XXX_BOARD_ONDA_MDTV_DATA_CARD 15
#define SMS1XXX_BOARD_SIANO_MING 16
#define SMS1XXX_BOARD_SIANO_PELE 17
#define SMS1XXX_BOARD_SIANO_RIO 18
#define SMS1XXX_BOARD_SIANO_DENVER_1530 19
#define SMS1XXX_BOARD_SIANO_DENVER_2160 20
struct sms_board_gpio_cfg {
int lna_vhf_exist;
@ -79,6 +87,12 @@ struct sms_board {
/* gpios */
int led_power, led_hi, led_lo, lna_ctrl, rf_switch;
char intf_num;
int default_mode;
unsigned int mtu;
unsigned int crystal;
struct sms_antenna_config_ST *antenna_config;
};
struct sms_board *sms_get_board(unsigned id);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,551 @@
/***********************************************************************
*
* Copyright(c) 2013 Mauro Carvalho Chehab <mchehab@redhat.com>
*
* 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, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/debugfs.h>
#include <linux/spinlock.h>
#include <linux/usb.h>
#include "dmxdev.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dvb_frontend.h"
#include "smscoreapi.h"
#include "smsdvb.h"
static struct dentry *smsdvb_debugfs_usb_root;
struct smsdvb_debugfs {
struct kref refcount;
spinlock_t lock;
char stats_data[PAGE_SIZE];
unsigned stats_count;
bool stats_was_read;
wait_queue_head_t stats_queue;
};
static void smsdvb_print_dvb_stats(struct smsdvb_debugfs *debug_data,
struct sms_stats *p)
{
int n = 0;
char *buf;
spin_lock(&debug_data->lock);
if (debug_data->stats_count) {
spin_unlock(&debug_data->lock);
return;
}
buf = debug_data->stats_data;
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_rf_locked = %d\n", p->is_rf_locked);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_demod_locked = %d\n", p->is_demod_locked);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_external_lna_on = %d\n", p->is_external_lna_on);
n += snprintf(&buf[n], PAGE_SIZE - n,
"SNR = %d\n", p->SNR);
n += snprintf(&buf[n], PAGE_SIZE - n,
"ber = %d\n", p->ber);
n += snprintf(&buf[n], PAGE_SIZE - n,
"FIB_CRC = %d\n", p->FIB_CRC);
n += snprintf(&buf[n], PAGE_SIZE - n,
"ts_per = %d\n", p->ts_per);
n += snprintf(&buf[n], PAGE_SIZE - n,
"MFER = %d\n", p->MFER);
n += snprintf(&buf[n], PAGE_SIZE - n,
"RSSI = %d\n", p->RSSI);
n += snprintf(&buf[n], PAGE_SIZE - n,
"in_band_pwr = %d\n", p->in_band_pwr);
n += snprintf(&buf[n], PAGE_SIZE - n,
"carrier_offset = %d\n", p->carrier_offset);
n += snprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\n", p->modem_state);
n += snprintf(&buf[n], PAGE_SIZE - n,
"frequency = %d\n", p->frequency);
n += snprintf(&buf[n], PAGE_SIZE - n,
"bandwidth = %d\n", p->bandwidth);
n += snprintf(&buf[n], PAGE_SIZE - n,
"transmission_mode = %d\n", p->transmission_mode);
n += snprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\n", p->modem_state);
n += snprintf(&buf[n], PAGE_SIZE - n,
"guard_interval = %d\n", p->guard_interval);
n += snprintf(&buf[n], PAGE_SIZE - n,
"code_rate = %d\n", p->code_rate);
n += snprintf(&buf[n], PAGE_SIZE - n,
"lp_code_rate = %d\n", p->lp_code_rate);
n += snprintf(&buf[n], PAGE_SIZE - n,
"hierarchy = %d\n", p->hierarchy);
n += snprintf(&buf[n], PAGE_SIZE - n,
"constellation = %d\n", p->constellation);
n += snprintf(&buf[n], PAGE_SIZE - n,
"burst_size = %d\n", p->burst_size);
n += snprintf(&buf[n], PAGE_SIZE - n,
"burst_duration = %d\n", p->burst_duration);
n += snprintf(&buf[n], PAGE_SIZE - n,
"burst_cycle_time = %d\n", p->burst_cycle_time);
n += snprintf(&buf[n], PAGE_SIZE - n,
"calc_burst_cycle_time = %d\n",
p->calc_burst_cycle_time);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_rows = %d\n", p->num_of_rows);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_padd_cols = %d\n", p->num_of_padd_cols);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_punct_cols = %d\n", p->num_of_punct_cols);
n += snprintf(&buf[n], PAGE_SIZE - n,
"error_ts_packets = %d\n", p->error_ts_packets);
n += snprintf(&buf[n], PAGE_SIZE - n,
"total_ts_packets = %d\n", p->total_ts_packets);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_corrected_mpe_tlbs = %d\n", p->num_of_corrected_mpe_tlbs);
n += snprintf(&buf[n], PAGE_SIZE - n,
"ber_error_count = %d\n", p->ber_error_count);
n += snprintf(&buf[n], PAGE_SIZE - n,
"ber_bit_count = %d\n", p->ber_bit_count);
n += snprintf(&buf[n], PAGE_SIZE - n,
"sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
n += snprintf(&buf[n], PAGE_SIZE - n,
"pre_ber = %d\n", p->pre_ber);
n += snprintf(&buf[n], PAGE_SIZE - n,
"cell_id = %d\n", p->cell_id);
n += snprintf(&buf[n], PAGE_SIZE - n,
"dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
n += snprintf(&buf[n], PAGE_SIZE - n,
"dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_mpe_received = %d\n", p->num_mpe_received);
debug_data->stats_count = n;
spin_unlock(&debug_data->lock);
wake_up(&debug_data->stats_queue);
}
static void smsdvb_print_isdb_stats(struct smsdvb_debugfs *debug_data,
struct sms_isdbt_stats *p)
{
int i, n = 0;
char *buf;
spin_lock(&debug_data->lock);
if (debug_data->stats_count) {
spin_unlock(&debug_data->lock);
return;
}
buf = debug_data->stats_data;
n += snprintf(&buf[n], PAGE_SIZE - n,
"statistics_type = %d\t", p->statistics_type);
n += snprintf(&buf[n], PAGE_SIZE - n,
"full_size = %d\n", p->full_size);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_rf_locked = %d\t\t", p->is_rf_locked);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_demod_locked = %d\t", p->is_demod_locked);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_external_lna_on = %d\n", p->is_external_lna_on);
n += snprintf(&buf[n], PAGE_SIZE - n,
"SNR = %d dB\t\t", p->SNR);
n += snprintf(&buf[n], PAGE_SIZE - n,
"RSSI = %d dBm\t\t", p->RSSI);
n += snprintf(&buf[n], PAGE_SIZE - n,
"in_band_pwr = %d dBm\n", p->in_band_pwr);
n += snprintf(&buf[n], PAGE_SIZE - n,
"carrier_offset = %d\t", p->carrier_offset);
n += snprintf(&buf[n], PAGE_SIZE - n,
"bandwidth = %d\t\t", p->bandwidth);
n += snprintf(&buf[n], PAGE_SIZE - n,
"frequency = %d Hz\n", p->frequency);
n += snprintf(&buf[n], PAGE_SIZE - n,
"transmission_mode = %d\t", p->transmission_mode);
n += snprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\t\t", p->modem_state);
n += snprintf(&buf[n], PAGE_SIZE - n,
"guard_interval = %d\n", p->guard_interval);
n += snprintf(&buf[n], PAGE_SIZE - n,
"system_type = %d\t\t", p->system_type);
n += snprintf(&buf[n], PAGE_SIZE - n,
"partial_reception = %d\t", p->partial_reception);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_layers = %d\n", p->num_of_layers);
n += snprintf(&buf[n], PAGE_SIZE - n,
"sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
for (i = 0; i < 3; i++) {
if (p->layer_info[i].number_of_segments < 1 ||
p->layer_info[i].number_of_segments > 13)
continue;
n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
p->layer_info[i].code_rate);
n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
p->layer_info[i].constellation);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
p->layer_info[i].ber);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
p->layer_info[i].ber_error_count);
n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
p->layer_info[i].ber_bit_count);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
p->layer_info[i].pre_ber);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
p->layer_info[i].ts_per);
n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
p->layer_info[i].error_ts_packets);
n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
p->layer_info[i].total_ts_packets);
n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
p->layer_info[i].ti_ldepth_i);
n += snprintf(&buf[n], PAGE_SIZE - n,
"\tnumber_of_segments = %d\t",
p->layer_info[i].number_of_segments);
n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
p->layer_info[i].tmcc_errors);
}
debug_data->stats_count = n;
spin_unlock(&debug_data->lock);
wake_up(&debug_data->stats_queue);
}
static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs *debug_data,
struct sms_isdbt_stats_ex *p)
{
int i, n = 0;
char *buf;
spin_lock(&debug_data->lock);
if (debug_data->stats_count) {
spin_unlock(&debug_data->lock);
return;
}
buf = debug_data->stats_data;
n += snprintf(&buf[n], PAGE_SIZE - n,
"statistics_type = %d\t", p->statistics_type);
n += snprintf(&buf[n], PAGE_SIZE - n,
"full_size = %d\n", p->full_size);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_rf_locked = %d\t\t", p->is_rf_locked);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_demod_locked = %d\t", p->is_demod_locked);
n += snprintf(&buf[n], PAGE_SIZE - n,
"is_external_lna_on = %d\n", p->is_external_lna_on);
n += snprintf(&buf[n], PAGE_SIZE - n,
"SNR = %d dB\t\t", p->SNR);
n += snprintf(&buf[n], PAGE_SIZE - n,
"RSSI = %d dBm\t\t", p->RSSI);
n += snprintf(&buf[n], PAGE_SIZE - n,
"in_band_pwr = %d dBm\n", p->in_band_pwr);
n += snprintf(&buf[n], PAGE_SIZE - n,
"carrier_offset = %d\t", p->carrier_offset);
n += snprintf(&buf[n], PAGE_SIZE - n,
"bandwidth = %d\t\t", p->bandwidth);
n += snprintf(&buf[n], PAGE_SIZE - n,
"frequency = %d Hz\n", p->frequency);
n += snprintf(&buf[n], PAGE_SIZE - n,
"transmission_mode = %d\t", p->transmission_mode);
n += snprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\t\t", p->modem_state);
n += snprintf(&buf[n], PAGE_SIZE - n,
"guard_interval = %d\n", p->guard_interval);
n += snprintf(&buf[n], PAGE_SIZE - n,
"system_type = %d\t\t", p->system_type);
n += snprintf(&buf[n], PAGE_SIZE - n,
"partial_reception = %d\t", p->partial_reception);
n += snprintf(&buf[n], PAGE_SIZE - n,
"num_of_layers = %d\n", p->num_of_layers);
n += snprintf(&buf[n], PAGE_SIZE - n, "segment_number = %d\t",
p->segment_number);
n += snprintf(&buf[n], PAGE_SIZE - n, "tune_bw = %d\n",
p->tune_bw);
for (i = 0; i < 3; i++) {
if (p->layer_info[i].number_of_segments < 1 ||
p->layer_info[i].number_of_segments > 13)
continue;
n += snprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
p->layer_info[i].code_rate);
n += snprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
p->layer_info[i].constellation);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
p->layer_info[i].ber);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tber_error_count = %-5d\t",
p->layer_info[i].ber_error_count);
n += snprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
p->layer_info[i].ber_bit_count);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
p->layer_info[i].pre_ber);
n += snprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
p->layer_info[i].ts_per);
n += snprintf(&buf[n], PAGE_SIZE - n, "\terror_ts_packets = %-5d\t",
p->layer_info[i].error_ts_packets);
n += snprintf(&buf[n], PAGE_SIZE - n, "total_ts_packets = %-5d\t",
p->layer_info[i].total_ts_packets);
n += snprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
p->layer_info[i].ti_ldepth_i);
n += snprintf(&buf[n], PAGE_SIZE - n,
"\tnumber_of_segments = %d\t",
p->layer_info[i].number_of_segments);
n += snprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
p->layer_info[i].tmcc_errors);
}
debug_data->stats_count = n;
spin_unlock(&debug_data->lock);
wake_up(&debug_data->stats_queue);
}
static int smsdvb_stats_open(struct inode *inode, struct file *file)
{
struct smsdvb_client_t *client = inode->i_private;
struct smsdvb_debugfs *debug_data = client->debug_data;
kref_get(&debug_data->refcount);
spin_lock(&debug_data->lock);
debug_data->stats_count = 0;
debug_data->stats_was_read = false;
spin_unlock(&debug_data->lock);
file->private_data = debug_data;
return 0;
}
static void smsdvb_debugfs_data_release(struct kref *ref)
{
struct smsdvb_debugfs *debug_data;
debug_data = container_of(ref, struct smsdvb_debugfs, refcount);
kfree(debug_data);
}
static int smsdvb_stats_wait_read(struct smsdvb_debugfs *debug_data)
{
int rc = 1;
spin_lock(&debug_data->lock);
if (debug_data->stats_was_read)
goto exit;
rc = debug_data->stats_count;
exit:
spin_unlock(&debug_data->lock);
return rc;
}
static unsigned int smsdvb_stats_poll(struct file *file, poll_table *wait)
{
struct smsdvb_debugfs *debug_data = file->private_data;
int rc;
kref_get(&debug_data->refcount);
poll_wait(file, &debug_data->stats_queue, wait);
rc = smsdvb_stats_wait_read(debug_data);
if (rc > 0)
rc = POLLIN | POLLRDNORM;
kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
return rc;
}
static ssize_t smsdvb_stats_read(struct file *file, char __user *user_buf,
size_t nbytes, loff_t *ppos)
{
int rc = 0, len;
struct smsdvb_debugfs *debug_data = file->private_data;
kref_get(&debug_data->refcount);
if (file->f_flags & O_NONBLOCK) {
rc = smsdvb_stats_wait_read(debug_data);
if (!rc) {
rc = -EWOULDBLOCK;
goto ret;
}
} else {
rc = wait_event_interruptible(debug_data->stats_queue,
smsdvb_stats_wait_read(debug_data));
if (rc < 0)
goto ret;
}
if (debug_data->stats_was_read) {
rc = 0; /* EOF */
goto ret;
}
len = debug_data->stats_count - *ppos;
if (len >= 0)
rc = simple_read_from_buffer(user_buf, nbytes, ppos,
debug_data->stats_data, len);
else
rc = 0;
if (*ppos >= debug_data->stats_count) {
spin_lock(&debug_data->lock);
debug_data->stats_was_read = true;
spin_unlock(&debug_data->lock);
}
ret:
kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
return rc;
}
static int smsdvb_stats_release(struct inode *inode, struct file *file)
{
struct smsdvb_debugfs *debug_data = file->private_data;
spin_lock(&debug_data->lock);
debug_data->stats_was_read = true; /* return EOF to read() */
spin_unlock(&debug_data->lock);
wake_up_interruptible_sync(&debug_data->stats_queue);
kref_put(&debug_data->refcount, smsdvb_debugfs_data_release);
file->private_data = NULL;
return 0;
}
static const struct file_operations debugfs_stats_ops = {
.open = smsdvb_stats_open,
.poll = smsdvb_stats_poll,
.read = smsdvb_stats_read,
.release = smsdvb_stats_release,
.llseek = generic_file_llseek,
};
/*
* Functions used by smsdvb, in order to create the interfaces
*/
int smsdvb_debugfs_create(struct smsdvb_client_t *client)
{
struct smscore_device_t *coredev = client->coredev;
struct dentry *d;
struct smsdvb_debugfs *debug_data;
if (!smsdvb_debugfs_usb_root || !coredev->is_usb_device)
return -ENODEV;
client->debugfs = debugfs_create_dir(coredev->devpath,
smsdvb_debugfs_usb_root);
if (IS_ERR_OR_NULL(client->debugfs)) {
pr_info("Unable to create debugfs %s directory.\n",
coredev->devpath);
return -ENODEV;
}
d = debugfs_create_file("stats", S_IRUGO | S_IWUSR, client->debugfs,
client, &debugfs_stats_ops);
if (!d) {
debugfs_remove(client->debugfs);
return -ENOMEM;
}
debug_data = kzalloc(sizeof(*client->debug_data), GFP_KERNEL);
if (!debug_data)
return -ENOMEM;
client->debug_data = debug_data;
client->prt_dvb_stats = smsdvb_print_dvb_stats;
client->prt_isdb_stats = smsdvb_print_isdb_stats;
client->prt_isdb_stats_ex = smsdvb_print_isdb_stats_ex;
init_waitqueue_head(&debug_data->stats_queue);
spin_lock_init(&debug_data->lock);
kref_init(&debug_data->refcount);
return 0;
}
void smsdvb_debugfs_release(struct smsdvb_client_t *client)
{
if (!client->debugfs)
return;
client->prt_dvb_stats = NULL;
client->prt_isdb_stats = NULL;
client->prt_isdb_stats_ex = NULL;
debugfs_remove_recursive(client->debugfs);
kref_put(&client->debug_data->refcount, smsdvb_debugfs_data_release);
client->debug_data = NULL;
client->debugfs = NULL;
}
int smsdvb_debugfs_register(void)
{
struct dentry *d;
/*
* FIXME: This was written to debug Siano USB devices. So, it creates
* the debugfs node under <debugfs>/usb.
* A similar logic would be needed for Siano sdio devices, but, in that
* case, usb_debug_root is not a good choice.
*
* Perhaps the right fix here would be to create another sysfs root
* node for sdio-based boards, but this may need some logic at sdio
* subsystem.
*/
d = debugfs_create_dir("smsdvb", usb_debug_root);
if (IS_ERR_OR_NULL(d)) {
sms_err("Couldn't create sysfs node for smsdvb");
return PTR_ERR(d);
} else {
smsdvb_debugfs_usb_root = d;
}
return 0;
}
void smsdvb_debugfs_unregister(void)
{
debugfs_remove_recursive(smsdvb_debugfs_usb_root);
smsdvb_debugfs_usb_root = NULL;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,130 @@
/***********************************************************************
*
* 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, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
struct smsdvb_debugfs;
struct smsdvb_client_t;
typedef void (*sms_prt_dvb_stats_t)(struct smsdvb_debugfs *debug_data,
struct sms_stats *p);
typedef void (*sms_prt_isdb_stats_t)(struct smsdvb_debugfs *debug_data,
struct sms_isdbt_stats *p);
typedef void (*sms_prt_isdb_stats_ex_t)
(struct smsdvb_debugfs *debug_data,
struct sms_isdbt_stats_ex *p);
struct smsdvb_client_t {
struct list_head entry;
struct smscore_device_t *coredev;
struct smscore_client_t *smsclient;
struct dvb_adapter adapter;
struct dvb_demux demux;
struct dmxdev dmxdev;
struct dvb_frontend frontend;
fe_status_t fe_status;
struct completion tune_done;
struct completion stats_done;
int last_per;
int legacy_ber, legacy_per;
int event_fe_state;
int event_unc_state;
unsigned long get_stats_jiffies;
int feed_users;
bool has_tuned;
/* stats debugfs data */
struct dentry *debugfs;
struct smsdvb_debugfs *debug_data;
sms_prt_dvb_stats_t prt_dvb_stats;
sms_prt_isdb_stats_t prt_isdb_stats;
sms_prt_isdb_stats_ex_t prt_isdb_stats_ex;
};
/*
* This struct is a mix of struct sms_rx_stats_ex and
* struct sms_srvm_signal_status.
* It was obtained by comparing the way it was filled by the original code
*/
struct RECEPTION_STATISTICS_PER_SLICES_S {
u32 result;
u32 snr;
s32 in_band_power;
u32 ts_packets;
u32 ets_packets;
u32 constellation;
u32 hp_code;
u32 tps_srv_ind_lp;
u32 tps_srv_ind_hp;
u32 cell_id;
u32 reason;
u32 request_id;
u32 modem_state; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */
u32 ber; /* Post Viterbi BER [1E-5] */
s32 RSSI; /* dBm */
s32 carrier_offset; /* Carrier Offset in bin/1024 */
u32 is_rf_locked; /* 0 - not locked, 1 - locked */
u32 is_demod_locked; /* 0 - not locked, 1 - locked */
u32 ber_bit_count; /* Total number of SYNC bits. */
u32 ber_error_count; /* Number of erronous SYNC bits. */
s32 MRC_SNR; /* dB */
s32 mrc_in_band_pwr; /* In band power in dBM */
s32 MRC_RSSI; /* dBm */
};
/* From smsdvb-debugfs.c */
#ifdef CONFIG_SMS_SIANO_DEBUGFS
int smsdvb_debugfs_create(struct smsdvb_client_t *client);
void smsdvb_debugfs_release(struct smsdvb_client_t *client);
int smsdvb_debugfs_register(void);
void smsdvb_debugfs_unregister(void);
#else
static inline int smsdvb_debugfs_create(struct smsdvb_client_t *client)
{
return 0;
}
static inline void smsdvb_debugfs_release(struct smsdvb_client_t *client) {}
static inline int smsdvb_debugfs_register(void)
{
return 0;
};
static inline void smsdvb_debugfs_unregister(void) {};
#endif

View file

@ -28,23 +28,23 @@
void smsendian_handle_tx_message(void *buffer)
{
#ifdef __BIG_ENDIAN
struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
int i;
int msgWords;
int msg_words;
switch (msg->xMsgHeader.msgType) {
switch (msg->x_msg_header.msg_type) {
case MSG_SMS_DATA_DOWNLOAD_REQ:
{
msg->msgData[0] = le32_to_cpu(msg->msgData[0]);
msg->msg_data[0] = le32_to_cpu(msg->msg_data[0]);
break;
}
default:
msgWords = (msg->xMsgHeader.msgLength -
sizeof(struct SmsMsgHdr_ST))/4;
msg_words = (msg->x_msg_header.msg_length -
sizeof(struct sms_msg_hdr))/4;
for (i = 0; i < msgWords; i++)
msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
for (i = 0; i < msg_words; i++)
msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
break;
}
@ -55,16 +55,16 @@ EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
void smsendian_handle_rx_message(void *buffer)
{
#ifdef __BIG_ENDIAN
struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer;
struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
int i;
int msgWords;
int msg_words;
switch (msg->xMsgHeader.msgType) {
switch (msg->x_msg_header.msg_type) {
case MSG_SMS_GET_VERSION_EX_RES:
{
struct SmsVersionRes_ST *ver =
(struct SmsVersionRes_ST *) msg;
ver->ChipModel = le16_to_cpu(ver->ChipModel);
struct sms_version_res *ver =
(struct sms_version_res *) msg;
ver->chip_model = le16_to_cpu(ver->chip_model);
break;
}
@ -77,11 +77,11 @@ void smsendian_handle_rx_message(void *buffer)
default:
{
msgWords = (msg->xMsgHeader.msgLength -
sizeof(struct SmsMsgHdr_ST))/4;
msg_words = (msg->x_msg_header.msg_length -
sizeof(struct sms_msg_hdr))/4;
for (i = 0; i < msgWords; i++)
msg->msgData[i] = le32_to_cpu(msg->msgData[i]);
for (i = 0; i < msg_words; i++)
msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]);
break;
}
@ -93,11 +93,11 @@ EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
void smsendian_handle_message_header(void *msg)
{
#ifdef __BIG_ENDIAN
struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg;
struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)msg;
phdr->msgType = le16_to_cpu(phdr->msgType);
phdr->msgLength = le16_to_cpu(phdr->msgLength);
phdr->msgFlags = le16_to_cpu(phdr->msgFlags);
phdr->msg_type = le16_to_cpu(phdr->msg_type);
phdr->msg_length = le16_to_cpu(phdr->msg_length);
phdr->msg_flags = le16_to_cpu(phdr->msg_flags);
#endif /* __BIG_ENDIAN */
}
EXPORT_SYMBOL_GPL(smsendian_handle_message_header);

View file

@ -40,7 +40,6 @@ struct ir_t {
char phys[32];
char *rc_codes;
u64 protocol;
u32 timeout;
u32 controller;

View file

@ -83,45 +83,6 @@ enum dmx_success {
#define TS_DEMUX 8 /* in case TS_PACKET is set, send the TS to
the demux device, not to the dvr device */
/* PES type for filters which write to built-in decoder */
/* these should be kept identical to the types in dmx.h */
enum dmx_ts_pes
{ /* also send packets to decoder (if it exists) */
DMX_TS_PES_AUDIO0,
DMX_TS_PES_VIDEO0,
DMX_TS_PES_TELETEXT0,
DMX_TS_PES_SUBTITLE0,
DMX_TS_PES_PCR0,
DMX_TS_PES_AUDIO1,
DMX_TS_PES_VIDEO1,
DMX_TS_PES_TELETEXT1,
DMX_TS_PES_SUBTITLE1,
DMX_TS_PES_PCR1,
DMX_TS_PES_AUDIO2,
DMX_TS_PES_VIDEO2,
DMX_TS_PES_TELETEXT2,
DMX_TS_PES_SUBTITLE2,
DMX_TS_PES_PCR2,
DMX_TS_PES_AUDIO3,
DMX_TS_PES_VIDEO3,
DMX_TS_PES_TELETEXT3,
DMX_TS_PES_SUBTITLE3,
DMX_TS_PES_PCR3,
DMX_TS_PES_OTHER
};
#define DMX_TS_PES_AUDIO DMX_TS_PES_AUDIO0
#define DMX_TS_PES_VIDEO DMX_TS_PES_VIDEO0
#define DMX_TS_PES_TELETEXT DMX_TS_PES_TELETEXT0
#define DMX_TS_PES_SUBTITLE DMX_TS_PES_SUBTITLE0
#define DMX_TS_PES_PCR DMX_TS_PES_PCR0
struct dmx_ts_feed {
int is_filtering; /* Set to non-zero when filtering in progress */
struct dmx_demux *parent; /* Back-pointer */

View file

@ -569,7 +569,7 @@ static int dvb_dmxdev_start_feed(struct dmxdev *dmxdev,
dmx_output_t otype;
int ret;
int ts_type;
dmx_pes_type_t ts_pes;
enum dmx_ts_pes ts_pes;
struct dmx_ts_feed *tsfeed;
feed->ts = NULL;
@ -852,7 +852,8 @@ static int dvb_dmxdev_filter_set(struct dmxdev *dmxdev,
struct dmxdev_filter *dmxdevfilter,
struct dmx_sct_filter_params *params)
{
dprintk("function : %s\n", __func__);
dprintk("function : %s, PID=0x%04x, flags=%02x, timeout=%d\n",
__func__, params->pid, params->flags, params->timeout);
dvb_dmxdev_filter_stop(dmxdevfilter);

View file

@ -124,8 +124,7 @@
#define USB_PID_DIBCOM_STK7770P 0x1e80
#define USB_PID_DIBCOM_NIM7090 0x1bb2
#define USB_PID_DIBCOM_TFE7090PVR 0x1bb4
#define USB_PID_DIBCOM_TFE7090E 0x1bb7
#define USB_PID_DIBCOM_TFE7790E 0x1e6e
#define USB_PID_DIBCOM_TFE7790P 0x1e6e
#define USB_PID_DIBCOM_NIM9090M 0x2383
#define USB_PID_DIBCOM_NIM9090MD 0x2384
#define USB_PID_DPOSH_M9206_COLD 0x9206

View file

@ -440,20 +440,22 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
if (!dvb_demux_feed_err_pkts)
return;
} else /* if TEI bit is set, pid may be wrong- skip pkt counter */
if (demux->cnt_storage && dvb_demux_tscheck) {
/* check pkt counter */
if (pid < MAX_PID) {
if ((buf[3] & 0xf) != demux->cnt_storage[pid])
dprintk_tscheck("TS packet counter mismatch. "
"PID=0x%x expected 0x%x "
"got 0x%x\n",
if (demux->cnt_storage && dvb_demux_tscheck) {
/* check pkt counter */
if (pid < MAX_PID) {
if (buf[3] & 0x10)
demux->cnt_storage[pid] =
(demux->cnt_storage[pid] + 1) & 0xf;
if ((buf[3] & 0xf) != demux->cnt_storage[pid]) {
dprintk_tscheck("TS packet counter mismatch. PID=0x%x expected 0x%x got 0x%x\n",
pid, demux->cnt_storage[pid],
buf[3] & 0xf);
demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
demux->cnt_storage[pid] = buf[3] & 0xf;
}
}
/* end check */
}
/* end check */
}
list_for_each_entry(feed, &demux->feed_list, list_head) {
if ((feed->pid != pid) && (feed->pid != 0x2000))
@ -672,7 +674,7 @@ static int dmx_ts_feed_set(struct dmx_ts_feed *ts_feed, u16 pid, int ts_type,
return -ERESTARTSYS;
if (ts_type & TS_DECODER) {
if (pes_type >= DMX_TS_PES_OTHER) {
if (pes_type >= DMX_PES_OTHER) {
mutex_unlock(&demux->mutex);
return -EINVAL;
}
@ -844,7 +846,7 @@ static int dvbdmx_release_ts_feed(struct dmx_demux *dmx,
feed->pid = 0xffff;
if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_TS_PES_OTHER)
if (feed->ts_type & TS_DECODER && feed->pes_type < DMX_PES_OTHER)
demux->pesfilter[feed->pes_type] = NULL;
mutex_unlock(&demux->mutex);
@ -1266,7 +1268,7 @@ int dvb_dmx_init(struct dvb_demux *dvbdemux)
INIT_LIST_HEAD(&dvbdemux->frontend_list);
for (i = 0; i < DMX_TS_PES_OTHER; i++) {
for (i = 0; i < DMX_PES_OTHER; i++) {
dvbdemux->pesfilter[i] = NULL;
dvbdemux->pids[i] = 0xffff;
}

View file

@ -119,8 +119,8 @@ struct dvb_demux {
struct list_head frontend_list;
struct dvb_demux_feed *pesfilter[DMX_TS_PES_OTHER];
u16 pids[DMX_TS_PES_OTHER];
struct dvb_demux_feed *pesfilter[DMX_PES_OTHER];
u16 pids[DMX_PES_OTHER];
int playing;
int recording;

View file

@ -920,7 +920,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
u32 delsys;
delsys = c->delivery_system;
memset(c, 0, sizeof(struct dtv_frontend_properties));
memset(c, 0, offsetof(struct dtv_frontend_properties, strength));
c->delivery_system = delsys;
c->state = DTV_CLEAR;
@ -1509,9 +1509,74 @@ static bool is_dvbv3_delsys(u32 delsys)
return status;
}
static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
/**
* emulate_delivery_system - emulate a DVBv5 delivery system with a DVBv3 type
* @fe: struct frontend;
* @delsys: DVBv5 type that will be used for emulation
*
* Provides emulation for delivery systems that are compatible with the old
* DVBv3 call. Among its usages, it provices support for ISDB-T, and allows
* using a DVB-S2 only frontend just like it were a DVB-S, if the frontent
* parameters are compatible with DVB-S spec.
*/
static int emulate_delivery_system(struct dvb_frontend *fe, u32 delsys)
{
int ncaps, i;
int i;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
c->delivery_system = delsys;
/*
* If the call is for ISDB-T, put it into full-seg, auto mode, TV
*/
if (c->delivery_system == SYS_ISDBT) {
dev_dbg(fe->dvb->device,
"%s: Using defaults for SYS_ISDBT\n",
__func__);
if (!c->bandwidth_hz)
c->bandwidth_hz = 6000000;
c->isdbt_partial_reception = 0;
c->isdbt_sb_mode = 0;
c->isdbt_sb_subchannel = 0;
c->isdbt_sb_segment_idx = 0;
c->isdbt_sb_segment_count = 0;
c->isdbt_layer_enabled = 7;
for (i = 0; i < 3; i++) {
c->layer[i].fec = FEC_AUTO;
c->layer[i].modulation = QAM_AUTO;
c->layer[i].interleaving = 0;
c->layer[i].segment_count = 0;
}
}
dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
__func__, c->delivery_system);
return 0;
}
/**
* dvbv5_set_delivery_system - Sets the delivery system for a DVBv5 API call
* @fe: frontend struct
* @desired_system: delivery system requested by the user
*
* A DVBv5 call know what's the desired system it wants. So, set it.
*
* There are, however, a few known issues with early DVBv5 applications that
* are also handled by this logic:
*
* 1) Some early apps use SYS_UNDEFINED as the desired delivery system.
* This is an API violation, but, as we don't want to break userspace,
* convert it to the first supported delivery system.
* 2) Some apps might be using a DVBv5 call in a wrong way, passing, for
* example, SYS_DVBT instead of SYS_ISDBT. This is because early usage of
* ISDB-T provided backward compat with DVB-T.
*/
static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
u32 desired_system)
{
int ncaps;
u32 delsys = SYS_UNDEFINED;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
enum dvbv3_emulation_type type;
@ -1522,166 +1587,136 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
* assume that the application wants to use the first supported
* delivery system.
*/
if (c->delivery_system == SYS_UNDEFINED)
c->delivery_system = fe->ops.delsys[0];
if (desired_system == SYS_UNDEFINED)
desired_system = fe->ops.delsys[0];
if (desired_system == SYS_UNDEFINED) {
/*
* A DVBv3 call doesn't know what's the desired system.
* Also, DVBv3 applications don't know that ops.info->type
* could be changed, and they simply dies when it doesn't
* match.
* So, don't change the current delivery system, as it
* may be trying to do the wrong thing, like setting an
* ISDB-T frontend as DVB-T. Instead, find the closest
* DVBv3 system that matches the delivery system.
*/
if (is_dvbv3_delsys(c->delivery_system)) {
/*
* This is a DVBv5 call. So, it likely knows the supported
* delivery systems. So, check if the desired delivery system is
* supported
*/
ncaps = 0;
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
if (fe->ops.delsys[ncaps] == desired_system) {
c->delivery_system = desired_system;
dev_dbg(fe->dvb->device,
"%s: Using delivery system to %d\n",
__func__, c->delivery_system);
"%s: Changing delivery system to %d\n",
__func__, desired_system);
return 0;
}
type = dvbv3_type(c->delivery_system);
switch (type) {
case DVBV3_QPSK:
desired_system = SYS_DVBS;
break;
case DVBV3_QAM:
desired_system = SYS_DVBC_ANNEX_A;
break;
case DVBV3_ATSC:
desired_system = SYS_ATSC;
break;
case DVBV3_OFDM:
desired_system = SYS_DVBT;
break;
default:
dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
__func__);
return -EINVAL;
}
/*
* Get a delivery system that is compatible with DVBv3
* NOTE: in order for this to work with softwares like Kaffeine that
* uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
* DVB-S, drivers that support both should put the SYS_DVBS entry
* before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
* The real fix is that userspace applications should not use DVBv3
* and not trust on calling FE_SET_FRONTEND to switch the delivery
* system.
*/
ncaps = 0;
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
if (fe->ops.delsys[ncaps] == desired_system) {
delsys = desired_system;
break;
}
ncaps++;
}
if (delsys == SYS_UNDEFINED) {
dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
__func__, desired_system);
}
} else {
/*
* This is a DVBv5 call. So, it likely knows the supported
* delivery systems.
*/
/* Check if the desired delivery system is supported */
ncaps = 0;
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
if (fe->ops.delsys[ncaps] == desired_system) {
c->delivery_system = desired_system;
dev_dbg(fe->dvb->device,
"%s: Changing delivery system to %d\n",
__func__, desired_system);
return 0;
}
ncaps++;
}
type = dvbv3_type(desired_system);
/*
* The delivery system is not supported. See if it can be
* emulated.
* The emulation only works if the desired system is one of the
* DVBv3 delivery systems
*/
if (!is_dvbv3_delsys(desired_system)) {
dev_dbg(fe->dvb->device,
"%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
__func__);
return -EINVAL;
}
/*
* Get the last non-DVBv3 delivery system that has the same type
* of the desired system
*/
ncaps = 0;
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
!is_dvbv3_delsys(fe->ops.delsys[ncaps]))
delsys = fe->ops.delsys[ncaps];
ncaps++;
}
/* There's nothing compatible with the desired delivery system */
if (delsys == SYS_UNDEFINED) {
dev_dbg(fe->dvb->device,
"%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
__func__);
return -EINVAL;
}
ncaps++;
}
c->delivery_system = delsys;
/*
* The DVBv3 or DVBv5 call is requesting a different system. So,
* emulation is needed.
* The requested delivery system isn't supported. Maybe userspace
* is requesting a DVBv3 compatible delivery system.
*
* Emulate newer delivery systems like ISDBT, DVBT and DTMB
* for older DVBv5 applications. The emulation will try to use
* the auto mode for most things, and will assume that the desired
* delivery system is the last one at the ops.delsys[] array
* The emulation only works if the desired system is one of the
* delivery systems supported by DVBv3 API
*/
dev_dbg(fe->dvb->device,
"%s: Using delivery system %d emulated as if it were a %d\n",
__func__, delsys, desired_system);
if (!is_dvbv3_delsys(desired_system)) {
dev_dbg(fe->dvb->device,
"%s: Delivery system %d not supported.\n",
__func__, desired_system);
return -EINVAL;
}
type = dvbv3_type(desired_system);
/*
* For now, handles ISDB-T calls. More code may be needed here for the
* other emulated stuff
*/
if (type == DVBV3_OFDM) {
if (c->delivery_system == SYS_ISDBT) {
dev_dbg(fe->dvb->device,
"%s: Using defaults for SYS_ISDBT\n",
__func__);
if (!c->bandwidth_hz)
c->bandwidth_hz = 6000000;
c->isdbt_partial_reception = 0;
c->isdbt_sb_mode = 0;
c->isdbt_sb_subchannel = 0;
c->isdbt_sb_segment_idx = 0;
c->isdbt_sb_segment_count = 0;
c->isdbt_layer_enabled = 0;
for (i = 0; i < 3; i++) {
c->layer[i].fec = FEC_AUTO;
c->layer[i].modulation = QAM_AUTO;
c->layer[i].interleaving = 0;
c->layer[i].segment_count = 0;
}
}
* Get the last non-DVBv3 delivery system that has the same type
* of the desired system
*/
ncaps = 0;
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
if (dvbv3_type(fe->ops.delsys[ncaps]) == type)
delsys = fe->ops.delsys[ncaps];
ncaps++;
}
dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
__func__, c->delivery_system);
return 0;
/* There's nothing compatible with the desired delivery system */
if (delsys == SYS_UNDEFINED) {
dev_dbg(fe->dvb->device,
"%s: Delivery system %d not supported on emulation mode.\n",
__func__, desired_system);
return -EINVAL;
}
dev_dbg(fe->dvb->device,
"%s: Using delivery system %d emulated as if it were %d\n",
__func__, delsys, desired_system);
return emulate_delivery_system(fe, desired_system);
}
/**
* dvbv3_set_delivery_system - Sets the delivery system for a DVBv3 API call
* @fe: frontend struct
*
* A DVBv3 call doesn't know what's the desired system it wants. It also
* doesn't allow to switch between different types. Due to that, userspace
* should use DVBv5 instead.
* However, in order to avoid breaking userspace API, limited backward
* compatibility support is provided.
*
* There are some delivery systems that are incompatible with DVBv3 calls.
*
* This routine should work fine for frontends that support just one delivery
* system.
*
* For frontends that support multiple frontends:
* 1) It defaults to use the first supported delivery system. There's an
* userspace application that allows changing it at runtime;
*
* 2) If the current delivery system is not compatible with DVBv3, it gets
* the first one that it is compatible.
*
* NOTE: in order for this to work with applications like Kaffeine that
* uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
* DVB-S, drivers that support both DVB-S and DVB-S2 should have the
* SYS_DVBS entry before the SYS_DVBS2, otherwise it won't switch back
* to DVB-S.
*/
static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
{
int ncaps;
u32 delsys = SYS_UNDEFINED;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
/* If not set yet, defaults to the first supported delivery system */
if (c->delivery_system == SYS_UNDEFINED)
c->delivery_system = fe->ops.delsys[0];
/*
* Trivial case: just use the current one, if it already a DVBv3
* delivery system
*/
if (is_dvbv3_delsys(c->delivery_system)) {
dev_dbg(fe->dvb->device,
"%s: Using delivery system to %d\n",
__func__, c->delivery_system);
return 0;
}
/*
* Seek for the first delivery system that it is compatible with a
* DVBv3 standard
*/
ncaps = 0;
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
if (dvbv3_type(fe->ops.delsys[ncaps]) != DVBV3_UNKNOWN) {
delsys = fe->ops.delsys[ncaps];
break;
}
ncaps++;
}
if (delsys == SYS_UNDEFINED) {
dev_dbg(fe->dvb->device,
"%s: Couldn't find a delivery system that works with FE_SET_FRONTEND\n",
__func__);
return -EINVAL;
}
return emulate_delivery_system(fe, delsys);
}
static int dtv_property_process_set(struct dvb_frontend *fe,
@ -1742,7 +1777,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
c->rolloff = tvp->u.data;
break;
case DTV_DELIVERY_SYSTEM:
r = set_delivery_system(fe, tvp->u.data);
r = dvbv5_set_delivery_system(fe, tvp->u.data);
break;
case DTV_VOLTAGE:
c->voltage = tvp->u.data;
@ -2335,7 +2370,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
break;
case FE_SET_FRONTEND:
err = set_delivery_system(fe, SYS_UNDEFINED);
err = dvbv3_set_delivery_system(fe);
if (err)
break;
@ -2594,7 +2629,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
* first supported delivery system (ops->delsys[0])
*/
fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
dvb_frontend_clear_cache(fe);
mutex_unlock(&frontend_mutex);

View file

@ -245,8 +245,8 @@ struct analog_demod_ops {
void (*set_params)(struct dvb_frontend *fe,
struct analog_parameters *params);
int (*has_signal)(struct dvb_frontend *fe);
int (*get_afc)(struct dvb_frontend *fe);
int (*has_signal)(struct dvb_frontend *fe, u16 *signal);
int (*get_afc)(struct dvb_frontend *fe, s32 *afc);
void (*tuner_status)(struct dvb_frontend *fe);
void (*standby)(struct dvb_frontend *fe);
void (*release)(struct dvb_frontend *fe);

View file

@ -1044,7 +1044,7 @@ static int dvb_net_feed_start(struct net_device *dev)
ret = priv->tsfeed->set(priv->tsfeed,
priv->pid, /* pid */
TS_PACKET, /* type */
DMX_TS_PES_OTHER, /* pes type */
DMX_PES_OTHER, /* pes type */
32768, /* circular buffer size */
timeout /* timeout */
);

View file

@ -210,7 +210,7 @@ config DVB_SI21XX
config DVB_TS2020
tristate "Montage Tehnology TS2020 based tuners"
depends on DVB_CORE && I2C
default m if DVB_FE_CUSTOMISE
default m if !MEDIA_SUBDRV_AUTOSELECT
help
A DVB-S/S2 silicon tuner. Say Y when you want to support this tuner.

View file

@ -21,12 +21,13 @@
#ifndef A8293_H
#define A8293_H
#include <linux/kconfig.h>
struct a8293_config {
u8 i2c_addr;
};
#if defined(CONFIG_DVB_A8293) || \
(defined(CONFIG_DVB_A8293_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_A8293)
extern struct dvb_frontend *a8293_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, const struct a8293_config *cfg);
#else

View file

@ -25,6 +25,7 @@
#ifndef AF9013_H
#define AF9013_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
/* AF9013/5 GPIOs (mostly guessed)
@ -102,8 +103,7 @@ struct af9013_config {
u8 gpio[4];
};
#if defined(CONFIG_DVB_AF9013) || \
(defined(CONFIG_DVB_AF9013_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_AF9013)
extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -156,6 +156,37 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
return 0;
}
/* write reg val table using reg addr auto increment */
static int af9033_wr_reg_val_tab(struct af9033_state *state,
const struct reg_val *tab, int tab_len)
{
int ret, i, j;
u8 buf[tab_len];
dev_dbg(&state->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
for (i = 0, j = 0; i < tab_len; i++) {
buf[j] = tab[i].val;
if (i == tab_len - 1 || tab[i].reg != tab[i + 1].reg - 1) {
ret = af9033_wr_regs(state, tab[i].reg - j, buf, j + 1);
if (ret < 0)
goto err;
j = 0;
} else {
j++;
}
}
return 0;
err:
dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x)
{
u32 r = 0, c = 0, i;
@ -223,6 +254,7 @@ static int af9033_init(struct dvb_frontend *fe)
{ 0x80f986, state->ts_mode_parallel, 0x01 },
{ 0x00d827, 0x00, 0xff },
{ 0x00d829, 0x00, 0xff },
{ 0x800045, state->cfg.adc_multiplier, 0xff },
};
/* program clock control */
@ -286,14 +318,29 @@ static int af9033_init(struct dvb_frontend *fe)
/* load OFSM settings */
dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
len = ARRAY_SIZE(ofsm_init);
init = ofsm_init;
for (i = 0; i < len; i++) {
ret = af9033_wr_reg(state, init[i].reg, init[i].val);
if (ret < 0)
goto err;
switch (state->cfg.tuner) {
case AF9033_TUNER_IT9135_38:
case AF9033_TUNER_IT9135_51:
case AF9033_TUNER_IT9135_52:
len = ARRAY_SIZE(ofsm_init_it9135_v1);
init = ofsm_init_it9135_v1;
break;
case AF9033_TUNER_IT9135_60:
case AF9033_TUNER_IT9135_61:
case AF9033_TUNER_IT9135_62:
len = ARRAY_SIZE(ofsm_init_it9135_v2);
init = ofsm_init_it9135_v2;
break;
default:
len = ARRAY_SIZE(ofsm_init);
init = ofsm_init;
break;
}
ret = af9033_wr_reg_val_tab(state, init, len);
if (ret < 0)
goto err;
/* load tuner specific settings */
dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
__func__);
@ -322,6 +369,30 @@ static int af9033_init(struct dvb_frontend *fe)
len = ARRAY_SIZE(tuner_init_fc0012);
init = tuner_init_fc0012;
break;
case AF9033_TUNER_IT9135_38:
len = ARRAY_SIZE(tuner_init_it9135_38);
init = tuner_init_it9135_38;
break;
case AF9033_TUNER_IT9135_51:
len = ARRAY_SIZE(tuner_init_it9135_51);
init = tuner_init_it9135_51;
break;
case AF9033_TUNER_IT9135_52:
len = ARRAY_SIZE(tuner_init_it9135_52);
init = tuner_init_it9135_52;
break;
case AF9033_TUNER_IT9135_60:
len = ARRAY_SIZE(tuner_init_it9135_60);
init = tuner_init_it9135_60;
break;
case AF9033_TUNER_IT9135_61:
len = ARRAY_SIZE(tuner_init_it9135_61);
init = tuner_init_it9135_61;
break;
case AF9033_TUNER_IT9135_62:
len = ARRAY_SIZE(tuner_init_it9135_62);
init = tuner_init_it9135_62;
break;
default:
dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n",
__func__, state->cfg.tuner);
@ -329,11 +400,9 @@ static int af9033_init(struct dvb_frontend *fe)
goto err;
}
for (i = 0; i < len; i++) {
ret = af9033_wr_reg(state, init[i].reg, init[i].val);
if (ret < 0)
goto err;
}
ret = af9033_wr_reg_val_tab(state, init, len);
if (ret < 0)
goto err;
if (state->cfg.ts_mode == AF9033_TS_MODE_SERIAL) {
ret = af9033_wr_reg_mask(state, 0x00d91c, 0x01, 0x01);
@ -349,6 +418,15 @@ static int af9033_init(struct dvb_frontend *fe)
goto err;
}
switch (state->cfg.tuner) {
case AF9033_TUNER_IT9135_60:
case AF9033_TUNER_IT9135_61:
case AF9033_TUNER_IT9135_62:
ret = af9033_wr_reg(state, 0x800000, 0x01);
if (ret < 0)
goto err;
}
state->bandwidth_hz = 0; /* force to program all parameters */
return 0;
@ -415,7 +493,8 @@ err:
static int af9033_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *fesettings)
{
fesettings->min_delay_ms = 800;
/* 800 => 2000 because IT9135 v2 is slow to gain lock */
fesettings->min_delay_ms = 2000;
fesettings->step_size = 0;
fesettings->max_drift = 0;
@ -498,17 +577,17 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
if (spec_inv == -1)
freq_cw = 0x800000 - freq_cw;
/* get adc multiplies */
ret = af9033_rd_reg(state, 0x800045, &tmp);
if (ret < 0)
goto err;
if (tmp == 1)
if (state->cfg.adc_multiplier == AF9033_ADC_MULTIPLIER_2X)
freq_cw /= 2;
buf[0] = (freq_cw >> 0) & 0xff;
buf[1] = (freq_cw >> 8) & 0xff;
buf[2] = (freq_cw >> 16) & 0x7f;
/* FIXME: there seems to be calculation error here... */
if (if_frequency == 0)
buf[2] = 0;
ret = af9033_wr_regs(state, 0x800029, buf, 3);
if (ret < 0)
goto err;
@ -934,13 +1013,24 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config,
buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
/* sleep */
ret = af9033_wr_reg(state, 0x80004c, 1);
if (ret < 0)
goto err;
switch (state->cfg.tuner) {
case AF9033_TUNER_IT9135_38:
case AF9033_TUNER_IT9135_51:
case AF9033_TUNER_IT9135_52:
case AF9033_TUNER_IT9135_60:
case AF9033_TUNER_IT9135_61:
case AF9033_TUNER_IT9135_62:
/* IT9135 did not like to sleep at that early */
break;
default:
ret = af9033_wr_reg(state, 0x80004c, 1);
if (ret < 0)
goto err;
ret = af9033_wr_reg(state, 0x800000, 0);
if (ret < 0)
goto err;
ret = af9033_wr_reg(state, 0x800000, 0);
if (ret < 0)
goto err;
}
/* configure internal TS mode */
switch (state->cfg.ts_mode) {

View file

@ -22,6 +22,8 @@
#ifndef AF9033_H
#define AF9033_H
#include <linux/kconfig.h>
struct af9033_config {
/*
* I2C address
@ -35,6 +37,13 @@ struct af9033_config {
*/
u32 clock;
/*
* ADC multiplier
*/
#define AF9033_ADC_MULTIPLIER_1X 0
#define AF9033_ADC_MULTIPLIER_2X 1
u8 adc_multiplier;
/*
* tuner
*/
@ -44,6 +53,14 @@ struct af9033_config {
#define AF9033_TUNER_MXL5007T 0xa0 /* MaxLinear MxL5007T */
#define AF9033_TUNER_TDA18218 0xa1 /* NXP TDA 18218HN */
#define AF9033_TUNER_FC2580 0x32 /* FCI FC2580 */
/* 50-5f Omega */
#define AF9033_TUNER_IT9135_38 0x38 /* Omega */
#define AF9033_TUNER_IT9135_51 0x51 /* Omega LNA config 1 */
#define AF9033_TUNER_IT9135_52 0x52 /* Omega LNA config 2 */
/* 60-6f Omega v2 */
#define AF9033_TUNER_IT9135_60 0x60 /* Omega v2 */
#define AF9033_TUNER_IT9135_61 0x61 /* Omega v2 LNA config 1 */
#define AF9033_TUNER_IT9135_62 0x62 /* Omega v2 LNA config 2 */
u8 tuner;
/*
@ -61,8 +78,7 @@ struct af9033_config {
};
#if defined(CONFIG_DVB_AF9033) || \
(defined(CONFIG_DVB_AF9033_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_AF9033)
extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
struct i2c_adapter *i2c);
#else

File diff suppressed because it is too large Load diff

View file

@ -22,6 +22,7 @@
#ifndef __ATBM8830_H__
#define __ATBM8830_H__
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
@ -60,8 +61,7 @@ struct atbm8830_config {
u8 agc_hold_loop;
};
#if defined(CONFIG_DVB_ATBM8830) || \
(defined(CONFIG_DVB_ATBM8830_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_ATBM8830)
extern struct dvb_frontend *atbm8830_attach(const struct atbm8830_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -22,6 +22,7 @@
#ifndef __AU8522_H__
#define __AU8522_H__
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
enum au8522_if_freq {
@ -60,8 +61,7 @@ struct au8522_config {
enum au8522_if_freq qam_if;
};
#if defined(CONFIG_DVB_AU8522) || \
(defined(CONFIG_DVB_AU8522_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_AU8522_DTV)
extern struct dvb_frontend *au8522_attach(const struct au8522_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -229,15 +229,11 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
/* Provide reasonable defaults for picture tuning values */
au8522_writereg(state, AU8522_TVDEC_SHARPNESSREG009H, 0x07);
au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH, 0xed);
state->brightness = 0xed - 128;
au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH, 0x79);
state->contrast = 0x79;
au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH, 0x80);
au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH, 0x80);
state->saturation = 0x80;
au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH, 0x00);
au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH, 0x00);
state->hue = 0x00;
/* Other decoder registers */
au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
@ -489,75 +485,32 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
/* ----------------------------------------------------------------------- */
static int au8522_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
static int au8522_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct au8522_state *state = to_state(sd);
struct au8522_state *state =
container_of(ctrl->handler, struct au8522_state, hdl);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
state->brightness = ctrl->value;
au8522_writereg(state, AU8522_TVDEC_BRIGHTNESS_REG00AH,
ctrl->value - 128);
ctrl->val - 128);
break;
case V4L2_CID_CONTRAST:
state->contrast = ctrl->value;
au8522_writereg(state, AU8522_TVDEC_CONTRAST_REG00BH,
ctrl->value);
ctrl->val);
break;
case V4L2_CID_SATURATION:
state->saturation = ctrl->value;
au8522_writereg(state, AU8522_TVDEC_SATURATION_CB_REG00CH,
ctrl->value);
ctrl->val);
au8522_writereg(state, AU8522_TVDEC_SATURATION_CR_REG00DH,
ctrl->value);
ctrl->val);
break;
case V4L2_CID_HUE:
state->hue = ctrl->value;
au8522_writereg(state, AU8522_TVDEC_HUE_H_REG00EH,
ctrl->value >> 8);
ctrl->val >> 8);
au8522_writereg(state, AU8522_TVDEC_HUE_L_REG00FH,
ctrl->value & 0xFF);
ctrl->val & 0xFF);
break;
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_MUTE:
/* Not yet implemented */
default:
return -EINVAL;
}
return 0;
}
static int au8522_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
struct au8522_state *state = to_state(sd);
/* Note that we are using values cached in the state structure instead
of reading the registers due to issues with i2c reads not working
properly/consistently yet on the HVR-950q */
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = state->brightness;
break;
case V4L2_CID_CONTRAST:
ctrl->value = state->contrast;
break;
case V4L2_CID_SATURATION:
ctrl->value = state->saturation;
break;
case V4L2_CID_HUE:
ctrl->value = state->hue;
break;
case V4L2_CID_AUDIO_VOLUME:
case V4L2_CID_AUDIO_BASS:
case V4L2_CID_AUDIO_TREBLE:
case V4L2_CID_AUDIO_BALANCE:
case V4L2_CID_AUDIO_MUTE:
/* Not yet supported */
default:
return -EINVAL;
}
@ -583,7 +536,7 @@ static int au8522_g_register(struct v4l2_subdev *sd,
}
static int au8522_s_register(struct v4l2_subdev *sd,
struct v4l2_dbg_register *reg)
const struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct au8522_state *state = to_state(sd);
@ -616,26 +569,6 @@ static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
return 0;
}
static int au8522_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
switch (qc->id) {
case V4L2_CID_CONTRAST:
return v4l2_ctrl_query_fill(qc, 0, 255, 1,
AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
case V4L2_CID_BRIGHTNESS:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 109);
case V4L2_CID_SATURATION:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
case V4L2_CID_HUE:
return v4l2_ctrl_query_fill(qc, -32768, 32768, 1, 0);
default:
break;
}
qc->type = 0;
return -EINVAL;
}
static int au8522_reset(struct v4l2_subdev *sd, u32 val)
{
struct au8522_state *state = to_state(sd);
@ -712,20 +645,11 @@ static int au8522_g_chip_ident(struct v4l2_subdev *sd,
return v4l2_chip_ident_i2c_client(client, chip, state->id, state->rev);
}
static int au8522_log_status(struct v4l2_subdev *sd)
{
/* FIXME: Add some status info here */
return 0;
}
/* ----------------------------------------------------------------------- */
static const struct v4l2_subdev_core_ops au8522_core_ops = {
.log_status = au8522_log_status,
.log_status = v4l2_ctrl_subdev_log_status,
.g_chip_ident = au8522_g_chip_ident,
.g_ctrl = au8522_g_ctrl,
.s_ctrl = au8522_s_ctrl,
.queryctrl = au8522_queryctrl,
.reset = au8522_reset,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = au8522_g_register,
@ -753,12 +677,17 @@ static const struct v4l2_subdev_ops au8522_ops = {
.video = &au8522_video_ops,
};
static const struct v4l2_ctrl_ops au8522_ctrl_ops = {
.s_ctrl = au8522_s_ctrl,
};
/* ----------------------------------------------------------------------- */
static int au8522_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct au8522_state *state;
struct v4l2_ctrl_handler *hdl;
struct v4l2_subdev *sd;
int instance;
struct au8522_config *demod_config;
@ -799,6 +728,27 @@ static int au8522_probe(struct i2c_client *client,
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &au8522_ops);
hdl = &state->hdl;
v4l2_ctrl_handler_init(hdl, 4);
v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 109);
v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
V4L2_CID_CONTRAST, 0, 255, 1,
AU8522_TVDEC_CONTRAST_REG00BH_CVBS);
v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
V4L2_CID_SATURATION, 0, 255, 1, 128);
v4l2_ctrl_new_std(hdl, &au8522_ctrl_ops,
V4L2_CID_HUE, -32768, 32767, 1, 0);
sd->ctrl_handler = hdl;
if (hdl->error) {
int err = hdl->error;
v4l2_ctrl_handler_free(hdl);
kfree(demod_config);
kfree(state);
return err;
}
state->c = client;
state->vid_input = AU8522_COMPOSITE_CH1;
state->aud_input = AU8522_AUDIO_NONE;
@ -815,6 +765,7 @@ static int au8522_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler);
au8522_release_state(to_state(sd));
return 0;
}

View file

@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/videodev2.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
#include "au8522.h"
@ -65,10 +66,7 @@ struct au8522_state {
int aud_input;
u32 id;
u32 rev;
u8 brightness;
u8 contrast;
u8 saturation;
s16 hue;
struct v4l2_ctrl_handler hdl;
};
/* These are routines shared by both the VSB/QAM demodulator and the analog

View file

@ -28,6 +28,7 @@
#ifndef CX22702_H
#define CX22702_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct cx22702_config {
@ -40,8 +41,7 @@ struct cx22702_config {
u8 output_mode;
};
#if defined(CONFIG_DVB_CX22702) || (defined(CONFIG_DVB_CX22702_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_CX22702)
extern struct dvb_frontend *cx22702_attach(
const struct cx22702_config *config,
struct i2c_adapter *i2c);

View file

@ -22,6 +22,8 @@
#ifndef CX24113_H
#define CX24113_H
#include <linux/kconfig.h>
struct dvb_frontend;
struct cx24113_config {
@ -30,8 +32,7 @@ struct cx24113_config {
u32 xtal_khz;
};
#if defined(CONFIG_DVB_TUNER_CX24113) || \
(defined(CONFIG_DVB_TUNER_CX24113_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_TUNER_CX24113)
extern struct dvb_frontend *cx24113_attach(struct dvb_frontend *,
const struct cx24113_config *config, struct i2c_adapter *i2c);

View file

@ -21,6 +21,7 @@
#ifndef CX24116_H
#define CX24116_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct cx24116_config {
@ -40,8 +41,7 @@ struct cx24116_config {
u16 i2c_wr_max;
};
#if defined(CONFIG_DVB_CX24116) || \
(defined(CONFIG_DVB_CX24116_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_CX24116)
extern struct dvb_frontend *cx24116_attach(
const struct cx24116_config *config,
struct i2c_adapter *i2c);

View file

@ -26,6 +26,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/div64.h>
#include "dvb_frontend.h"
#include "cx24123.h"
@ -452,7 +453,8 @@ static u32 cx24123_int_log2(u32 a, u32 b)
static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
{
u32 tmp, sample_rate, ratio, sample_gain;
u64 tmp;
u32 sample_rate, ratio, sample_gain;
u8 pll_mult;
/* check if symbol rate is within limits */
@ -482,27 +484,11 @@ static int cx24123_set_symbolrate(struct cx24123_state *state, u32 srate)
sample_rate = pll_mult * XTAL;
/*
SYSSymbolRate[21:0] = (srate << 23) / sample_rate
We have to use 32 bit unsigned arithmetic without precision loss.
The maximum srate is 45000000 or 0x02AEA540. This number has
only 6 clear bits on top, hence we can shift it left only 6 bits
at a time. Borrowed from cx24110.c
*/
tmp = srate << 6;
ratio = tmp / sample_rate;
tmp = (tmp % sample_rate) << 6;
ratio = (ratio << 6) + (tmp / sample_rate);
tmp = (tmp % sample_rate) << 6;
ratio = (ratio << 6) + (tmp / sample_rate);
tmp = (tmp % sample_rate) << 5;
ratio = (ratio << 5) + (tmp / sample_rate);
/* SYSSymbolRate[21:0] = (srate << 23) / sample_rate */
tmp = ((u64)srate) << 23;
do_div(tmp, sample_rate);
ratio = (u32) tmp;
cx24123_writereg(state, 0x01, pll_mult * 6);

View file

@ -21,6 +21,7 @@
#ifndef CX24123_H
#define CX24123_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct cx24123_config {
@ -38,8 +39,7 @@ struct cx24123_config {
void (*agc_callback) (struct dvb_frontend *);
};
#if defined(CONFIG_DVB_CX24123) || (defined(CONFIG_DVB_CX24123_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_CX24123)
extern struct dvb_frontend *cx24123_attach(const struct cx24123_config *config,
struct i2c_adapter *i2c);
extern struct i2c_adapter *cx24123_get_tuner_i2c_adapter(struct dvb_frontend *);

View file

@ -22,6 +22,7 @@
#ifndef CXD2820R_H
#define CXD2820R_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#define CXD2820R_GPIO_D (0 << 0) /* disable */
@ -65,8 +66,7 @@ struct cxd2820r_config {
};
#if defined(CONFIG_DVB_CXD2820R) || \
(defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_CXD2820R)
extern struct dvb_frontend *cxd2820r_attach(
const struct cxd2820r_config *config,
struct i2c_adapter *i2c,

View file

@ -660,7 +660,8 @@ static const struct dvb_frontend_ops cxd2820r_ops = {
FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO |
FE_CAN_MUTE_TS |
FE_CAN_2G_MODULATION
FE_CAN_2G_MODULATION |
FE_CAN_MULTISTREAM
},
.release = cxd2820r_release,

View file

@ -124,6 +124,23 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
buf[1] = ((if_ctl >> 8) & 0xff);
buf[2] = ((if_ctl >> 0) & 0xff);
/* PLP filtering */
if (c->stream_id > 255) {
dev_dbg(&priv->i2c->dev, "%s: Disable PLP filtering\n", __func__);
ret = cxd2820r_wr_reg(priv, 0x023ad , 0);
if (ret)
goto error;
} else {
dev_dbg(&priv->i2c->dev, "%s: Enable PLP filtering = %d\n", __func__,
c->stream_id);
ret = cxd2820r_wr_reg(priv, 0x023af , c->stream_id & 0xFF);
if (ret)
goto error;
ret = cxd2820r_wr_reg(priv, 0x023ad , 1);
if (ret)
goto error;
}
ret = cxd2820r_wr_regs(priv, 0x020b6, buf, 3);
if (ret)
goto error;

View file

@ -528,20 +528,19 @@ static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_
u16 PllCfg, i, v;
HARD_RESET(state);
dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
if (cfg->in_soc)
return;
if (!cfg->in_soc) {
/* adcClkOutRatio=8->7, release reset */
dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
if (cfg->clkoutdrive != 0)
dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
| (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
else
dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
| (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
}
dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL); /* PLL, DIG_CLK and CRYSTAL remain */
/* adcClkOutRatio=8->7, release reset */
dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
if (cfg->clkoutdrive != 0)
dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
| (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
else
dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
| (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
/* Read Pll current config * */
PllCfg = dib0090_read_reg(state, 0x21);
@ -694,192 +693,174 @@ void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
EXPORT_SYMBOL(dib0090_dcc_freq);
static const u16 bb_ramp_pwm_normal_socs[] = {
550, /* max BB gain in 10th of dB */
(1 << 9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
550, /* max BB gain in 10th of dB */
(1<<9) | 8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
440,
(4 << 9) | 0, /* BB_RAMP3 = 26dB */
(0 << 9) | 208, /* BB_RAMP4 */
(4 << 9) | 208, /* BB_RAMP5 = 29dB */
(0 << 9) | 440, /* BB_RAMP6 */
(4 << 9) | 0, /* BB_RAMP3 = 26dB */
(0 << 9) | 208, /* BB_RAMP4 */
(4 << 9) | 208, /* BB_RAMP5 = 29dB */
(0 << 9) | 440, /* BB_RAMP6 */
};
static const u16 rf_ramp_pwm_cband_7090[] = {
280, /* max RF gain in 10th of dB */
18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
504, /* ramp_max = maximum X used on the ramp */
(29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
(0 << 10) | 504, /* RF_RAMP6, LNA 1 */
(60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
(0 << 10) | 364, /* RF_RAMP8, LNA 2 */
(34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
(0 << 10) | 228, /* GAIN_4_2, LNA 3 */
(37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
(0 << 10) | 109, /* RF_RAMP4, LNA 4 */
static const u16 rf_ramp_pwm_cband_7090p[] = {
280, /* max RF gain in 10th of dB */
18, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
504, /* ramp_max = maximum X used on the ramp */
(29 << 10) | 364, /* RF_RAMP5, LNA 1 = 8dB */
(0 << 10) | 504, /* RF_RAMP6, LNA 1 */
(60 << 10) | 228, /* RF_RAMP7, LNA 2 = 7.7dB */
(0 << 10) | 364, /* RF_RAMP8, LNA 2 */
(34 << 10) | 109, /* GAIN_4_1, LNA 3 = 6.8dB */
(0 << 10) | 228, /* GAIN_4_2, LNA 3 */
(37 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */
(0 << 10) | 109, /* RF_RAMP4, LNA 4 */
};
static const uint16_t rf_ramp_pwm_cband_7090e_sensitivity[] = {
186,
40,
746,
(10 << 10) | 345,
(0 << 10) | 746,
(0 << 10) | 0,
(0 << 10) | 0,
(28 << 10) | 200,
(0 << 10) | 345,
(20 << 10) | 0,
(0 << 10) | 200,
static const u16 rf_ramp_pwm_cband_7090e_sensitivity[] = {
186, /* max RF gain in 10th of dB */
40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
746, /* ramp_max = maximum X used on the ramp */
(10 << 10) | 345, /* RF_RAMP5, LNA 1 = 10dB */
(0 << 10) | 746, /* RF_RAMP6, LNA 1 */
(0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
(0 << 10) | 0, /* RF_RAMP8, LNA 2 */
(28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
(0 << 10) | 345, /* GAIN_4_2, LNA 3 */
(20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
(0 << 10) | 200, /* RF_RAMP4, LNA 4 */
};
static const uint16_t rf_ramp_pwm_cband_7090e_aci[] = {
86,
40,
345,
(0 << 10) | 0,
(0 << 10) | 0,
(0 << 10) | 0,
(0 << 10) | 0,
(28 << 10) | 200,
(0 << 10) | 345,
(20 << 10) | 0,
(0 << 10) | 200,
static const u16 rf_ramp_pwm_cband_7090e_aci[] = {
86, /* max RF gain in 10th of dB */
40, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
345, /* ramp_max = maximum X used on the ramp */
(0 << 10) | 0, /* RF_RAMP5, LNA 1 = 8dB */ /* 7.47 dB */
(0 << 10) | 0, /* RF_RAMP6, LNA 1 */
(0 << 10) | 0, /* RF_RAMP7, LNA 2 = 0 dB */
(0 << 10) | 0, /* RF_RAMP8, LNA 2 */
(28 << 10) | 200, /* GAIN_4_1, LNA 3 = 6.8dB */ /* 3.61 dB */
(0 << 10) | 345, /* GAIN_4_2, LNA 3 */
(20 << 10) | 0, /* RF_RAMP3, LNA 4 = 6.2dB */ /* 4.96 dB */
(0 << 10) | 200, /* RF_RAMP4, LNA 4 */
};
static const u16 rf_ramp_pwm_cband_8090[] = {
345, /* max RF gain in 10th of dB */
29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
1000, /* ramp_max = maximum X used on the ramp */
(35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
(0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
(58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
(0 << 10) | 772, /* RF_RAMP6, LNA 2 */
(27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
(0 << 10) | 496, /* RF_RAMP8, LNA 3 */
(40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
(0 << 10) | 200, /* GAIN_4_2, LNA 4 */
345, /* max RF gain in 10th of dB */
29, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
1000, /* ramp_max = maximum X used on the ramp */
(35 << 10) | 772, /* RF_RAMP3, LNA 1 = 8dB */
(0 << 10) | 1000, /* RF_RAMP4, LNA 1 */
(58 << 10) | 496, /* RF_RAMP5, LNA 2 = 9.5dB */
(0 << 10) | 772, /* RF_RAMP6, LNA 2 */
(27 << 10) | 200, /* RF_RAMP7, LNA 3 = 10.5dB */
(0 << 10) | 496, /* RF_RAMP8, LNA 3 */
(40 << 10) | 0, /* GAIN_4_1, LNA 4 = 7dB */
(0 << 10) | 200, /* GAIN_4_2, LNA 4 */
};
static const u16 rf_ramp_pwm_uhf_7090[] = {
407, /* max RF gain in 10th of dB */
13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
529, /* ramp_max = maximum X used on the ramp */
(23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
(0 << 10) | 176, /* RF_RAMP4, LNA 1 */
(63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
(0 << 10) | 529, /* RF_RAMP6, LNA 2 */
(48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
(0 << 10) | 400, /* RF_RAMP8, LNA 3 */
(29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
(0 << 10) | 316, /* GAIN_4_2, LNA 4 */
407, /* max RF gain in 10th of dB */
13, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
529, /* ramp_max = maximum X used on the ramp */
(23 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
(0 << 10) | 176, /* RF_RAMP4, LNA 1 */
(63 << 10) | 400, /* RF_RAMP5, LNA 2 = 8dB */
(0 << 10) | 529, /* RF_RAMP6, LNA 2 */
(48 << 10) | 316, /* RF_RAMP7, LNA 3 = 6.8dB */
(0 << 10) | 400, /* RF_RAMP8, LNA 3 */
(29 << 10) | 176, /* GAIN_4_1, LNA 4 = 11.5dB */
(0 << 10) | 316, /* GAIN_4_2, LNA 4 */
};
static const u16 rf_ramp_pwm_uhf_8090[] = {
388, /* max RF gain in 10th of dB */
26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
1008, /* ramp_max = maximum X used on the ramp */
(11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
(0 << 10) | 369, /* RF_RAMP4, LNA 1 */
(41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
(0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
(27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
(0 << 10) | 809, /* RF_RAMP8, LNA 3 */
(14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
(0 << 10) | 659, /* GAIN_4_2, LNA 4 */
388, /* max RF gain in 10th of dB */
26, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
1008, /* ramp_max = maximum X used on the ramp */
(11 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.7dB */
(0 << 10) | 369, /* RF_RAMP4, LNA 1 */
(41 << 10) | 809, /* RF_RAMP5, LNA 2 = 8dB */
(0 << 10) | 1008, /* RF_RAMP6, LNA 2 */
(27 << 10) | 659, /* RF_RAMP7, LNA 3 = 6dB */
(0 << 10) | 809, /* RF_RAMP8, LNA 3 */
(14 << 10) | 369, /* GAIN_4_1, LNA 4 = 11.5dB */
(0 << 10) | 659, /* GAIN_4_2, LNA 4 */
};
/* GENERAL PWM ramp definition for all other Krosus */
static const u16 bb_ramp_pwm_normal[] = {
500, /* max BB gain in 10th of dB */
8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
400,
(2 << 9) | 0, /* BB_RAMP3 = 21dB */
(0 << 9) | 168, /* BB_RAMP4 */
(2 << 9) | 168, /* BB_RAMP5 = 29dB */
(0 << 9) | 400, /* BB_RAMP6 */
};
static const u16 bb_ramp_pwm_boost[] = {
550, /* max BB gain in 10th of dB */
8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
440,
(2 << 9) | 0, /* BB_RAMP3 = 26dB */
(0 << 9) | 208, /* BB_RAMP4 */
(2 << 9) | 208, /* BB_RAMP5 = 29dB */
(0 << 9) | 440, /* BB_RAMP6 */
};
static const u16 rf_ramp_pwm_cband[] = {
0, /* max RF gain in 10th of dB */
0, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
0, /* ramp_max = maximum X used on the ramp */
(0 << 10) | 0, /* 0x2c, LNA 1 = 0dB */
(0 << 10) | 0, /* 0x2d, LNA 1 */
(0 << 10) | 0, /* 0x2e, LNA 2 = 0dB */
(0 << 10) | 0, /* 0x2f, LNA 2 */
(0 << 10) | 0, /* 0x30, LNA 3 = 0dB */
(0 << 10) | 0, /* 0x31, LNA 3 */
(0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
(0 << 10) | 0, /* GAIN_4_2, LNA 4 */
};
static const u16 rf_ramp_vhf[] = {
412, /* max RF gain in 10th of dB */
132, 307, 127, /* LNA1, 13.2dB */
105, 412, 255, /* LNA2, 10.5dB */
50, 50, 127, /* LNA3, 5dB */
125, 175, 127, /* LNA4, 12.5dB */
0, 0, 127, /* CBAND, 0dB */
};
static const u16 rf_ramp_uhf[] = {
412, /* max RF gain in 10th of dB */
132, 307, 127, /* LNA1 : total gain = 13.2dB, point on the ramp where this amp is full gain, value to write to get full gain */
105, 412, 255, /* LNA2 : 10.5 dB */
50, 50, 127, /* LNA3 : 5.0 dB */
125, 175, 127, /* LNA4 : 12.5 dB */
0, 0, 127, /* CBAND : 0.0 dB */
};
static const u16 rf_ramp_cband_broadmatching[] = /* for p1G only */
{
314, /* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
84, 314, 127, /* LNA1 */
80, 230, 255, /* LNA2 */
80, 150, 127, /* LNA3 It was measured 12dB, do not lock if 120 */
70, 70, 127, /* LNA4 */
0, 0, 127, /* CBAND */
};
static const u16 rf_ramp_cband[] = {
332, /* max RF gain in 10th of dB */
132, 252, 127, /* LNA1, dB */
80, 332, 255, /* LNA2, dB */
0, 0, 127, /* LNA3, dB */
0, 0, 127, /* LNA4, dB */
120, 120, 127, /* LT1 CBAND */
314, /* max RF gain in 10th of dB */
33, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
1023, /* ramp_max = maximum X used on the ramp */
(8 << 10) | 743, /* RF_RAMP3, LNA 1 = 0dB */
(0 << 10) | 1023, /* RF_RAMP4, LNA 1 */
(15 << 10) | 469, /* RF_RAMP5, LNA 2 = 0dB */
(0 << 10) | 742, /* RF_RAMP6, LNA 2 */
(9 << 10) | 234, /* RF_RAMP7, LNA 3 = 0dB */
(0 << 10) | 468, /* RF_RAMP8, LNA 3 */
(9 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
(0 << 10) | 233, /* GAIN_4_2, LNA 4 */
};
static const u16 rf_ramp_pwm_vhf[] = {
404, /* max RF gain in 10th of dB */
25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
1011, /* ramp_max = maximum X used on the ramp */
(6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
(0 << 10) | 756, /* 0x2d, LNA 1 */
(16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
(0 << 10) | 1011, /* 0x2f, LNA 2 */
(16 << 10) | 290, /* 0x30, LNA 3 = 5dB */
(0 << 10) | 417, /* 0x31, LNA 3 */
(7 << 10) | 0, /* GAIN_4_1, LNA 4 = 12.5dB */
(0 << 10) | 290, /* GAIN_4_2, LNA 4 */
398, /* max RF gain in 10th of dB */
24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
954, /* ramp_max = maximum X used on the ramp */
(7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
(0 << 10) | 290, /* RF_RAMP4, LNA 1 */
(16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
(0 << 10) | 954, /* RF_RAMP6, LNA 2 */
(17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
(0 << 10) | 699, /* RF_RAMP8, LNA 3 */
(7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
(0 << 10) | 580, /* GAIN_4_2, LNA 4 */
};
static const u16 rf_ramp_pwm_uhf[] = {
404, /* max RF gain in 10th of dB */
25, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
1011, /* ramp_max = maximum X used on the ramp */
(6 << 10) | 417, /* 0x2c, LNA 1 = 13.2dB */
(0 << 10) | 756, /* 0x2d, LNA 1 */
(16 << 10) | 756, /* 0x2e, LNA 2 = 10.5dB */
(0 << 10) | 1011, /* 0x2f, LNA 2 */
(16 << 10) | 0, /* 0x30, LNA 3 = 5dB */
(0 << 10) | 127, /* 0x31, LNA 3 */
(7 << 10) | 127, /* GAIN_4_1, LNA 4 = 12.5dB */
(0 << 10) | 417, /* GAIN_4_2, LNA 4 */
398, /* max RF gain in 10th of dB */
24, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
954, /* ramp_max = maximum X used on the ramp */
(7 << 10) | 0, /* RF_RAMP3, LNA 1 = 13.2dB */
(0 << 10) | 290, /* RF_RAMP4, LNA 1 */
(16 << 10) | 699, /* RF_RAMP5, LNA 2 = 10.5dB */
(0 << 10) | 954, /* RF_RAMP6, LNA 2 */
(17 << 10) | 580, /* RF_RAMP7, LNA 3 = 5dB */
(0 << 10) | 699, /* RF_RAMP8, LNA 3 */
(7 << 10) | 290, /* GAIN_4_1, LNA 4 = 12.5dB */
(0 << 10) | 580, /* GAIN_4_2, LNA 4 */
};
static const u16 bb_ramp_boost[] = {
550, /* max BB gain in 10th of dB */
260, 260, 26, /* BB1, 26dB */
290, 550, 29, /* BB2, 29dB */
};
static const u16 bb_ramp_pwm_normal[] = {
500, /* max RF gain in 10th of dB */
8, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x34 */
400,
(2 << 9) | 0, /* 0x35 = 21dB */
(0 << 9) | 168, /* 0x36 */
(2 << 9) | 168, /* 0x37 = 29dB */
(0 << 9) | 400, /* 0x38 */
static const u16 rf_ramp_pwm_sband[] = {
253, /* max RF gain in 10th of dB */
38, /* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
961,
(4 << 10) | 0, /* RF_RAMP3, LNA 1 = 14.1dB */
(0 << 10) | 508, /* RF_RAMP4, LNA 1 */
(9 << 10) | 508, /* RF_RAMP5, LNA 2 = 11.2dB */
(0 << 10) | 961, /* RF_RAMP6, LNA 2 */
(0 << 10) | 0, /* RF_RAMP7, LNA 3 = 0dB */
(0 << 10) | 0, /* RF_RAMP8, LNA 3 */
(0 << 10) | 0, /* GAIN_4_1, LNA 4 = 0dB */
(0 << 10) | 0, /* GAIN_4_2, LNA 4 */
};
struct slope {
@ -1089,70 +1070,69 @@ static void dib0090_set_bbramp_pwm(struct dib0090_state *state, const u16 * cfg)
void dib0090_pwm_gain_reset(struct dvb_frontend *fe)
{
struct dib0090_state *state = fe->tuner_priv;
/* reset the AGC */
u16 *bb_ramp = (u16 *)&bb_ramp_pwm_normal; /* default baseband config */
u16 *rf_ramp = NULL;
u8 en_pwm_rf_mux = 1;
/* reset the AGC */
if (state->config->use_pwm_agc) {
#ifdef CONFIG_BAND_SBAND
if (state->current_band == BAND_SBAND) {
dib0090_set_rframp_pwm(state, rf_ramp_pwm_sband);
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_boost);
} else
#endif
#ifdef CONFIG_BAND_CBAND
if (state->current_band == BAND_CBAND) {
if (state->identity.in_soc) {
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
else if (state->identity.version == SOC_7090_P1G_11R1
|| state->identity.version == SOC_7090_P1G_21R1) {
rf_ramp = (u16 *)&rf_ramp_pwm_cband_8090;
else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1) {
if (state->config->is_dib7090e) {
if (state->rf_ramp == NULL)
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090e_sensitivity);
rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090e_sensitivity;
else
dib0090_set_rframp_pwm(state, state->rf_ramp);
rf_ramp = (u16 *)state->rf_ramp;
} else
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
rf_ramp = (u16 *)&rf_ramp_pwm_cband_7090p;
}
} else {
dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
}
} else
rf_ramp = (u16 *)&rf_ramp_pwm_cband;
} else
#endif
#ifdef CONFIG_BAND_VHF
if (state->current_band == BAND_VHF) {
if (state->identity.in_soc) {
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
} else {
dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
}
} else
#endif
{
if (state->identity.in_soc) {
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
} else {
dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
}
}
if (state->rf_ramp[0] != 0)
dib0090_write_reg(state, 0x32, (3 << 11));
if (state->current_band == BAND_VHF) {
if (state->identity.in_soc) {
bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
/* rf_ramp = &rf_ramp_pwm_vhf_socs; */ /* TODO */
} else
rf_ramp = (u16 *)&rf_ramp_pwm_vhf;
} else if (state->current_band == BAND_UHF) {
if (state->identity.in_soc) {
bb_ramp = (u16 *)&bb_ramp_pwm_normal_socs;
if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
rf_ramp = (u16 *)&rf_ramp_pwm_uhf_8090;
else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
rf_ramp = (u16 *)&rf_ramp_pwm_uhf_7090;
} else
rf_ramp = (u16 *)&rf_ramp_pwm_uhf;
}
if (rf_ramp)
dib0090_set_rframp_pwm(state, rf_ramp);
dib0090_set_bbramp_pwm(state, bb_ramp);
/* activate the ramp generator using PWM control */
dprintk("ramp RF gain = %d BAND = %s version = %d", state->rf_ramp[0], (state->current_band == BAND_CBAND) ? "CBAND" : "NOT CBAND", state->identity.version & 0x1f);
if ((state->rf_ramp[0] == 0) || (state->current_band == BAND_CBAND && (state->identity.version & 0x1f) <= P1D_E_F)) {
dprintk("DE-Engage mux for direct gain reg control");
en_pwm_rf_mux = 0;
} else
dprintk("Engage mux for PWM control");
dib0090_write_reg(state, 0x32, (en_pwm_rf_mux << 12) | (en_pwm_rf_mux << 11));
/* Set fast servo cutoff to start AGC; 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast*/
if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
dib0090_write_reg(state, 0x04, 3);
else
dib0090_write_reg(state, 0x32, (0 << 11));
dib0090_write_reg(state, 0x04, 0x03);
dib0090_write_reg(state, 0x39, (1 << 10));
dib0090_write_reg(state, 0x04, 1);
dib0090_write_reg(state, 0x39, (1 << 10)); /* 0 gain by default */
}
}
EXPORT_SYMBOL(dib0090_pwm_gain_reset);
void dib0090_set_dc_servo(struct dvb_frontend *fe, u8 DC_servo_cutoff)
@ -1193,22 +1173,22 @@ int dib0090_gain_control(struct dvb_frontend *fe)
#endif
#ifdef CONFIG_BAND_VHF
if (state->current_band == BAND_VHF && !state->identity.p1g) {
dib0090_set_rframp(state, rf_ramp_vhf);
dib0090_set_bbramp(state, bb_ramp_boost);
dib0090_set_rframp(state, rf_ramp_pwm_vhf);
dib0090_set_bbramp(state, bb_ramp_pwm_normal);
} else
#endif
#ifdef CONFIG_BAND_CBAND
if (state->current_band == BAND_CBAND && !state->identity.p1g) {
dib0090_set_rframp(state, rf_ramp_cband);
dib0090_set_bbramp(state, bb_ramp_boost);
dib0090_set_rframp(state, rf_ramp_pwm_cband);
dib0090_set_bbramp(state, bb_ramp_pwm_normal);
} else
#endif
if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
dib0090_set_bbramp(state, bb_ramp_boost);
dib0090_set_rframp(state, rf_ramp_pwm_cband_7090p);
dib0090_set_bbramp(state, bb_ramp_pwm_normal_socs);
} else {
dib0090_set_rframp(state, rf_ramp_uhf);
dib0090_set_bbramp(state, bb_ramp_boost);
dib0090_set_rframp(state, rf_ramp_pwm_uhf);
dib0090_set_bbramp(state, bb_ramp_pwm_normal);
}
dib0090_write_reg(state, 0x32, 0);
@ -1553,14 +1533,16 @@ static void dib0090_set_EFUSE(struct dib0090_state *state)
if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
c = 32;
else
c += 14;
if ((h >= HR_MAX) || (h <= HR_MIN))
h = 34;
if ((n >= POLY_MAX) || (n <= POLY_MIN))
n = 3;
dib0090_write_reg(state, 0x13, (h << 10)) ;
e2 = (n<<11) | ((h>>2)<<6) | (c);
dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
dib0090_write_reg(state, 0x13, (h << 10));
e2 = (n << 11) | ((h >> 2)<<6) | c;
dib0090_write_reg(state, 0x2, e2); /* Load the BB_2 */
}
}

View file

@ -13,6 +13,8 @@
#ifndef DIB3000MC_H
#define DIB3000MC_H
#include <linux/kconfig.h>
#include "dibx000_common.h"
struct dib3000mc_config {
@ -39,8 +41,7 @@ struct dib3000mc_config {
#define DEFAULT_DIB3000MC_I2C_ADDRESS 16
#define DEFAULT_DIB3000P_I2C_ADDRESS 24
#if defined(CONFIG_DVB_DIB3000MC) || (defined(CONFIG_DVB_DIB3000MC_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DIB3000MC)
extern struct dvb_frontend *dib3000mc_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr,
struct dib3000mc_config *cfg);

View file

@ -1,6 +1,8 @@
#ifndef DIB7000M_H
#define DIB7000M_H
#include <linux/kconfig.h>
#include "dibx000_common.h"
struct dib7000m_config {
@ -38,8 +40,7 @@ struct dib7000m_config {
#define DEFAULT_DIB7000M_I2C_ADDRESS 18
#if defined(CONFIG_DVB_DIB7000M) || (defined(CONFIG_DVB_DIB7000M_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DIB7000M)
extern struct dvb_frontend *dib7000m_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr,
struct dib7000m_config *cfg);

View file

@ -429,6 +429,13 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
}
EXPORT_SYMBOL(dib7000p_get_agc_values);
int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
struct dib7000p_state *state = fe->demodulator_priv;
return dib7000p_write_word(state, 108, v);
}
EXPORT_SYMBOL(dib7000p_set_agc1_min);
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
@ -821,6 +828,7 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod)
u8 agc_split;
u16 reg;
u32 upd_demod_gain_period = 0x1000;
s32 frequency_offset = 0;
switch (state->agc_state) {
case 0:
@ -841,7 +849,14 @@ static int dib7000p_agc_startup(struct dvb_frontend *demod)
if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
return -1;
dib7000p_set_dds(state, 0);
if (demod->ops.tuner_ops.get_frequency) {
u32 frequency_tuner;
demod->ops.tuner_ops.get_frequency(demod, &frequency_tuner);
frequency_offset = (s32)frequency_tuner / 1000 - ch->frequency / 1000;
}
dib7000p_set_dds(state, frequency_offset);
ret = 7;
(*agc_state)++;
break;

View file

@ -1,6 +1,8 @@
#ifndef DIB7000P_H
#define DIB7000P_H
#include <linux/kconfig.h>
#include "dibx000_common.h"
struct dib7000p_config {
@ -44,8 +46,7 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
#if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DIB7000P)
extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
@ -62,6 +63,7 @@ extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
extern int dib7090_slave_reset(struct dvb_frontend *fe);
extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
#else
static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
@ -153,6 +155,12 @@ static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;
}
#endif
#endif

File diff suppressed because it is too large Load diff

View file

@ -33,6 +33,8 @@ struct dib8000_config {
u8 output_mode;
u8 refclksel;
u8 enMpegOutput:1;
struct dibx000_bandwidth_config *plltable;
};
#define DEFAULT_DIB8000_I2C_ADDRESS 18
@ -58,7 +60,7 @@ extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
uint8_t op, uint32_t timf);
extern int dib8000_update_pll(struct dvb_frontend *fe,
struct dibx000_bandwidth_config *pll);
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
@ -147,7 +149,7 @@ static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
return 0;
}
static inline int dib8000_update_pll(struct dvb_frontend *fe,
struct dibx000_bandwidth_config *pll)
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return -ENODEV;

View file

@ -193,7 +193,8 @@ enum frontend_tune_state {
CT_DEMOD_STEP_8,
CT_DEMOD_STEP_9,
CT_DEMOD_STEP_10,
CT_DEMOD_SEARCH_NEXT = 41,
CT_DEMOD_STEP_11,
CT_DEMOD_SEARCH_NEXT = 51,
CT_DEMOD_STEP_LOCKED,
CT_DEMOD_STOP,

View file

@ -24,6 +24,7 @@
#ifndef _DRXD_H_
#define _DRXD_H_
#include <linux/kconfig.h>
#include <linux/types.h>
#include <linux/i2c.h>
@ -51,8 +52,7 @@ struct drxd_config {
s16(*osc_deviation) (void *priv, s16 dev, int flag);
};
#if defined(CONFIG_DVB_DRXD) || \
(defined(CONFIG_DVB_DRXD_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DRXD)
extern
struct dvb_frontend *drxd_attach(const struct drxd_config *config,
void *priv, struct i2c_adapter *i2c,

View file

@ -1,6 +1,7 @@
#ifndef _DRXK_H_
#define _DRXK_H_
#include <linux/kconfig.h>
#include <linux/types.h>
#include <linux/i2c.h>
@ -52,8 +53,7 @@ struct drxk_config {
int qam_demod_parameter_count;
};
#if defined(CONFIG_DVB_DRXK) || (defined(CONFIG_DVB_DRXK_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DRXK)
extern struct dvb_frontend *drxk_attach(const struct drxk_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -1947,8 +1947,7 @@ static int ShutDown(struct drxk_state *state)
return 0;
}
static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus,
u32 Time)
static int GetLockStatus(struct drxk_state *state, u32 *pLockStatus)
{
int status = -EINVAL;
@ -2490,32 +2489,6 @@ error:
return status;
}
static int ReadIFAgc(struct drxk_state *state, u32 *pValue)
{
u16 agcDacLvl;
int status;
u16 Level = 0;
dprintk(1, "\n");
status = read16(state, IQM_AF_AGC_IF__A, &agcDacLvl);
if (status < 0) {
printk(KERN_ERR "drxk: Error %d on %s\n", status, __func__);
return status;
}
*pValue = 0;
if (agcDacLvl > DRXK_AGC_DAC_OFFSET)
Level = agcDacLvl - DRXK_AGC_DAC_OFFSET;
if (Level < 14000)
*pValue = (14000 - Level) / 4;
else
*pValue = 0;
return status;
}
static int GetQAMSignalToNoise(struct drxk_state *state,
s32 *pSignalToNoise)
{
@ -2654,12 +2627,7 @@ static int GetDVBTSignalToNoise(struct drxk_state *state,
/* log(x) x = (16bits + 16bits) << 15 ->32 bits */
c = Log10Times100(SqrErrIQ);
iMER = a + b;
/* No negative MER, clip to zero */
if (iMER > c)
iMER -= c;
else
iMER = 0;
iMER = a + b - c;
}
*pSignalToNoise = iMER;
@ -6380,46 +6348,257 @@ static int drxk_set_parameters(struct dvb_frontend *fe)
fe->ops.tuner_ops.get_if_frequency(fe, &IF);
Start(state, 0, IF);
/* After set_frontend, stats aren't avaliable */
p->strength.stat[0].scale = FE_SCALE_RELATIVE;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
/* printk(KERN_DEBUG "drxk: %s IF=%d done\n", __func__, IF); */
return 0;
}
static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
static int get_strength(struct drxk_state *state, u64 *strength)
{
struct drxk_state *state = fe->demodulator_priv;
u32 stat;
int status;
struct SCfgAgc rfAgc, ifAgc;
u32 totalGain = 0;
u32 atten = 0;
u32 agcRange = 0;
u16 scu_lvl = 0;
u16 scu_coc = 0;
/* FIXME: those are part of the tuner presets */
u16 tunerRfGain = 50; /* Default value on az6007 driver */
u16 tunerIfGain = 40; /* Default value on az6007 driver */
dprintk(1, "\n");
*strength = 0;
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
if (IsDVBT(state)) {
rfAgc = state->m_dvbtRfAgcCfg;
ifAgc = state->m_dvbtIfAgcCfg;
} else if (IsQAM(state)) {
rfAgc = state->m_qamRfAgcCfg;
ifAgc = state->m_qamIfAgcCfg;
} else {
rfAgc = state->m_atvRfAgcCfg;
ifAgc = state->m_atvIfAgcCfg;
}
if (rfAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) {
/* SCU outputLevel */
status = read16(state, SCU_RAM_AGC_RF_IACCU_HI__A, &scu_lvl);
if (status < 0)
return status;
/* SCU c.o.c. */
read16(state, SCU_RAM_AGC_RF_IACCU_HI_CO__A, &scu_coc);
if (status < 0)
return status;
if (((u32) scu_lvl + (u32) scu_coc) < 0xffff)
rfAgc.outputLevel = scu_lvl + scu_coc;
else
rfAgc.outputLevel = 0xffff;
/* Take RF gain into account */
totalGain += tunerRfGain;
/* clip output value */
if (rfAgc.outputLevel < rfAgc.minOutputLevel)
rfAgc.outputLevel = rfAgc.minOutputLevel;
if (rfAgc.outputLevel > rfAgc.maxOutputLevel)
rfAgc.outputLevel = rfAgc.maxOutputLevel;
agcRange = (u32) (rfAgc.maxOutputLevel - rfAgc.minOutputLevel);
if (agcRange > 0) {
atten += 100UL *
((u32)(tunerRfGain)) *
((u32)(rfAgc.outputLevel - rfAgc.minOutputLevel))
/ agcRange;
}
}
if (ifAgc.ctrlMode == DRXK_AGC_CTRL_AUTO) {
status = read16(state, SCU_RAM_AGC_IF_IACCU_HI__A,
&ifAgc.outputLevel);
if (status < 0)
return status;
status = read16(state, SCU_RAM_AGC_INGAIN_TGT_MIN__A,
&ifAgc.top);
if (status < 0)
return status;
/* Take IF gain into account */
totalGain += (u32) tunerIfGain;
/* clip output value */
if (ifAgc.outputLevel < ifAgc.minOutputLevel)
ifAgc.outputLevel = ifAgc.minOutputLevel;
if (ifAgc.outputLevel > ifAgc.maxOutputLevel)
ifAgc.outputLevel = ifAgc.maxOutputLevel;
agcRange = (u32) (ifAgc.maxOutputLevel - ifAgc.minOutputLevel);
if (agcRange > 0) {
atten += 100UL *
((u32)(tunerIfGain)) *
((u32)(ifAgc.outputLevel - ifAgc.minOutputLevel))
/ agcRange;
}
}
/*
* Convert to 0..65535 scale.
* If it can't be measured (AGC is disabled), just show 100%.
*/
if (totalGain > 0)
*strength = (65535UL * atten / totalGain / 100);
else
*strength = 65535;
*status = 0;
GetLockStatus(state, &stat, 0);
if (stat == MPEG_LOCK)
*status |= 0x1f;
if (stat == FEC_LOCK)
*status |= 0x0f;
if (stat == DEMOD_LOCK)
*status |= 0x07;
return 0;
}
static int drxk_read_ber(struct dvb_frontend *fe, u32 *ber)
static int drxk_get_stats(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "\n");
int status;
u32 stat;
u16 reg16;
u32 post_bit_count;
u32 post_bit_err_count;
u32 post_bit_error_scale;
u32 pre_bit_err_count;
u32 pre_bit_count;
u32 pkt_count;
u32 pkt_error_count;
s32 cnr;
if (state->m_DrxkState == DRXK_NO_DEV)
return -ENODEV;
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
*ber = 0;
/* get status */
state->fe_status = 0;
GetLockStatus(state, &stat);
if (stat == MPEG_LOCK)
state->fe_status |= 0x1f;
if (stat == FEC_LOCK)
state->fe_status |= 0x0f;
if (stat == DEMOD_LOCK)
state->fe_status |= 0x07;
/*
* Estimate signal strength from AGC
*/
get_strength(state, &c->strength.stat[0].uvalue);
c->strength.stat[0].scale = FE_SCALE_RELATIVE;
if (stat >= DEMOD_LOCK) {
GetSignalToNoise(state, &cnr);
c->cnr.stat[0].svalue = cnr * 100;
c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
} else {
c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
}
if (stat < FEC_LOCK) {
c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
return 0;
}
/* Get post BER */
/* BER measurement is valid if at least FEC lock is achieved */
/* OFDM_EC_VD_REQ_SMB_CNT__A and/or OFDM_EC_VD_REQ_BIT_CNT can be written
to set nr of symbols or bits over which
to measure EC_VD_REG_ERR_BIT_CNT__A . See CtrlSetCfg(). */
/* Read registers for post/preViterbi BER calculation */
status = read16(state, OFDM_EC_VD_ERR_BIT_CNT__A, &reg16);
if (status < 0)
goto error;
pre_bit_err_count = reg16;
status = read16(state, OFDM_EC_VD_IN_BIT_CNT__A , &reg16);
if (status < 0)
goto error;
pre_bit_count = reg16;
/* Number of bit-errors */
status = read16(state, FEC_RS_NR_BIT_ERRORS__A, &reg16);
if (status < 0)
goto error;
post_bit_err_count = reg16;
status = read16(state, FEC_RS_MEASUREMENT_PRESCALE__A, &reg16);
if (status < 0)
goto error;
post_bit_error_scale = reg16;
status = read16(state, FEC_RS_MEASUREMENT_PERIOD__A, &reg16);
if (status < 0)
goto error;
pkt_count = reg16;
status = read16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, &reg16);
if (status < 0)
goto error;
pkt_error_count = reg16;
write16(state, SCU_RAM_FEC_ACCUM_PKT_FAILURES__A, 0);
post_bit_err_count *= post_bit_error_scale;
post_bit_count = pkt_count * 204 * 8;
/* Store the results */
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue += pkt_error_count;
c->block_count.stat[0].scale = FE_SCALE_COUNTER;
c->block_count.stat[0].uvalue += pkt_count;
c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[0].uvalue += pre_bit_err_count;
c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[0].uvalue += pre_bit_count;
c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[0].uvalue += post_bit_err_count;
c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[0].uvalue += post_bit_count;
error:
return status;
}
static int drxk_read_status(struct dvb_frontend *fe, fe_status_t *status)
{
struct drxk_state *state = fe->demodulator_priv;
int rc;
dprintk(1, "\n");
rc = drxk_get_stats(fe);
if (rc < 0)
return rc;
*status = state->fe_status;
return 0;
}
@ -6427,7 +6606,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
u16 *strength)
{
struct drxk_state *state = fe->demodulator_priv;
u32 val = 0;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
dprintk(1, "\n");
@ -6436,8 +6615,7 @@ static int drxk_read_signal_strength(struct dvb_frontend *fe,
if (state->m_DrxkState == DRXK_UNINITIALIZED)
return -EAGAIN;
ReadIFAgc(state, &val);
*strength = val & 0xffff;
*strength = c->strength.stat[0].uvalue;
return 0;
}
@ -6454,6 +6632,10 @@ static int drxk_read_snr(struct dvb_frontend *fe, u16 *snr)
return -EAGAIN;
GetSignalToNoise(state, &snr2);
/* No negative SNR, clip to zero */
if (snr2 < 0)
snr2 = 0;
*snr = snr2 & 0xffff;
return 0;
}
@ -6529,7 +6711,6 @@ static struct dvb_frontend_ops drxk_ops = {
.get_tune_settings = drxk_get_tune_settings,
.read_status = drxk_read_status,
.read_ber = drxk_read_ber,
.read_signal_strength = drxk_read_signal_strength,
.read_snr = drxk_read_snr,
.read_ucblocks = drxk_read_ucblocks,
@ -6538,6 +6719,7 @@ static struct dvb_frontend_ops drxk_ops = {
struct dvb_frontend *drxk_attach(const struct drxk_config *config,
struct i2c_adapter *i2c)
{
struct dtv_frontend_properties *p;
struct drxk_state *state = NULL;
u8 adr = config->adr;
int status;
@ -6618,6 +6800,27 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
} else if (init_drxk(state) < 0)
goto error;
/* Initialize stats */
p = &state->frontend.dtv_property_cache;
p->strength.len = 1;
p->cnr.len = 1;
p->block_error.len = 1;
p->block_count.len = 1;
p->pre_bit_error.len = 1;
p->pre_bit_count.len = 1;
p->post_bit_error.len = 1;
p->post_bit_count.len = 1;
p->strength.stat[0].scale = FE_SCALE_RELATIVE;
p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->pre_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
p->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
printk(KERN_INFO "drxk: frontend initialized.\n");
return &state->frontend;

View file

@ -345,6 +345,8 @@ struct drxk_state {
bool antenna_dvbt;
u16 antenna_gpio;
fe_status_t fe_status;
/* Firmware */
const char *microcode_name;
struct completion fw_wait_load;

View file

@ -10,6 +10,7 @@
#define FEC_RS_COMM_EXEC_STOP 0x0
#define FEC_RS_MEASUREMENT_PERIOD__A 0x1C30012
#define FEC_RS_MEASUREMENT_PRESCALE__A 0x1C30013
#define FEC_RS_NR_BIT_ERRORS__A 0x1C30014
#define FEC_OC_MODE__A 0x1C40011
#define FEC_OC_MODE_PARITY__M 0x1
#define FEC_OC_DTO_MODE__A 0x1C40014
@ -129,6 +130,8 @@
#define OFDM_EC_SB_PRIOR__A 0x3410013
#define OFDM_EC_SB_PRIOR_HI 0x0
#define OFDM_EC_SB_PRIOR_LO 0x1
#define OFDM_EC_VD_ERR_BIT_CNT__A 0x3420017
#define OFDM_EC_VD_IN_BIT_CNT__A 0x3420018
#define OFDM_EQ_TOP_TD_TPS_CONST__A 0x3010054
#define OFDM_EQ_TOP_TD_TPS_CONST__M 0x3
#define OFDM_EQ_TOP_TD_TPS_CONST_64QAM 0x2

View file

@ -22,6 +22,7 @@
#ifndef DS3000_H
#define DS3000_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct ds3000_config {
@ -34,8 +35,7 @@ struct ds3000_config {
void (*set_lock_led)(struct dvb_frontend *fe, int offon);
};
#if defined(CONFIG_DVB_DS3000) || \
(defined(CONFIG_DVB_DS3000_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DS3000)
extern struct dvb_frontend *ds3000_attach(const struct ds3000_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -22,11 +22,11 @@
#ifndef DVB_DUMMY_FE_H
#define DVB_DUMMY_FE_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
#if defined(CONFIG_DVB_DUMMY_FE) || (defined(CONFIG_DVB_DUMMY_FE_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_DUMMY_FE)
extern struct dvb_frontend* dvb_dummy_fe_ofdm_attach(void);
extern struct dvb_frontend* dvb_dummy_fe_qpsk_attach(void);
extern struct dvb_frontend* dvb_dummy_fe_qam_attach(void);

View file

@ -22,6 +22,7 @@
#ifndef EC100_H
#define EC100_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct ec100_config {
@ -30,8 +31,7 @@ struct ec100_config {
};
#if defined(CONFIG_DVB_EC100) || \
(defined(CONFIG_DVB_EC100_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_EC100)
extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -23,6 +23,7 @@
#ifndef HD29L2_H
#define HD29L2_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct hd29l2_config {
@ -50,8 +51,7 @@ struct hd29l2_config {
};
#if defined(CONFIG_DVB_HD29L2) || \
(defined(CONFIG_DVB_HD29L2_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_HD29L2)
extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -89,6 +89,30 @@ static int isl6421_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static int isl6421_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone)
{
struct isl6421 *isl6421 = (struct isl6421 *) fe->sec_priv;
struct i2c_msg msg = { .addr = isl6421->i2c_addr, .flags = 0,
.buf = &isl6421->config,
.len = sizeof(isl6421->config) };
switch (tone) {
case SEC_TONE_ON:
isl6421->config |= ISL6421_ENT1;
break;
case SEC_TONE_OFF:
isl6421->config &= ~ISL6421_ENT1;
break;
default:
return -EINVAL;
}
isl6421->config |= isl6421->override_or;
isl6421->config &= isl6421->override_and;
return (i2c_transfer(isl6421->i2c, &msg, 1) == 1) ? 0 : -EIO;
}
static void isl6421_release(struct dvb_frontend *fe)
{
/* power off */
@ -100,7 +124,7 @@ static void isl6421_release(struct dvb_frontend *fe)
}
struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear)
u8 override_set, u8 override_clear, bool override_tone)
{
struct isl6421 *isl6421 = kmalloc(sizeof(struct isl6421), GFP_KERNEL);
if (!isl6421)
@ -131,6 +155,8 @@ struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter
/* override frontend ops */
fe->ops.set_voltage = isl6421_set_voltage;
fe->ops.enable_high_lnb_voltage = isl6421_enable_high_lnb_voltage;
if (override_tone)
fe->ops.set_tone = isl6421_set_tone;
return fe;
}

View file

@ -42,10 +42,10 @@
#if IS_ENABLED(CONFIG_DVB_ISL6421)
/* override_set and override_clear control which system register bits (above) to always set & clear */
extern struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear);
u8 override_set, u8 override_clear, bool override_tone);
#else
static inline struct dvb_frontend *isl6421_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, u8 i2c_addr,
u8 override_set, u8 override_clear)
u8 override_set, u8 override_clear, bool override_tone)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;

View file

@ -21,6 +21,7 @@
#ifndef IT913X_FE_H
#define IT913X_FE_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
@ -38,8 +39,7 @@ struct ite_config {
u8 read_slevel;
};
#if defined(CONFIG_DVB_IT913X_FE) || (defined(CONFIG_DVB_IT913X_FE_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_IT913X_FE)
extern struct dvb_frontend *it913x_fe_attach(struct i2c_adapter *i2c_adap,
u8 i2c_addr, struct ite_config *config);
#else

View file

@ -20,6 +20,7 @@
#ifndef DVB_IX2505V_H
#define DVB_IX2505V_H
#include <linux/kconfig.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
@ -48,8 +49,7 @@ struct ix2505v_config {
};
#if defined(CONFIG_DVB_IX2505V) || \
(defined(CONFIG_DVB_IX2505V_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_IX2505V)
extern struct dvb_frontend *ix2505v_attach(struct dvb_frontend *fe,
const struct ix2505v_config *config, struct i2c_adapter *i2c);
#else

View file

@ -22,6 +22,7 @@
#ifndef _LG2160_H_
#define _LG2160_H_
#include <linux/kconfig.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
@ -56,18 +57,17 @@ struct lg2160_config {
u16 if_khz;
/* disable i2c repeater - 0:repeater enabled 1:repeater disabled */
int deny_i2c_rptr:1;
unsigned int deny_i2c_rptr:1;
/* spectral inversion - 0:disabled 1:enabled */
int spectral_inversion:1;
unsigned int spectral_inversion:1;
unsigned int output_if;
enum lg2160_spi_clock spi_clock;
enum lg_chip_type lg_chip;
};
#if defined(CONFIG_DVB_LG2160) || (defined(CONFIG_DVB_LG2160_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LG2160)
extern
struct dvb_frontend *lg2160_attach(const struct lg2160_config *config,
struct i2c_adapter *i2c_adap);

View file

@ -22,6 +22,7 @@
#ifndef _LGDT3305_H_
#define _LGDT3305_H_
#include <linux/kconfig.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
@ -73,8 +74,7 @@ struct lgdt3305_config {
enum lgdt_demod_chip_type demod_chip;
};
#if defined(CONFIG_DVB_LGDT3305) || (defined(CONFIG_DVB_LGDT3305_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LGDT3305)
extern
struct dvb_frontend *lgdt3305_attach(const struct lgdt3305_config *config,
struct i2c_adapter *i2c_adap);

View file

@ -23,6 +23,7 @@
#ifndef LGS8GL5_H
#define LGS8GL5_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct lgs8gl5_config {
@ -30,8 +31,7 @@ struct lgs8gl5_config {
u8 demod_address;
};
#if defined(CONFIG_DVB_LGS8GL5) || \
(defined(CONFIG_DVB_LGS8GL5_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LGS8GL5)
extern struct dvb_frontend *lgs8gl5_attach(
const struct lgs8gl5_config *config, struct i2c_adapter *i2c);
#else

View file

@ -26,6 +26,7 @@
#ifndef __LGS8GXX_H__
#define __LGS8GXX_H__
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include <linux/i2c.h>
@ -79,8 +80,7 @@ struct lgs8gxx_config {
u8 tuner_address;
};
#if defined(CONFIG_DVB_LGS8GXX) || \
(defined(CONFIG_DVB_LGS8GXX_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LGS8GXX)
extern struct dvb_frontend *lgs8gxx_attach(const struct lgs8gxx_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -23,6 +23,8 @@
#ifndef _LNBH24_H
#define _LNBH24_H
#include <linux/kconfig.h>
/* system register bits */
#define LNBH24_OLF 0x01
#define LNBH24_OTF 0x02
@ -35,8 +37,7 @@
#include <linux/dvb/frontend.h>
#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LNBP21)
/* override_set and override_clear control which
system register bits (above) to always set & clear */
extern struct dvb_frontend *lnbh24_attach(struct dvb_frontend *fe,

View file

@ -27,6 +27,8 @@
#ifndef _LNBP21_H
#define _LNBP21_H
#include <linux/kconfig.h>
/* system register bits */
/* [RO] 0=OK; 1=over current limit flag */
#define LNBP21_OLF 0x01
@ -55,8 +57,7 @@
#include <linux/dvb/frontend.h>
#if defined(CONFIG_DVB_LNBP21) || (defined(CONFIG_DVB_LNBP21_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LNBP21)
/* override_set and override_clear control which
system register bits (above) to always set & clear */
extern struct dvb_frontend *lnbp21_attach(struct dvb_frontend *fe,

View file

@ -28,6 +28,8 @@
#ifndef _LNBP22_H
#define _LNBP22_H
#include <linux/kconfig.h>
/* Enable */
#define LNBP22_EN 0x10
/* Voltage selection */
@ -37,8 +39,7 @@
#include <linux/dvb/frontend.h>
#if defined(CONFIG_DVB_LNBP22) || \
(defined(CONFIG_DVB_LNBP22_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_LNBP22)
/*
* override_set and override_clear control which system register bits (above)
* to always set & clear

View file

@ -20,6 +20,7 @@
#ifndef M88RS2000_H
#define M88RS2000_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
@ -40,8 +41,7 @@ enum {
CALL_IS_READ,
};
#if defined(CONFIG_DVB_M88RS2000) || (defined(CONFIG_DVB_M88RS2000_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_M88RS2000)
extern struct dvb_frontend *m88rs2000_attach(
const struct m88rs2000_config *config, struct i2c_adapter *i2c);
#else

View file

@ -20,10 +20,24 @@
#include "dvb_frontend.h"
#include "mb86a20s.h"
#define NUM_LAYERS 3
static int debug = 1;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)");
enum mb86a20s_bandwidth {
MB86A20S_13SEG = 0,
MB86A20S_13SEG_PARTIAL = 1,
MB86A20S_1SEG = 2,
MB86A20S_3SEG = 3,
};
u8 mb86a20s_subchannel[] = {
0xb0, 0xc0, 0xd0, 0xe0,
0xf0, 0x00, 0x10, 0x20,
};
struct mb86a20s_state {
struct i2c_adapter *i2c;
const struct mb86a20s_config *config;
@ -31,7 +45,13 @@ struct mb86a20s_state {
struct dvb_frontend frontend;
u32 estimated_rate[3];
u32 if_freq;
enum mb86a20s_bandwidth bw;
bool inversion;
u32 subchannel;
u32 estimated_rate[NUM_LAYERS];
unsigned long get_strength_time;
bool need_init;
};
@ -47,35 +67,33 @@ struct regdata {
* Initialization sequence: Use whatevere default values that PV SBTVD
* does on its initialisation, obtained via USB snoop
*/
static struct regdata mb86a20s_init[] = {
static struct regdata mb86a20s_init1[] = {
{ 0x70, 0x0f },
{ 0x70, 0xff },
{ 0x08, 0x01 },
{ 0x09, 0x3e },
{ 0x50, 0xd1 }, { 0x51, 0x22 },
{ 0x39, 0x01 },
{ 0x71, 0x00 },
{ 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 },
{ 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 },
{ 0x50, 0xd1 }, { 0x51, 0x20 },
};
static struct regdata mb86a20s_init2[] = {
{ 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 },
{ 0x3b, 0x21 },
{ 0x3c, 0x3a },
{ 0x3c, 0x38 },
{ 0x01, 0x0d },
{ 0x04, 0x08 }, { 0x05, 0x05 },
{ 0x04, 0x08 }, { 0x05, 0x03 },
{ 0x04, 0x0e }, { 0x05, 0x00 },
{ 0x04, 0x0f }, { 0x05, 0x14 },
{ 0x04, 0x0b }, { 0x05, 0x8c },
{ 0x04, 0x0f }, { 0x05, 0x37 },
{ 0x04, 0x0b }, { 0x05, 0x78 },
{ 0x04, 0x00 }, { 0x05, 0x00 },
{ 0x04, 0x01 }, { 0x05, 0x07 },
{ 0x04, 0x02 }, { 0x05, 0x0f },
{ 0x04, 0x03 }, { 0x05, 0xa0 },
{ 0x04, 0x01 }, { 0x05, 0x1e },
{ 0x04, 0x02 }, { 0x05, 0x07 },
{ 0x04, 0x03 }, { 0x05, 0xd0 },
{ 0x04, 0x09 }, { 0x05, 0x00 },
{ 0x04, 0x0a }, { 0x05, 0xff },
{ 0x04, 0x27 }, { 0x05, 0x64 },
{ 0x04, 0x27 }, { 0x05, 0x00 },
{ 0x04, 0x28 }, { 0x05, 0x00 },
{ 0x04, 0x1e }, { 0x05, 0xff },
{ 0x04, 0x29 }, { 0x05, 0x0a },
{ 0x04, 0x32 }, { 0x05, 0x0a },
{ 0x04, 0x1e }, { 0x05, 0x00 },
{ 0x04, 0x29 }, { 0x05, 0x64 },
{ 0x04, 0x32 }, { 0x05, 0x02 },
{ 0x04, 0x14 }, { 0x05, 0x02 },
{ 0x04, 0x04 }, { 0x05, 0x00 },
{ 0x04, 0x05 }, { 0x05, 0x22 },
@ -142,39 +160,39 @@ static struct regdata mb86a20s_init[] = {
{ 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */
{ 0x50, 0xd6 }, { 0x51, 0x1f },
{ 0x50, 0xd2 }, { 0x51, 0x03 },
{ 0x50, 0xd7 }, { 0x51, 0x3f },
{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 },
{ 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c },
{ 0x50, 0xd7 }, { 0x51, 0xbf },
{ 0x28, 0x74 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xff },
{ 0x28, 0x46 }, { 0x29, 0x00 }, { 0x2a, 0x1a }, { 0x2b, 0x0c },
{ 0x04, 0x40 }, { 0x05, 0x00 },
{ 0x28, 0x00 }, { 0x29, 0x10 },
{ 0x28, 0x05 }, { 0x29, 0x02 },
{ 0x28, 0x00 }, { 0x2b, 0x08 },
{ 0x28, 0x05 }, { 0x2b, 0x00 },
{ 0x1c, 0x01 },
{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 },
{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d },
{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 },
{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 },
{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 },
{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 },
{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e },
{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e },
{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 },
{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 },
{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 },
{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe },
{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 },
{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee },
{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 },
{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f },
{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 },
{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 },
{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a },
{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc },
{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba },
{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 },
{ 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x1f },
{ 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x18 },
{ 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x12 },
{ 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x30 },
{ 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x37 },
{ 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 },
{ 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x09 },
{ 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x06 },
{ 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7b },
{ 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x76 },
{ 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x7d },
{ 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x08 },
{ 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0b },
{ 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
{ 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf2 },
{ 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xf3 },
{ 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x05 },
{ 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 },
{ 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f },
{ 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xef },
{ 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xd8 },
{ 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xf1 },
{ 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x3d },
{ 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x94 },
{ 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0xba },
{ 0x50, 0x1e }, { 0x51, 0x5d },
{ 0x50, 0x22 }, { 0x51, 0x00 },
{ 0x50, 0x23 }, { 0x51, 0xc8 },
@ -183,6 +201,8 @@ static struct regdata mb86a20s_init[] = {
{ 0x50, 0x26 }, { 0x51, 0x00 },
{ 0x50, 0x27 }, { 0x51, 0xc3 },
{ 0x50, 0x39 }, { 0x51, 0x02 },
{ 0xec, 0x0f },
{ 0xeb, 0x1f },
{ 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 },
{ 0xd0, 0x00 },
};
@ -308,15 +328,23 @@ static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status)
dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n",
__func__, *status, val);
return 0;
return val;
}
static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc;
unsigned rf_max, rf_min, rf;
if (state->get_strength_time &&
(!time_after(jiffies, state->get_strength_time)))
return c->strength.stat[0].uvalue;
/* Reset its value if an error happen */
c->strength.stat[0].uvalue = 0;
/* Does a binary search to get RF strength */
rf_max = 0xfff;
rf_min = 0;
@ -331,7 +359,7 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
rc = mb86a20s_writereg(state, 0x04, 0x20);
if (rc < 0)
return rc;
rc = mb86a20s_writereg(state, 0x04, rf);
rc = mb86a20s_writereg(state, 0x05, rf);
if (rc < 0)
return rc;
@ -346,15 +374,19 @@ static int mb86a20s_read_signal_strength(struct dvb_frontend *fe)
rf = (rf_max + rf_min) / 2;
/* Rescale it from 2^12 (4096) to 2^16 */
rf <<= (16 - 12);
rf = rf << (16 - 12);
if (rf)
rf |= (1 << 12) - 1;
dev_dbg(&state->i2c->dev,
"%s: signal strength = %d (%d < RF=%d < %d)\n",
__func__, rf, rf_min, rf >> 4, rf_max);
return rf;
c->strength.stat[0].uvalue = rf;
state->get_strength_time = jiffies +
msecs_to_jiffies(1000);
return 0;
}
} while (1);
return 0;
}
static int mb86a20s_get_modulation(struct mb86a20s_state *state,
@ -534,12 +566,13 @@ static u32 isdbt_rate[3][5][4] = {
};
static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
u32 modulation, u32 fec, u32 interleaving,
u32 modulation, u32 forward_error_correction,
u32 interleaving,
u32 segment)
{
struct mb86a20s_state *state = fe->demodulator_priv;
u32 rate;
int m, f, i;
int mod, fec, guard;
/*
* If modulation/fec/interleaving is not detected, the default is
@ -550,54 +583,54 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
case DQPSK:
case QPSK:
default:
m = 0;
mod = 0;
break;
case QAM_16:
m = 1;
mod = 1;
break;
case QAM_64:
m = 2;
mod = 2;
break;
}
switch (fec) {
switch (forward_error_correction) {
default:
case FEC_1_2:
case FEC_AUTO:
f = 0;
fec = 0;
break;
case FEC_2_3:
f = 1;
fec = 1;
break;
case FEC_3_4:
f = 2;
fec = 2;
break;
case FEC_5_6:
f = 3;
fec = 3;
break;
case FEC_7_8:
f = 4;
fec = 4;
break;
}
switch (interleaving) {
default:
case GUARD_INTERVAL_1_4:
i = 0;
guard = 0;
break;
case GUARD_INTERVAL_1_8:
i = 1;
guard = 1;
break;
case GUARD_INTERVAL_1_16:
i = 2;
guard = 2;
break;
case GUARD_INTERVAL_1_32:
i = 3;
guard = 3;
break;
}
/* Samples BER at BER_SAMPLING_RATE seconds */
rate = isdbt_rate[m][f][i] * segment * BER_SAMPLING_RATE;
rate = isdbt_rate[mod][fec][guard] * segment * BER_SAMPLING_RATE;
/* Avoids sampling too quickly or to overflow the register */
if (rate < 256)
@ -607,18 +640,18 @@ static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer,
dev_dbg(&state->i2c->dev,
"%s: layer %c bitrate: %d kbps; counter = %d (0x%06x)\n",
__func__, 'A' + layer, segment * isdbt_rate[m][f][i]/1000,
__func__, 'A' + layer,
segment * isdbt_rate[mod][fec][guard]/1000,
rate, rate);
state->estimated_rate[layer] = rate;
}
static int mb86a20s_get_frontend(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int i, rc;
int layer, rc;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
@ -636,43 +669,43 @@ static int mb86a20s_get_frontend(struct dvb_frontend *fe)
/* Get per-layer data */
for (i = 0; i < 3; i++) {
for (layer = 0; layer < NUM_LAYERS; layer++) {
dev_dbg(&state->i2c->dev, "%s: getting data for layer %c.\n",
__func__, 'A' + i);
__func__, 'A' + layer);
rc = mb86a20s_get_segment_count(state, i);
rc = mb86a20s_get_segment_count(state, layer);
if (rc < 0)
goto noperlayer_error;
if (rc >= 0 && rc < 14) {
c->layer[i].segment_count = rc;
c->layer[layer].segment_count = rc;
} else {
c->layer[i].segment_count = 0;
state->estimated_rate[i] = 0;
c->layer[layer].segment_count = 0;
state->estimated_rate[layer] = 0;
continue;
}
c->isdbt_layer_enabled |= 1 << i;
rc = mb86a20s_get_modulation(state, i);
c->isdbt_layer_enabled |= 1 << layer;
rc = mb86a20s_get_modulation(state, layer);
if (rc < 0)
goto noperlayer_error;
dev_dbg(&state->i2c->dev, "%s: modulation %d.\n",
__func__, rc);
c->layer[i].modulation = rc;
rc = mb86a20s_get_fec(state, i);
c->layer[layer].modulation = rc;
rc = mb86a20s_get_fec(state, layer);
if (rc < 0)
goto noperlayer_error;
dev_dbg(&state->i2c->dev, "%s: FEC %d.\n",
__func__, rc);
c->layer[i].fec = rc;
rc = mb86a20s_get_interleaving(state, i);
c->layer[layer].fec = rc;
rc = mb86a20s_get_interleaving(state, layer);
if (rc < 0)
goto noperlayer_error;
dev_dbg(&state->i2c->dev, "%s: interleaving %d.\n",
__func__, rc);
c->layer[i].interleaving = rc;
mb86a20s_layer_bitrate(fe, i, c->layer[i].modulation,
c->layer[i].fec,
c->layer[i].interleaving,
c->layer[i].segment_count);
c->layer[layer].interleaving = rc;
mb86a20s_layer_bitrate(fe, layer, c->layer[layer].modulation,
c->layer[layer].fec,
c->layer[layer].interleaving,
c->layer[layer].segment_count);
}
rc = mb86a20s_writereg(state, 0x6d, 0x84);
@ -735,7 +768,6 @@ static int mb86a20s_reset_counters(struct dvb_frontend *fe)
/* Reset the counters, if the channel changed */
if (state->last_frequency != c->frequency) {
memset(&c->strength, 0, sizeof(c->strength));
memset(&c->cnr, 0, sizeof(c->cnr));
memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error));
memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count));
@ -799,7 +831,7 @@ static int mb86a20s_get_pre_ber(struct dvb_frontend *fe,
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
if (layer >= 3)
if (layer >= NUM_LAYERS)
return -EINVAL;
/* Check if the BER measures are already available */
@ -933,7 +965,7 @@ static int mb86a20s_get_post_ber(struct dvb_frontend *fe,
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
if (layer >= 3)
if (layer >= NUM_LAYERS)
return -EINVAL;
/* Check if the BER measures are already available */
@ -1060,7 +1092,7 @@ static int mb86a20s_get_blk_error(struct dvb_frontend *fe,
u32 collect_rate;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
if (layer >= 3)
if (layer >= NUM_LAYERS)
return -EINVAL;
/* Check if the PER measures are already available */
@ -1095,7 +1127,7 @@ static int mb86a20s_get_blk_error(struct dvb_frontend *fe,
if (rc < 0)
return rc;
*error |= rc;
dev_err(&state->i2c->dev, "%s: block error for layer %c: %d.\n",
dev_dbg(&state->i2c->dev, "%s: block error for layer %c: %d.\n",
__func__, 'A' + layer, *error);
/* Read Bit Count */
@ -1386,7 +1418,7 @@ static int mb86a20s_get_main_CNR(struct dvb_frontend *fe)
return rc;
if (!(rc & 0x40)) {
dev_info(&state->i2c->dev, "%s: CNR is not available yet.\n",
dev_dbg(&state->i2c->dev, "%s: CNR is not available yet.\n",
__func__);
return -EBUSY;
}
@ -1425,7 +1457,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
struct mb86a20s_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
u32 mer, cnr;
int rc, val, i;
int rc, val, layer;
struct linear_segments *segs;
unsigned segs_len;
@ -1441,33 +1473,33 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
/* Check if data is available */
if (!(rc & 0x01)) {
dev_info(&state->i2c->dev,
dev_dbg(&state->i2c->dev,
"%s: MER measures aren't available yet.\n", __func__);
return -EBUSY;
}
/* Read all layers */
for (i = 0; i < 3; i++) {
if (!(c->isdbt_layer_enabled & (1 << i))) {
c->cnr.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
for (layer = 0; layer < NUM_LAYERS; layer++) {
if (!(c->isdbt_layer_enabled & (1 << layer))) {
c->cnr.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
continue;
}
rc = mb86a20s_writereg(state, 0x50, 0x52 + i * 3);
rc = mb86a20s_writereg(state, 0x50, 0x52 + layer * 3);
if (rc < 0)
return rc;
rc = mb86a20s_readreg(state, 0x51);
if (rc < 0)
return rc;
mer = rc << 16;
rc = mb86a20s_writereg(state, 0x50, 0x53 + i * 3);
rc = mb86a20s_writereg(state, 0x50, 0x53 + layer * 3);
if (rc < 0)
return rc;
rc = mb86a20s_readreg(state, 0x51);
if (rc < 0)
return rc;
mer |= rc << 8;
rc = mb86a20s_writereg(state, 0x50, 0x54 + i * 3);
rc = mb86a20s_writereg(state, 0x50, 0x54 + layer * 3);
if (rc < 0)
return rc;
rc = mb86a20s_readreg(state, 0x51);
@ -1475,7 +1507,7 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
return rc;
mer |= rc;
switch (c->layer[i].modulation) {
switch (c->layer[layer].modulation) {
case DQPSK:
case QPSK:
segs = cnr_qpsk_table;
@ -1493,12 +1525,12 @@ static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe)
}
cnr = interpolate_value(mer, segs, segs_len);
c->cnr.stat[1 + i].scale = FE_SCALE_DECIBEL;
c->cnr.stat[1 + i].svalue = cnr;
c->cnr.stat[1 + layer].scale = FE_SCALE_DECIBEL;
c->cnr.stat[1 + layer].svalue = cnr;
dev_dbg(&state->i2c->dev,
"%s: CNR for layer %c is %d.%03d dB (MER = %d).\n",
__func__, 'A' + i, cnr / 1000, cnr % 1000, mer);
__func__, 'A' + layer, cnr / 1000, cnr % 1000, mer);
}
@ -1526,7 +1558,7 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int i;
int layer;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
@ -1536,35 +1568,35 @@ static void mb86a20s_stats_not_ready(struct dvb_frontend *fe)
c->strength.len = 1;
/* Per-layer stats - 3 layers + global */
c->cnr.len = 4;
c->pre_bit_error.len = 4;
c->pre_bit_count.len = 4;
c->post_bit_error.len = 4;
c->post_bit_count.len = 4;
c->block_error.len = 4;
c->block_count.len = 4;
c->cnr.len = NUM_LAYERS + 1;
c->pre_bit_error.len = NUM_LAYERS + 1;
c->pre_bit_count.len = NUM_LAYERS + 1;
c->post_bit_error.len = NUM_LAYERS + 1;
c->post_bit_count.len = NUM_LAYERS + 1;
c->block_error.len = NUM_LAYERS + 1;
c->block_count.len = NUM_LAYERS + 1;
/* Signal is always available */
c->strength.stat[0].scale = FE_SCALE_RELATIVE;
c->strength.stat[0].uvalue = 0;
/* Put all of them at FE_SCALE_NOT_AVAILABLE */
for (i = 0; i < 4; i++) {
c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE;
for (layer = 0; layer < NUM_LAYERS + 1; layer++) {
c->cnr.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
c->block_error.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[layer].scale = FE_SCALE_NOT_AVAILABLE;
}
}
static int mb86a20s_get_stats(struct dvb_frontend *fe)
static int mb86a20s_get_stats(struct dvb_frontend *fe, int status_nr)
{
struct mb86a20s_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc = 0, i;
int rc = 0, layer;
u32 bit_error = 0, bit_count = 0;
u32 t_pre_bit_error = 0, t_pre_bit_count = 0;
u32 t_post_bit_error = 0, t_post_bit_count = 0;
@ -1580,90 +1612,98 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
/* Get per-layer stats */
mb86a20s_get_blk_error_layer_CNR(fe);
for (i = 0; i < 3; i++) {
if (c->isdbt_layer_enabled & (1 << i)) {
/*
* At state 7, only CNR is available
* For BER measures, state=9 is required
* FIXME: we may get MER measures with state=8
*/
if (status_nr < 9)
return 0;
for (layer = 0; layer < NUM_LAYERS; layer++) {
if (c->isdbt_layer_enabled & (1 << layer)) {
/* Layer is active and has rc segments */
active_layers++;
/* Handle BER before vterbi */
rc = mb86a20s_get_pre_ber(fe, i,
rc = mb86a20s_get_pre_ber(fe, layer,
&bit_error, &bit_count);
if (rc >= 0) {
c->pre_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[1 + i].uvalue += bit_error;
c->pre_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[1 + i].uvalue += bit_count;
c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->pre_bit_error.stat[1 + layer].uvalue += bit_error;
c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->pre_bit_count.stat[1 + layer].uvalue += bit_count;
} else if (rc != -EBUSY) {
/*
* If an I/O error happened,
* measures are now unavailable
*/
c->pre_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
c->pre_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
dev_err(&state->i2c->dev,
"%s: Can't get BER for layer %c (error %d).\n",
__func__, 'A' + i, rc);
__func__, 'A' + layer, rc);
}
if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE)
if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
pre_ber_layers++;
/* Handle BER post vterbi */
rc = mb86a20s_get_post_ber(fe, i,
rc = mb86a20s_get_post_ber(fe, layer,
&bit_error, &bit_count);
if (rc >= 0) {
c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[1 + i].uvalue += bit_error;
c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[1 + i].uvalue += bit_count;
c->post_bit_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->post_bit_error.stat[1 + layer].uvalue += bit_error;
c->post_bit_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->post_bit_count.stat[1 + layer].uvalue += bit_count;
} else if (rc != -EBUSY) {
/*
* If an I/O error happened,
* measures are now unavailable
*/
c->post_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
c->post_bit_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
dev_err(&state->i2c->dev,
"%s: Can't get BER for layer %c (error %d).\n",
__func__, 'A' + i, rc);
__func__, 'A' + layer, rc);
}
if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE)
if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
post_ber_layers++;
/* Handle Block errors for PER/UCB reports */
rc = mb86a20s_get_blk_error(fe, i,
rc = mb86a20s_get_blk_error(fe, layer,
&block_error,
&block_count);
if (rc >= 0) {
c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER;
c->block_error.stat[1 + i].uvalue += block_error;
c->block_count.stat[1 + i].scale = FE_SCALE_COUNTER;
c->block_count.stat[1 + i].uvalue += block_count;
c->block_error.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->block_error.stat[1 + layer].uvalue += block_error;
c->block_count.stat[1 + layer].scale = FE_SCALE_COUNTER;
c->block_count.stat[1 + layer].uvalue += block_count;
} else if (rc != -EBUSY) {
/*
* If an I/O error happened,
* measures are now unavailable
*/
c->block_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE;
c->block_error.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
c->block_count.stat[1 + layer].scale = FE_SCALE_NOT_AVAILABLE;
dev_err(&state->i2c->dev,
"%s: Can't get PER for layer %c (error %d).\n",
__func__, 'A' + i, rc);
__func__, 'A' + layer, rc);
}
if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE)
if (c->block_error.stat[1 + layer].scale != FE_SCALE_NOT_AVAILABLE)
per_layers++;
/* Update total preBER */
t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue;
t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue;
t_pre_bit_error += c->pre_bit_error.stat[1 + layer].uvalue;
t_pre_bit_count += c->pre_bit_count.stat[1 + layer].uvalue;
/* Update total postBER */
t_post_bit_error += c->post_bit_error.stat[1 + i].uvalue;
t_post_bit_count += c->post_bit_count.stat[1 + i].uvalue;
t_post_bit_error += c->post_bit_error.stat[1 + layer].uvalue;
t_post_bit_count += c->post_bit_count.stat[1 + layer].uvalue;
/* Update total PER */
t_block_error += c->block_error.stat[1 + i].uvalue;
t_block_count += c->block_count.stat[1 + i].uvalue;
t_block_error += c->block_error.stat[1 + layer].uvalue;
t_block_count += c->block_count.stat[1 + layer].uvalue;
}
}
@ -1737,8 +1777,10 @@ static int mb86a20s_get_stats(struct dvb_frontend *fe)
static int mb86a20s_initfe(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
u64 pll;
u32 fclk;
int rc;
u8 regD5 = 1;
u8 regD5 = 1, reg71, reg09 = 0x3a;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
@ -1746,10 +1788,78 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
fe->ops.i2c_gate_ctrl(fe, 0);
/* Initialize the frontend */
rc = mb86a20s_writeregdata(state, mb86a20s_init);
rc = mb86a20s_writeregdata(state, mb86a20s_init1);
if (rc < 0)
goto err;
if (!state->inversion)
reg09 |= 0x04;
rc = mb86a20s_writereg(state, 0x09, reg09);
if (rc < 0)
goto err;
if (!state->bw)
reg71 = 1;
else
reg71 = 0;
rc = mb86a20s_writereg(state, 0x39, reg71);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x71, state->bw);
if (rc < 0)
goto err;
if (state->subchannel) {
rc = mb86a20s_writereg(state, 0x44, state->subchannel);
if (rc < 0)
goto err;
}
fclk = state->config->fclk;
if (!fclk)
fclk = 32571428;
/* Adjust IF frequency to match tuner */
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &state->if_freq);
if (!state->if_freq)
state->if_freq = 3300000;
pll = (((u64)1) << 34) * state->if_freq;
do_div(pll, 63 * fclk);
pll = (1 << 25) - pll;
rc = mb86a20s_writereg(state, 0x28, 0x2a);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
if (rc < 0)
goto err;
dev_dbg(&state->i2c->dev, "%s: fclk=%d, IF=%d, clock reg=0x%06llx\n",
__func__, fclk, state->if_freq, (long long)pll);
/* pll = freq[Hz] * 2^24/10^6 / 16.285714286 */
pll = state->if_freq * 1677721600L;
do_div(pll, 1628571429L);
rc = mb86a20s_writereg(state, 0x28, 0x20);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x29, (pll >> 16) & 0xff);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x2a, (pll >> 8) & 0xff);
if (rc < 0)
goto err;
rc = mb86a20s_writereg(state, 0x2b, pll & 0xff);
if (rc < 0)
goto err;
dev_dbg(&state->i2c->dev, "%s: IF=%d, IF reg=0x%06llx\n",
__func__, state->if_freq, (long long)pll);
if (!state->config->is_serial) {
regD5 &= ~1;
@ -1761,6 +1871,11 @@ static int mb86a20s_initfe(struct dvb_frontend *fe)
goto err;
}
rc = mb86a20s_writeregdata(state, mb86a20s_init2);
if (rc < 0)
goto err;
err:
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@ -1779,15 +1894,34 @@ err:
static int mb86a20s_set_frontend(struct dvb_frontend *fe)
{
struct mb86a20s_state *state = fe->demodulator_priv;
int rc;
#if 0
/*
* FIXME: Properly implement the set frontend properties
*/
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
#endif
int rc, if_freq;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
if (!c->isdbt_layer_enabled)
c->isdbt_layer_enabled = 7;
if (c->isdbt_layer_enabled == 1)
state->bw = MB86A20S_1SEG;
else if (c->isdbt_partial_reception)
state->bw = MB86A20S_13SEG_PARTIAL;
else
state->bw = MB86A20S_13SEG;
if (c->inversion == INVERSION_ON)
state->inversion = true;
else
state->inversion = false;
if (!c->isdbt_sb_mode) {
state->subchannel = 0;
} else {
if (c->isdbt_sb_subchannel >= ARRAY_SIZE(mb86a20s_subchannel))
c->isdbt_sb_subchannel = 0;
state->subchannel = mb86a20s_subchannel[c->isdbt_sb_subchannel];
}
/*
* Gate should already be opened, but it doesn't hurt to
* double-check
@ -1796,6 +1930,9 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
fe->ops.i2c_gate_ctrl(fe, 1);
fe->ops.tuner_ops.set_params(fe);
if (fe->ops.tuner_ops.get_if_frequency)
fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
/*
* Make it more reliable: if, for some reason, the initial
* device initialization doesn't happen, initialize it when
@ -1805,15 +1942,22 @@ static int mb86a20s_set_frontend(struct dvb_frontend *fe)
* the agc callback logic is not called during DVB attach time,
* causing mb86a20s to not be initialized with Kworld SBTVD.
* So, this hack is needed, in order to make Kworld SBTVD to work.
*
* It is also needed to change the IF after the initial init.
*
* HACK: Always init the frontend when set_frontend is called:
* it was noticed that, on some devices, it fails to lock on a
* different channel. So, it is better to reset everything, even
* wasting some time, than to loose channel lock.
*/
if (state->need_init)
mb86a20s_initfe(fe);
mb86a20s_initfe(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 0);
rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception);
mb86a20s_reset_counters(fe);
mb86a20s_stats_not_ready(fe);
if (fe->ops.i2c_gate_ctrl)
fe->ops.i2c_gate_ctrl(fe, 1);
@ -1825,8 +1969,7 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
fe_status_t *status)
{
struct mb86a20s_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int rc;
int rc, status_nr;
dev_dbg(&state->i2c->dev, "%s called.\n", __func__);
@ -1834,12 +1977,12 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
fe->ops.i2c_gate_ctrl(fe, 0);
/* Get lock */
rc = mb86a20s_read_status(fe, status);
if (!(*status & FE_HAS_LOCK)) {
status_nr = mb86a20s_read_status(fe, status);
if (status_nr < 7) {
mb86a20s_stats_not_ready(fe);
mb86a20s_reset_frontend_cache(fe);
}
if (rc < 0) {
if (status_nr < 0) {
dev_err(&state->i2c->dev,
"%s: Can't read frontend lock status\n", __func__);
goto error;
@ -1856,10 +1999,8 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
rc = 0; /* Status is OK */
goto error;
}
/* Fill signal strength */
c->strength.stat[0].uvalue = rc;
if (*status & FE_HAS_LOCK) {
if (status_nr >= 7) {
/* Get TMCC info*/
rc = mb86a20s_get_frontend(fe);
if (rc < 0) {
@ -1870,7 +2011,7 @@ static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe,
}
/* Get statistics */
rc = mb86a20s_get_stats(fe);
rc = mb86a20s_get_stats(fe, status_nr);
if (rc < 0 && rc != -EBUSY) {
dev_err(&state->i2c->dev,
"%s: Can't get FE statistics.\n", __func__);
@ -1994,7 +2135,7 @@ static struct dvb_frontend_ops mb86a20s_ops = {
/* Use dib8000 values per default */
.info = {
.name = "Fujitsu mb86A20s",
.caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER |
.caps = FE_CAN_RECOVER |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |

View file

@ -16,21 +16,25 @@
#ifndef MB86A20S_H
#define MB86A20S_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
/**
* struct mb86a20s_config - Define the per-device attributes of the frontend
*
* @fclk: Clock frequency. If zero, assumes the default
* (32.57142 Mhz)
* @demod_address: the demodulator's i2c address
* @is_serial: if true, TS is serial. Otherwise, TS is parallel
*/
struct mb86a20s_config {
u8 demod_address;
bool is_serial;
u32 fclk;
u8 demod_address;
bool is_serial;
};
#if defined(CONFIG_DVB_MB86A20S) || (defined(CONFIG_DVB_MB86A20S_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_MB86A20S)
extern struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config,
struct i2c_adapter *i2c);
extern struct i2c_adapter *mb86a20s_get_tuner_i2c_adapter(struct dvb_frontend *);

View file

@ -21,6 +21,7 @@
#ifndef RTL2830_H
#define RTL2830_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct rtl2830_config {
@ -59,8 +60,7 @@ struct rtl2830_config {
u8 agc_targ_val;
};
#if defined(CONFIG_DVB_RTL2830) || \
(defined(CONFIG_DVB_RTL2830_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_RTL2830)
extern struct dvb_frontend *rtl2830_attach(
const struct rtl2830_config *config,
struct i2c_adapter *i2c

View file

@ -380,13 +380,41 @@ err:
return ret;
}
static int rtl2832_set_if(struct dvb_frontend *fe, u32 if_freq)
{
struct rtl2832_priv *priv = fe->demodulator_priv;
int ret;
u64 pset_iffreq;
u8 en_bbin = (if_freq == 0 ? 0x1 : 0x0);
/*
* PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
* / CrystalFreqHz)
*/
pset_iffreq = if_freq % priv->cfg.xtal;
pset_iffreq *= 0x400000;
pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
pset_iffreq = -pset_iffreq;
pset_iffreq = pset_iffreq & 0x3fffff;
dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d pset_iffreq=%08x\n",
__func__, if_freq, (unsigned)pset_iffreq);
ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
if (ret)
return ret;
ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
return (ret);
}
static int rtl2832_init(struct dvb_frontend *fe)
{
struct rtl2832_priv *priv = fe->demodulator_priv;
int i, ret, len;
u8 en_bbin;
u64 pset_iffreq;
const struct rtl2832_reg_value *init;
int i, ret, len;
/* initialization values for the demodulator registers */
struct rtl2832_reg_value rtl2832_initial_regs[] = {
@ -432,22 +460,10 @@ static int rtl2832_init(struct dvb_frontend *fe)
{DVBT_TR_THD_SET2, 0x6},
{DVBT_TRK_KC_I2, 0x5},
{DVBT_CR_THD_SET2, 0x1},
{DVBT_SPEC_INV, 0x0},
};
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0);
/*
* PSET_IFFREQ = - floor((IfFreqHz % CrystalFreqHz) * pow(2, 22)
* / CrystalFreqHz)
*/
pset_iffreq = priv->cfg.if_dvbt % priv->cfg.xtal;
pset_iffreq *= 0x400000;
pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
pset_iffreq = pset_iffreq & 0x3fffff;
for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
rtl2832_initial_regs[i].value);
@ -472,6 +488,10 @@ static int rtl2832_init(struct dvb_frontend *fe)
len = ARRAY_SIZE(rtl2832_tuner_init_e4000);
init = rtl2832_tuner_init_e4000;
break;
case RTL2832_TUNER_R820T:
len = ARRAY_SIZE(rtl2832_tuner_init_r820t);
init = rtl2832_tuner_init_r820t;
break;
default:
ret = -EINVAL;
goto err;
@ -483,14 +503,26 @@ static int rtl2832_init(struct dvb_frontend *fe)
goto err;
}
/* if frequency settings */
ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
if (!fe->ops.tuner_ops.get_if_frequency) {
ret = rtl2832_set_if(fe, priv->cfg.if_dvbt);
if (ret)
goto err;
}
ret = rtl2832_wr_demod_reg(priv, DVBT_PSET_IFFREQ, pset_iffreq);
if (ret)
goto err;
/*
* r820t NIM code does a software reset here at the demod -
* may not be needed, as there's already a software reset at set_params()
*/
#if 1
/* soft reset */
ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
if (ret)
goto err;
ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
if (ret)
goto err;
#endif
priv->sleeping = false;
@ -564,6 +596,19 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
/* If the frontend has get_if_frequency(), use it */
if (fe->ops.tuner_ops.get_if_frequency) {
u32 if_freq;
ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_freq);
if (ret)
goto err;
ret = rtl2832_set_if(fe, if_freq);
if (ret)
goto err;
}
switch (c->bandwidth_hz) {
case 6000000:
i = 0;

View file

@ -21,6 +21,7 @@
#ifndef RTL2832_H
#define RTL2832_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct rtl2832_config {
@ -51,11 +52,11 @@ struct rtl2832_config {
#define RTL2832_TUNER_FC0012 0x26
#define RTL2832_TUNER_E4000 0x27
#define RTL2832_TUNER_FC0013 0x29
#define RTL2832_TUNER_R820T 0x2a
u8 tuner;
};
#if defined(CONFIG_DVB_RTL2832) || \
(defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_RTL2832)
extern struct dvb_frontend *rtl2832_attach(
const struct rtl2832_config *cfg,
struct i2c_adapter *i2c

View file

@ -267,6 +267,7 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = {
{DVBT_OPT_ADC_IQ, 0x1},
{DVBT_AD_AVI, 0x0},
{DVBT_AD_AVQ, 0x0},
{DVBT_SPEC_INV, 0x0},
};
static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = {
@ -300,6 +301,7 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = {
{DVBT_GI_PGA_STATE, 0x0},
{DVBT_EN_AGC_PGA, 0x1},
{DVBT_IF_AGC_MAN, 0x0},
{DVBT_SPEC_INV, 0x0},
};
static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = {
@ -337,6 +339,32 @@ static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = {
{DVBT_REG_MONSEL, 0x1},
{DVBT_REG_MON, 0x1},
{DVBT_REG_4MSEL, 0x0},
{DVBT_SPEC_INV, 0x0},
};
static const struct rtl2832_reg_value rtl2832_tuner_init_r820t[] = {
{DVBT_DAGC_TRG_VAL, 0x39},
{DVBT_AGC_TARG_VAL_0, 0x0},
{DVBT_AGC_TARG_VAL_8_1, 0x40},
{DVBT_AAGC_LOOP_GAIN, 0x16},
{DVBT_LOOP_GAIN2_3_0, 0x8},
{DVBT_LOOP_GAIN2_4, 0x1},
{DVBT_LOOP_GAIN3, 0x18},
{DVBT_VTOP1, 0x35},
{DVBT_VTOP2, 0x21},
{DVBT_VTOP3, 0x21},
{DVBT_KRF1, 0x0},
{DVBT_KRF2, 0x40},
{DVBT_KRF3, 0x10},
{DVBT_KRF4, 0x10},
{DVBT_IF_AGC_MIN, 0x80},
{DVBT_IF_AGC_MAX, 0x7f},
{DVBT_RF_AGC_MIN, 0x80},
{DVBT_RF_AGC_MAX, 0x7f},
{DVBT_POLAR_RF_AGC, 0x0},
{DVBT_POLAR_IF_AGC, 0x0},
{DVBT_AD7_SETTING, 0xe9f4},
{DVBT_SPEC_INV, 0x1},
};
#endif /* RTL2832_PRIV_H */

View file

@ -22,6 +22,7 @@
#ifndef __S5H1409_H__
#define __S5H1409_H__
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct s5h1409_config {
@ -66,8 +67,7 @@ struct s5h1409_config {
u8 hvr1600_opt;
};
#if defined(CONFIG_DVB_S5H1409) || (defined(CONFIG_DVB_S5H1409_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_S5H1409)
extern struct dvb_frontend *s5h1409_attach(const struct s5h1409_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -22,6 +22,7 @@
#ifndef __S5H1411_H__
#define __S5H1411_H__
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#define S5H1411_I2C_TOP_ADDR (0x32 >> 1)
@ -68,8 +69,7 @@ struct s5h1411_config {
u8 status_mode;
};
#if defined(CONFIG_DVB_S5H1411) || \
(defined(CONFIG_DVB_S5H1411_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_S5H1411)
extern struct dvb_frontend *s5h1411_attach(const struct s5h1411_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -22,6 +22,7 @@
#ifndef __S5H1432_H__
#define __S5H1432_H__
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#define S5H1432_I2C_TOP_ADDR (0x02 >> 1)
@ -74,8 +75,7 @@ struct s5h1432_config {
u8 status_mode;
};
#if defined(CONFIG_DVB_S5H1432) || \
(defined(CONFIG_DVB_S5H1432_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_S5H1432)
extern struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -17,6 +17,7 @@
#ifndef S921_H
#define S921_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct s921_config {
@ -24,8 +25,7 @@ struct s921_config {
u8 demod_address;
};
#if defined(CONFIG_DVB_S921) || (defined(CONFIG_DVB_S921_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_S921)
extern struct dvb_frontend *s921_attach(const struct s921_config *config,
struct i2c_adapter *i2c);
extern struct i2c_adapter *s921_get_tuner_i2c_adapter(struct dvb_frontend *);

View file

@ -1,6 +1,7 @@
#ifndef SI21XX_H
#define SI21XX_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
@ -12,8 +13,7 @@ struct si21xx_config {
int min_delay_ms;
};
#if defined(CONFIG_DVB_SI21XX) || \
(defined(CONFIG_DVB_SI21XX_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_SI21XX)
extern struct dvb_frontend *si21xx_attach(const struct si21xx_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -23,6 +23,7 @@
#ifndef __DVB_STB6000_H__
#define __DVB_STB6000_H__
#include <linux/kconfig.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
@ -34,8 +35,7 @@
* @param i2c i2c adapter to use.
* @return FE pointer on success, NULL on failure.
*/
#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_STB6000)
extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
struct i2c_adapter *i2c);
#else

View file

@ -27,6 +27,7 @@
#ifndef STV0288_H
#define STV0288_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
@ -42,8 +43,7 @@ struct stv0288_config {
int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
};
#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_STV0288)
extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
struct i2c_adapter *i2c);
#else

View file

@ -26,6 +26,7 @@
#ifndef STV0367_H
#define STV0367_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
@ -38,8 +39,7 @@ struct stv0367_config {
int clk_pol;
};
#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_STV0367)
extern struct
dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
struct i2c_adapter *i2c);

View file

@ -26,6 +26,7 @@
#ifndef STV0900_H
#define STV0900_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include "dvb_frontend.h"
@ -57,8 +58,7 @@ struct stv0900_config {
void (*set_lock_led)(struct dvb_frontend *fe, int offon);
};
#if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_STV0900)
extern struct dvb_frontend *stv0900_attach(const struct stv0900_config *config,
struct i2c_adapter *i2c, int demod);
#else

View file

@ -3906,12 +3906,12 @@ static int stv090x_sleep(struct dvb_frontend *fe)
reg = stv090x_read_reg(state, STV090x_TSTTNR1);
STV090x_SETFIELD(reg, ADC1_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR1, reg) < 0)
goto err;
goto err_unlock;
/* power off DiSEqC 1 */
reg = stv090x_read_reg(state, STV090x_TSTTNR2);
STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
goto err;
goto err_unlock;
/* check whether path 2 is already sleeping, that is when
ADC2 is off */
@ -3930,7 +3930,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
goto err;
goto err_unlock;
reg = stv090x_read_reg(state, STV090x_STOPCLK2);
/* sampling 1 clock */
STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
@ -3941,7 +3941,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
goto err;
goto err_unlock;
break;
case STV090x_DEMODULATOR_1:
@ -3949,12 +3949,12 @@ static int stv090x_sleep(struct dvb_frontend *fe)
reg = stv090x_read_reg(state, STV090x_TSTTNR3);
STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
goto err;
goto err_unlock;
/* power off DiSEqC 2 */
reg = stv090x_read_reg(state, STV090x_TSTTNR4);
STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
goto err;
goto err_unlock;
/* check whether path 1 is already sleeping, that is when
ADC1 is off */
@ -3973,7 +3973,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
goto err;
goto err_unlock;
reg = stv090x_read_reg(state, STV090x_STOPCLK2);
/* sampling 2 clock */
STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
@ -3984,7 +3984,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
if (full_standby)
STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
goto err;
goto err_unlock;
break;
default:
@ -3997,7 +3997,7 @@ static int stv090x_sleep(struct dvb_frontend *fe)
reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
goto err;
goto err_unlock;
}
mutex_unlock(&state->internal->demod_lock);
@ -4005,8 +4005,10 @@ static int stv090x_sleep(struct dvb_frontend *fe)
err_gateoff:
stv090x_i2c_gate_ctrl(state, 0);
err:
goto err;
err_unlock:
mutex_unlock(&state->internal->demod_lock);
err:
dprintk(FE_ERROR, 1, "I/O error");
return -1;
}

View file

@ -25,6 +25,7 @@
#ifndef __DVB_STV6110_H__
#define __DVB_STV6110_H__
#include <linux/kconfig.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
@ -45,8 +46,7 @@ struct stv6110_config {
u8 clk_div; /* divisor value for the output clock */
};
#if defined(CONFIG_DVB_STV6110) || (defined(CONFIG_DVB_STV6110_MODULE) \
&& defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_STV6110)
extern struct dvb_frontend *stv6110_attach(struct dvb_frontend *fe,
const struct stv6110_config *config,
struct i2c_adapter *i2c);

View file

@ -22,6 +22,7 @@
#ifndef TDA10048_H
#define TDA10048_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
#include <linux/firmware.h>
@ -72,8 +73,7 @@ struct tda10048_config {
u8 pll_n;
};
#if defined(CONFIG_DVB_TDA10048) || \
(defined(CONFIG_DVB_TDA10048_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_TDA10048)
extern struct dvb_frontend *tda10048_attach(
const struct tda10048_config *config,
struct i2c_adapter *i2c);

View file

@ -21,6 +21,7 @@
#ifndef TDA10071_H
#define TDA10071_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct tda10071_config {
@ -71,8 +72,7 @@ struct tda10071_config {
};
#if defined(CONFIG_DVB_TDA10071) || \
(defined(CONFIG_DVB_TDA10071_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_TDA10071)
extern struct dvb_frontend *tda10071_attach(
const struct tda10071_config *config, struct i2c_adapter *i2c);
#else

View file

@ -1,7 +1,9 @@
#ifndef _TDA18271C2DD_H_
#define _TDA18271C2DD_H_
#if defined(CONFIG_DVB_TDA18271C2DD) || (defined(CONFIG_DVB_TDA18271C2DD_MODULE) \
&& defined(MODULE))
#include <linux/kconfig.h>
#if IS_ENABLED(CONFIG_DVB_TDA18271C2DD)
struct dvb_frontend *tda18271c2dd_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c, u8 adr);
#else

View file

@ -22,6 +22,7 @@
#ifndef TS2020_H
#define TS2020_H
#include <linux/kconfig.h>
#include <linux/dvb/frontend.h>
struct ts2020_config {
@ -29,8 +30,7 @@ struct ts2020_config {
u8 clk_out_div;
};
#if defined(CONFIG_DVB_TS2020) || \
(defined(CONFIG_DVB_TS2020_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_TS2020)
extern struct dvb_frontend *ts2020_attach(
struct dvb_frontend *fe,

View file

@ -21,6 +21,7 @@
#ifndef DVB_ZL10036_H
#define DVB_ZL10036_H
#include <linux/kconfig.h>
#include <linux/i2c.h>
#include "dvb_frontend.h"
@ -37,8 +38,7 @@ struct zl10036_config {
int rf_loop_enable;
};
#if defined(CONFIG_DVB_ZL10036) || \
(defined(CONFIG_DVB_ZL10036_MODULE) && defined(MODULE))
#if IS_ENABLED(CONFIG_DVB_ZL10036)
extern struct dvb_frontend *zl10036_attach(struct dvb_frontend *fe,
const struct zl10036_config *config, struct i2c_adapter *i2c);
#else

View file

@ -22,8 +22,9 @@
#ifndef ZL10039_H
#define ZL10039_H
#if defined(CONFIG_DVB_ZL10039) || (defined(CONFIG_DVB_ZL10039_MODULE) \
&& defined(MODULE))
#include <linux/kconfig.h>
#if IS_ENABLED(CONFIG_DVB_ZL10039)
struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe,
u8 i2c_addr,
struct i2c_adapter *i2c);

View file

@ -71,11 +71,11 @@ int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed)
if (dvbdmxfeed->type == DMX_TYPE_TS) {
switch (dvbdmxfeed->pes_type) {
case DMX_TS_PES_VIDEO:
case DMX_TS_PES_AUDIO:
case DMX_TS_PES_TELETEXT:
case DMX_TS_PES_PCR:
case DMX_TS_PES_OTHER:
case DMX_PES_VIDEO:
case DMX_PES_AUDIO:
case DMX_PES_TELETEXT:
case DMX_PES_PCR:
case DMX_PES_OTHER:
c = alloc_channel(fdtv);
break;
default:
@ -132,7 +132,7 @@ int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
(demux->dmx.frontend->source != DMX_MEMORY_FE))) {
if (dvbdmxfeed->ts_type & TS_DECODER) {
if (dvbdmxfeed->pes_type >= DMX_TS_PES_OTHER ||
if (dvbdmxfeed->pes_type >= DMX_PES_OTHER ||
!demux->pesfilter[dvbdmxfeed->pes_type])
return -EINVAL;
@ -141,7 +141,7 @@ int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
}
if (!(dvbdmxfeed->ts_type & TS_DECODER &&
dvbdmxfeed->pes_type < DMX_TS_PES_OTHER))
dvbdmxfeed->pes_type < DMX_PES_OTHER))
return 0;
}

View file

@ -112,6 +112,15 @@ config VIDEO_TLV320AIC23B
To compile this driver as a module, choose M here: the
module will be called tlv320aic23b.
config VIDEO_UDA1342
tristate "Philips UDA1342 audio codec"
depends on VIDEO_V4L2 && I2C
---help---
Support for the Philips UDA1342 audio codec.
To compile this driver as a module, choose M here: the
module will be called uda1342.
config VIDEO_WM8775
tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
depends on VIDEO_V4L2 && I2C
@ -133,7 +142,7 @@ config VIDEO_WM8739
module will be called wm8739.
config VIDEO_VP27SMPX
tristate "Panasonic VP27s internal MPX"
tristate "Panasonic VP27's internal MPX"
depends on VIDEO_V4L2 && I2C
---help---
Support for the internal MPX of the Panasonic VP27s tuner.
@ -141,6 +150,15 @@ config VIDEO_VP27SMPX
To compile this driver as a module, choose M here: the
module will be called vp27smpx.
config VIDEO_SONY_BTF_MPX
tristate "Sony BTF's internal MPX"
depends on VIDEO_V4L2 && I2C
help
Support for the internal MPX of the Sony BTF-PG472Z tuner.
To compile this driver as a module, choose M here: the
module will be called sony-btf-mpx.
comment "RDS decoders"
config VIDEO_SAA6588
@ -283,6 +301,35 @@ config VIDEO_TVP7002
To compile this driver as a module, choose M here: the
module will be called tvp7002.
config VIDEO_TW2804
tristate "Techwell TW2804 multiple video decoder"
depends on VIDEO_V4L2 && I2C
---help---
Support for the Techwell tw2804 multiple video decoder.
To compile this driver as a module, choose M here: the
module will be called tw2804.
config VIDEO_TW9903
tristate "Techwell TW9903 video decoder"
depends on VIDEO_V4L2 && I2C
---help---
Support for the Techwell tw9903 multi-standard video decoder
with high quality down scaler.
To compile this driver as a module, choose M here: the
module will be called tw9903.
config VIDEO_TW9906
tristate "Techwell TW9906 video decoder"
depends on VIDEO_V4L2 && I2C
---help---
Support for the Techwell tw9906 enhanced multi-standard comb filter
video decoder with YCbCr input support.
To compile this driver as a module, choose M here: the
module will be called tw9906.
config VIDEO_VPX3220
tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
depends on VIDEO_V4L2 && I2C
@ -386,6 +433,17 @@ config VIDEO_APTINA_PLL
config VIDEO_SMIAPP_PLL
tristate
config VIDEO_OV7640
tristate "OmniVision OV7640 sensor support"
depends on I2C && VIDEO_V4L2
depends on MEDIA_CAMERA_SUPPORT
---help---
This is a Video4Linux2 sensor-level driver for the OmniVision
OV7640 camera.
To compile this driver as a module, choose M here: the
module will be called ov7640.
config VIDEO_OV7670
tristate "OmniVision OV7670 sensor support"
depends on I2C && VIDEO_V4L2
@ -501,8 +559,8 @@ config VIDEO_S5C73M3
tristate "Samsung S5C73M3 sensor support"
depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
---help---
This is a V4L2 sensor-level driver for Samsung S5C73M3
8 Mpixel camera.
This is a V4L2 sensor-level driver for Samsung S5C73M3
8 Mpixel camera.
comment "Flash devices"
@ -550,10 +608,10 @@ config VIDEO_UPD64083
comment "Miscelaneous helper chips"
config VIDEO_THS7303
tristate "THS7303 Video Amplifier"
depends on I2C
tristate "THS7303/53 Video Amplifier"
depends on VIDEO_V4L2 && I2C
help
Support for TI THS7303 video amplifier
Support for TI THS7303/53 video amplifier
To compile this driver as a module, choose M here: the
module will be called ths7303.

View file

@ -37,16 +37,22 @@ obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
obj-$(CONFIG_VIDEO_TW2804) += tw2804.o
obj-$(CONFIG_VIDEO_TW9903) += tw9903.o
obj-$(CONFIG_VIDEO_TW9906) += tw9906.o
obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
obj-$(CONFIG_VIDEO_M52790) += m52790.o
obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
obj-$(CONFIG_VIDEO_UDA1342) += uda1342.o
obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
obj-$(CONFIG_VIDEO_SONY_BTF_MPX) += sony-btf-mpx.o
obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
obj-$(CONFIG_VIDEO_OV7640) += ov7640.o
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o

View file

@ -354,7 +354,7 @@ static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *
return 0;
}
static int ad9389b_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
static int ad9389b_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_register *reg)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);

Some files were not shown because too many files have changed in this diff Show more