Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
config DVB_CXD2880
tristate "Sony CXD2880 DVB-T2/T tuner + demodulator"
depends on DVB_CORE && SPI
default m if !MEDIA_SUBDRV_AUTOSELECT
help
Say Y when you want to support this frontend.
@@ -0,0 +1,16 @@
# SPDX-License-Identifier: GPL-2.0
cxd2880-objs := cxd2880_common.o \
cxd2880_devio_spi.o \
cxd2880_integ.o \
cxd2880_io.o \
cxd2880_spi_device.o \
cxd2880_tnrdmd.o \
cxd2880_tnrdmd_dvbt2.o \
cxd2880_tnrdmd_dvbt2_mon.o \
cxd2880_tnrdmd_dvbt.o \
cxd2880_tnrdmd_dvbt_mon.o\
cxd2880_tnrdmd_mon.o\
cxd2880_top.o
obj-$(CONFIG_DVB_CXD2880) += cxd2880.o
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver public definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_H
#define CXD2880_H
struct cxd2880_config {
struct spi_device *spi;
struct mutex *spi_mutex; /* For SPI access exclusive control */
};
#if IS_REACHABLE(CONFIG_DVB_CXD2880)
extern struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe,
struct cxd2880_config *cfg);
#else
static inline struct dvb_frontend *cxd2880_attach(struct dvb_frontend *fe,
struct cxd2880_config *cfg)
{
pr_warn("%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif /* CONFIG_DVB_CXD2880 */
#endif /* CXD2880_H */
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_common.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_common.h"
int cxd2880_convert2s_complement(u32 value, u32 bitlen)
{
if (!bitlen || bitlen >= 32)
return (int)value;
if (value & (u32)(1 << (bitlen - 1)))
return (int)(GENMASK(31, bitlen) | value);
else
return (int)(GENMASK(bitlen - 1, 0) & value);
}
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_common.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver common definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_COMMON_H
#define CXD2880_COMMON_H
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <linux/bits.h>
#include <linux/string.h>
int cxd2880_convert2s_complement(u32 value, u32 bitlen);
#endif
@@ -0,0 +1,129 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_devio_spi.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* I/O interface via SPI
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_devio_spi.h"
#define BURST_WRITE_MAX 128
static int cxd2880_io_spi_read_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 *data,
u32 size)
{
int ret = 0;
struct cxd2880_spi *spi = NULL;
u8 send_data[6];
u8 *read_data_top = data;
if (!io || !io->if_object || !data)
return -EINVAL;
if (sub_address + size > 0x100)
return -EINVAL;
spi = io->if_object;
if (tgt == CXD2880_IO_TGT_SYS)
send_data[0] = 0x0b;
else
send_data[0] = 0x0a;
send_data[3] = 0;
send_data[4] = 0;
send_data[5] = 0;
while (size > 0) {
send_data[1] = sub_address;
if (size > 255)
send_data[2] = 255;
else
send_data[2] = size;
ret =
spi->write_read(spi, send_data, sizeof(send_data),
read_data_top, send_data[2]);
if (ret)
return ret;
sub_address += send_data[2];
read_data_top += send_data[2];
size -= send_data[2];
}
return ret;
}
static int cxd2880_io_spi_write_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address,
const u8 *data, u32 size)
{
int ret = 0;
struct cxd2880_spi *spi = NULL;
u8 send_data[BURST_WRITE_MAX + 4];
const u8 *write_data_top = data;
if (!io || !io->if_object || !data)
return -EINVAL;
if (size > BURST_WRITE_MAX)
return -EINVAL;
if (sub_address + size > 0x100)
return -EINVAL;
spi = io->if_object;
if (tgt == CXD2880_IO_TGT_SYS)
send_data[0] = 0x0f;
else
send_data[0] = 0x0e;
while (size > 0) {
send_data[1] = sub_address;
if (size > 255)
send_data[2] = 255;
else
send_data[2] = size;
memcpy(&send_data[3], write_data_top, send_data[2]);
if (tgt == CXD2880_IO_TGT_SYS) {
send_data[3 + send_data[2]] = 0x00;
ret = spi->write(spi, send_data, send_data[2] + 4);
} else {
ret = spi->write(spi, send_data, send_data[2] + 3);
}
if (ret)
return ret;
sub_address += send_data[2];
write_data_top += send_data[2];
size -= send_data[2];
}
return ret;
}
int cxd2880_io_spi_create(struct cxd2880_io *io,
struct cxd2880_spi *spi, u8 slave_select)
{
if (!io || !spi)
return -EINVAL;
io->read_regs = cxd2880_io_spi_read_reg;
io->write_regs = cxd2880_io_spi_write_reg;
io->write_reg = cxd2880_io_common_write_one_reg;
io->if_object = spi;
io->i2c_address_sys = 0;
io->i2c_address_demod = 0;
io->slave_select = slave_select;
return 0;
}
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_devio_spi.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* I/O interface via SPI
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DEVIO_SPI_H
#define CXD2880_DEVIO_SPI_H
#include "cxd2880_common.h"
#include "cxd2880_io.h"
#include "cxd2880_spi.h"
#include "cxd2880_tnrdmd.h"
int cxd2880_io_spi_create(struct cxd2880_io *io,
struct cxd2880_spi *spi,
u8 slave_select);
#endif
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_dtv.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DTV related definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DTV_H
#define CXD2880_DTV_H
enum cxd2880_dtv_sys {
CXD2880_DTV_SYS_UNKNOWN,
CXD2880_DTV_SYS_DVBT,
CXD2880_DTV_SYS_DVBT2,
CXD2880_DTV_SYS_ANY
};
enum cxd2880_dtv_bandwidth {
CXD2880_DTV_BW_UNKNOWN = 0,
CXD2880_DTV_BW_1_7_MHZ = 1,
CXD2880_DTV_BW_5_MHZ = 5,
CXD2880_DTV_BW_6_MHZ = 6,
CXD2880_DTV_BW_7_MHZ = 7,
CXD2880_DTV_BW_8_MHZ = 8
};
#endif
@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_dvbt.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T related definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DVBT_H
#define CXD2880_DVBT_H
#include "cxd2880_common.h"
enum cxd2880_dvbt_constellation {
CXD2880_DVBT_CONSTELLATION_QPSK,
CXD2880_DVBT_CONSTELLATION_16QAM,
CXD2880_DVBT_CONSTELLATION_64QAM,
CXD2880_DVBT_CONSTELLATION_RESERVED_3
};
enum cxd2880_dvbt_hierarchy {
CXD2880_DVBT_HIERARCHY_NON,
CXD2880_DVBT_HIERARCHY_1,
CXD2880_DVBT_HIERARCHY_2,
CXD2880_DVBT_HIERARCHY_4
};
enum cxd2880_dvbt_coderate {
CXD2880_DVBT_CODERATE_1_2,
CXD2880_DVBT_CODERATE_2_3,
CXD2880_DVBT_CODERATE_3_4,
CXD2880_DVBT_CODERATE_5_6,
CXD2880_DVBT_CODERATE_7_8,
CXD2880_DVBT_CODERATE_RESERVED_5,
CXD2880_DVBT_CODERATE_RESERVED_6,
CXD2880_DVBT_CODERATE_RESERVED_7
};
enum cxd2880_dvbt_guard {
CXD2880_DVBT_GUARD_1_32,
CXD2880_DVBT_GUARD_1_16,
CXD2880_DVBT_GUARD_1_8,
CXD2880_DVBT_GUARD_1_4
};
enum cxd2880_dvbt_mode {
CXD2880_DVBT_MODE_2K,
CXD2880_DVBT_MODE_8K,
CXD2880_DVBT_MODE_RESERVED_2,
CXD2880_DVBT_MODE_RESERVED_3
};
enum cxd2880_dvbt_profile {
CXD2880_DVBT_PROFILE_HP = 0,
CXD2880_DVBT_PROFILE_LP
};
struct cxd2880_dvbt_tpsinfo {
enum cxd2880_dvbt_constellation constellation;
enum cxd2880_dvbt_hierarchy hierarchy;
enum cxd2880_dvbt_coderate rate_hp;
enum cxd2880_dvbt_coderate rate_lp;
enum cxd2880_dvbt_guard guard;
enum cxd2880_dvbt_mode mode;
u8 fnum;
u8 length_indicator;
u16 cell_id;
u8 cell_id_ok;
u8 reserved_even;
u8 reserved_odd;
};
#endif
@@ -0,0 +1,385 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_dvbt2.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T2 related definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_DVBT2_H
#define CXD2880_DVBT2_H
#include "cxd2880_common.h"
enum cxd2880_dvbt2_profile {
CXD2880_DVBT2_PROFILE_BASE,
CXD2880_DVBT2_PROFILE_LITE,
CXD2880_DVBT2_PROFILE_ANY
};
enum cxd2880_dvbt2_version {
CXD2880_DVBT2_V111,
CXD2880_DVBT2_V121,
CXD2880_DVBT2_V131
};
enum cxd2880_dvbt2_s1 {
CXD2880_DVBT2_S1_BASE_SISO = 0x00,
CXD2880_DVBT2_S1_BASE_MISO = 0x01,
CXD2880_DVBT2_S1_NON_DVBT2 = 0x02,
CXD2880_DVBT2_S1_LITE_SISO = 0x03,
CXD2880_DVBT2_S1_LITE_MISO = 0x04,
CXD2880_DVBT2_S1_RSVD3 = 0x05,
CXD2880_DVBT2_S1_RSVD4 = 0x06,
CXD2880_DVBT2_S1_RSVD5 = 0x07,
CXD2880_DVBT2_S1_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_base_s2 {
CXD2880_DVBT2_BASE_S2_M2K_G_ANY = 0x00,
CXD2880_DVBT2_BASE_S2_M8K_G_DVBT = 0x01,
CXD2880_DVBT2_BASE_S2_M4K_G_ANY = 0x02,
CXD2880_DVBT2_BASE_S2_M1K_G_ANY = 0x03,
CXD2880_DVBT2_BASE_S2_M16K_G_ANY = 0x04,
CXD2880_DVBT2_BASE_S2_M32K_G_DVBT = 0x05,
CXD2880_DVBT2_BASE_S2_M8K_G_DVBT2 = 0x06,
CXD2880_DVBT2_BASE_S2_M32K_G_DVBT2 = 0x07,
CXD2880_DVBT2_BASE_S2_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_lite_s2 {
CXD2880_DVBT2_LITE_S2_M2K_G_ANY = 0x00,
CXD2880_DVBT2_LITE_S2_M8K_G_DVBT = 0x01,
CXD2880_DVBT2_LITE_S2_M4K_G_ANY = 0x02,
CXD2880_DVBT2_LITE_S2_M16K_G_DVBT2 = 0x03,
CXD2880_DVBT2_LITE_S2_M16K_G_DVBT = 0x04,
CXD2880_DVBT2_LITE_S2_RSVD1 = 0x05,
CXD2880_DVBT2_LITE_S2_M8K_G_DVBT2 = 0x06,
CXD2880_DVBT2_LITE_S2_RSVD2 = 0x07,
CXD2880_DVBT2_LITE_S2_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_guard {
CXD2880_DVBT2_G1_32 = 0x00,
CXD2880_DVBT2_G1_16 = 0x01,
CXD2880_DVBT2_G1_8 = 0x02,
CXD2880_DVBT2_G1_4 = 0x03,
CXD2880_DVBT2_G1_128 = 0x04,
CXD2880_DVBT2_G19_128 = 0x05,
CXD2880_DVBT2_G19_256 = 0x06,
CXD2880_DVBT2_G_RSVD1 = 0x07,
CXD2880_DVBT2_G_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_mode {
CXD2880_DVBT2_M2K = 0x00,
CXD2880_DVBT2_M8K = 0x01,
CXD2880_DVBT2_M4K = 0x02,
CXD2880_DVBT2_M1K = 0x03,
CXD2880_DVBT2_M16K = 0x04,
CXD2880_DVBT2_M32K = 0x05,
CXD2880_DVBT2_M_RSVD1 = 0x06,
CXD2880_DVBT2_M_RSVD2 = 0x07
};
enum cxd2880_dvbt2_bw {
CXD2880_DVBT2_BW_8 = 0x00,
CXD2880_DVBT2_BW_7 = 0x01,
CXD2880_DVBT2_BW_6 = 0x02,
CXD2880_DVBT2_BW_5 = 0x03,
CXD2880_DVBT2_BW_10 = 0x04,
CXD2880_DVBT2_BW_1_7 = 0x05,
CXD2880_DVBT2_BW_RSVD1 = 0x06,
CXD2880_DVBT2_BW_RSVD2 = 0x07,
CXD2880_DVBT2_BW_RSVD3 = 0x08,
CXD2880_DVBT2_BW_RSVD4 = 0x09,
CXD2880_DVBT2_BW_RSVD5 = 0x0a,
CXD2880_DVBT2_BW_RSVD6 = 0x0b,
CXD2880_DVBT2_BW_RSVD7 = 0x0c,
CXD2880_DVBT2_BW_RSVD8 = 0x0d,
CXD2880_DVBT2_BW_RSVD9 = 0x0e,
CXD2880_DVBT2_BW_RSVD10 = 0x0f,
CXD2880_DVBT2_BW_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1pre_type {
CXD2880_DVBT2_L1PRE_TYPE_TS = 0x00,
CXD2880_DVBT2_L1PRE_TYPE_GS = 0x01,
CXD2880_DVBT2_L1PRE_TYPE_TS_GS = 0x02,
CXD2880_DVBT2_L1PRE_TYPE_RESERVED = 0x03,
CXD2880_DVBT2_L1PRE_TYPE_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_papr {
CXD2880_DVBT2_PAPR_0 = 0x00,
CXD2880_DVBT2_PAPR_1 = 0x01,
CXD2880_DVBT2_PAPR_2 = 0x02,
CXD2880_DVBT2_PAPR_3 = 0x03,
CXD2880_DVBT2_PAPR_RSVD1 = 0x04,
CXD2880_DVBT2_PAPR_RSVD2 = 0x05,
CXD2880_DVBT2_PAPR_RSVD3 = 0x06,
CXD2880_DVBT2_PAPR_RSVD4 = 0x07,
CXD2880_DVBT2_PAPR_RSVD5 = 0x08,
CXD2880_DVBT2_PAPR_RSVD6 = 0x09,
CXD2880_DVBT2_PAPR_RSVD7 = 0x0a,
CXD2880_DVBT2_PAPR_RSVD8 = 0x0b,
CXD2880_DVBT2_PAPR_RSVD9 = 0x0c,
CXD2880_DVBT2_PAPR_RSVD10 = 0x0d,
CXD2880_DVBT2_PAPR_RSVD11 = 0x0e,
CXD2880_DVBT2_PAPR_RSVD12 = 0x0f,
CXD2880_DVBT2_PAPR_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1post_constell {
CXD2880_DVBT2_L1POST_BPSK = 0x00,
CXD2880_DVBT2_L1POST_QPSK = 0x01,
CXD2880_DVBT2_L1POST_QAM16 = 0x02,
CXD2880_DVBT2_L1POST_QAM64 = 0x03,
CXD2880_DVBT2_L1POST_C_RSVD1 = 0x04,
CXD2880_DVBT2_L1POST_C_RSVD2 = 0x05,
CXD2880_DVBT2_L1POST_C_RSVD3 = 0x06,
CXD2880_DVBT2_L1POST_C_RSVD4 = 0x07,
CXD2880_DVBT2_L1POST_C_RSVD5 = 0x08,
CXD2880_DVBT2_L1POST_C_RSVD6 = 0x09,
CXD2880_DVBT2_L1POST_C_RSVD7 = 0x0a,
CXD2880_DVBT2_L1POST_C_RSVD8 = 0x0b,
CXD2880_DVBT2_L1POST_C_RSVD9 = 0x0c,
CXD2880_DVBT2_L1POST_C_RSVD10 = 0x0d,
CXD2880_DVBT2_L1POST_C_RSVD11 = 0x0e,
CXD2880_DVBT2_L1POST_C_RSVD12 = 0x0f,
CXD2880_DVBT2_L1POST_CONSTELL_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1post_cr {
CXD2880_DVBT2_L1POST_R1_2 = 0x00,
CXD2880_DVBT2_L1POST_R_RSVD1 = 0x01,
CXD2880_DVBT2_L1POST_R_RSVD2 = 0x02,
CXD2880_DVBT2_L1POST_R_RSVD3 = 0x03,
CXD2880_DVBT2_L1POST_R_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_l1post_fec_type {
CXD2880_DVBT2_L1POST_FEC_LDPC16K = 0x00,
CXD2880_DVBT2_L1POST_FEC_RSVD1 = 0x01,
CXD2880_DVBT2_L1POST_FEC_RSVD2 = 0x02,
CXD2880_DVBT2_L1POST_FEC_RSVD3 = 0x03,
CXD2880_DVBT2_L1POST_FEC_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_pp {
CXD2880_DVBT2_PP1 = 0x00,
CXD2880_DVBT2_PP2 = 0x01,
CXD2880_DVBT2_PP3 = 0x02,
CXD2880_DVBT2_PP4 = 0x03,
CXD2880_DVBT2_PP5 = 0x04,
CXD2880_DVBT2_PP6 = 0x05,
CXD2880_DVBT2_PP7 = 0x06,
CXD2880_DVBT2_PP8 = 0x07,
CXD2880_DVBT2_PP_RSVD1 = 0x08,
CXD2880_DVBT2_PP_RSVD2 = 0x09,
CXD2880_DVBT2_PP_RSVD3 = 0x0a,
CXD2880_DVBT2_PP_RSVD4 = 0x0b,
CXD2880_DVBT2_PP_RSVD5 = 0x0c,
CXD2880_DVBT2_PP_RSVD6 = 0x0d,
CXD2880_DVBT2_PP_RSVD7 = 0x0e,
CXD2880_DVBT2_PP_RSVD8 = 0x0f,
CXD2880_DVBT2_PP_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_code_rate {
CXD2880_DVBT2_R1_2 = 0x00,
CXD2880_DVBT2_R3_5 = 0x01,
CXD2880_DVBT2_R2_3 = 0x02,
CXD2880_DVBT2_R3_4 = 0x03,
CXD2880_DVBT2_R4_5 = 0x04,
CXD2880_DVBT2_R5_6 = 0x05,
CXD2880_DVBT2_R1_3 = 0x06,
CXD2880_DVBT2_R2_5 = 0x07,
CXD2880_DVBT2_PLP_CR_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_constell {
CXD2880_DVBT2_QPSK = 0x00,
CXD2880_DVBT2_QAM16 = 0x01,
CXD2880_DVBT2_QAM64 = 0x02,
CXD2880_DVBT2_QAM256 = 0x03,
CXD2880_DVBT2_CON_RSVD1 = 0x04,
CXD2880_DVBT2_CON_RSVD2 = 0x05,
CXD2880_DVBT2_CON_RSVD3 = 0x06,
CXD2880_DVBT2_CON_RSVD4 = 0x07,
CXD2880_DVBT2_CONSTELL_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_type {
CXD2880_DVBT2_PLP_TYPE_COMMON = 0x00,
CXD2880_DVBT2_PLP_TYPE_DATA1 = 0x01,
CXD2880_DVBT2_PLP_TYPE_DATA2 = 0x02,
CXD2880_DVBT2_PLP_TYPE_RSVD1 = 0x03,
CXD2880_DVBT2_PLP_TYPE_RSVD2 = 0x04,
CXD2880_DVBT2_PLP_TYPE_RSVD3 = 0x05,
CXD2880_DVBT2_PLP_TYPE_RSVD4 = 0x06,
CXD2880_DVBT2_PLP_TYPE_RSVD5 = 0x07,
CXD2880_DVBT2_PLP_TYPE_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_payload {
CXD2880_DVBT2_PLP_PAYLOAD_GFPS = 0x00,
CXD2880_DVBT2_PLP_PAYLOAD_GCS = 0x01,
CXD2880_DVBT2_PLP_PAYLOAD_GSE = 0x02,
CXD2880_DVBT2_PLP_PAYLOAD_TS = 0x03,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD1 = 0x04,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD2 = 0x05,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD3 = 0x06,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD4 = 0x07,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD5 = 0x08,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD6 = 0x09,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD7 = 0x0a,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD8 = 0x0b,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD9 = 0x0c,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD10 = 0x0d,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD11 = 0x0e,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD12 = 0x0f,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD13 = 0x10,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD14 = 0x11,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD15 = 0x12,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD16 = 0x13,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD17 = 0x14,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD18 = 0x15,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD19 = 0x16,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD20 = 0x17,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD21 = 0x18,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD22 = 0x19,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD23 = 0x1a,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD24 = 0x1b,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD25 = 0x1c,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD26 = 0x1d,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD27 = 0x1e,
CXD2880_DVBT2_PLP_PAYLOAD_RSVD28 = 0x1f,
CXD2880_DVBT2_PLP_PAYLOAD_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_fec {
CXD2880_DVBT2_FEC_LDPC_16K = 0x00,
CXD2880_DVBT2_FEC_LDPC_64K = 0x01,
CXD2880_DVBT2_FEC_RSVD1 = 0x02,
CXD2880_DVBT2_FEC_RSVD2 = 0x03,
CXD2880_DVBT2_FEC_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_mode {
CXD2880_DVBT2_PLP_MODE_NOTSPECIFIED = 0x00,
CXD2880_DVBT2_PLP_MODE_NM = 0x01,
CXD2880_DVBT2_PLP_MODE_HEM = 0x02,
CXD2880_DVBT2_PLP_MODE_RESERVED = 0x03,
CXD2880_DVBT2_PLP_MODE_UNKNOWN = 0xff
};
enum cxd2880_dvbt2_plp_btype {
CXD2880_DVBT2_PLP_COMMON,
CXD2880_DVBT2_PLP_DATA
};
enum cxd2880_dvbt2_stream {
CXD2880_DVBT2_STREAM_GENERIC_PACKETIZED = 0x00,
CXD2880_DVBT2_STREAM_GENERIC_CONTINUOUS = 0x01,
CXD2880_DVBT2_STREAM_GENERIC_ENCAPSULATED = 0x02,
CXD2880_DVBT2_STREAM_TRANSPORT = 0x03,
CXD2880_DVBT2_STREAM_UNKNOWN = 0xff
};
struct cxd2880_dvbt2_l1pre {
enum cxd2880_dvbt2_l1pre_type type;
u8 bw_ext;
enum cxd2880_dvbt2_s1 s1;
u8 s2;
u8 mixed;
enum cxd2880_dvbt2_mode fft_mode;
u8 l1_rep;
enum cxd2880_dvbt2_guard gi;
enum cxd2880_dvbt2_papr papr;
enum cxd2880_dvbt2_l1post_constell mod;
enum cxd2880_dvbt2_l1post_cr cr;
enum cxd2880_dvbt2_l1post_fec_type fec;
u32 l1_post_size;
u32 l1_post_info_size;
enum cxd2880_dvbt2_pp pp;
u8 tx_id_availability;
u16 cell_id;
u16 network_id;
u16 sys_id;
u8 num_frames;
u16 num_symbols;
u8 regen;
u8 post_ext;
u8 num_rf_freqs;
u8 rf_idx;
enum cxd2880_dvbt2_version t2_version;
u8 l1_post_scrambled;
u8 t2_base_lite;
u32 crc32;
};
struct cxd2880_dvbt2_plp {
u8 id;
enum cxd2880_dvbt2_plp_type type;
enum cxd2880_dvbt2_plp_payload payload;
u8 ff;
u8 first_rf_idx;
u8 first_frm_idx;
u8 group_id;
enum cxd2880_dvbt2_plp_constell constell;
enum cxd2880_dvbt2_plp_code_rate plp_cr;
u8 rot;
enum cxd2880_dvbt2_plp_fec fec;
u16 num_blocks_max;
u8 frm_int;
u8 til_len;
u8 til_type;
u8 in_band_a_flag;
u8 in_band_b_flag;
u16 rsvd;
enum cxd2880_dvbt2_plp_mode plp_mode;
u8 static_flag;
u8 static_padding_flag;
};
struct cxd2880_dvbt2_l1post {
u16 sub_slices_per_frame;
u8 num_plps;
u8 num_aux;
u8 aux_cfg_rfu;
u8 rf_idx;
u32 freq;
u8 fef_type;
u32 fef_length;
u8 fef_intvl;
};
struct cxd2880_dvbt2_ofdm {
u8 mixed;
u8 is_miso;
enum cxd2880_dvbt2_mode mode;
enum cxd2880_dvbt2_guard gi;
enum cxd2880_dvbt2_pp pp;
u8 bw_ext;
enum cxd2880_dvbt2_papr papr;
u16 num_symbols;
};
struct cxd2880_dvbt2_bbheader {
enum cxd2880_dvbt2_stream stream_input;
u8 is_single_input_stream;
u8 is_constant_coding_modulation;
u8 issy_indicator;
u8 null_packet_deletion;
u8 ext;
u8 input_stream_identifier;
u16 user_packet_length;
u16 data_field_length;
u8 sync_byte;
u32 issy;
enum cxd2880_dvbt2_plp_mode plp_mode;
};
#endif
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_integ.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* integration layer common functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include <linux/ktime.h>
#include <linux/errno.h>
#include "cxd2880_tnrdmd.h"
#include "cxd2880_tnrdmd_mon.h"
#include "cxd2880_integ.h"
int cxd2880_integ_init(struct cxd2880_tnrdmd *tnr_dmd)
{
int ret;
ktime_t start;
u8 cpu_task_completed = 0;
if (!tnr_dmd)
return -EINVAL;
ret = cxd2880_tnrdmd_init1(tnr_dmd);
if (ret)
return ret;
start = ktime_get();
while (1) {
ret =
cxd2880_tnrdmd_check_internal_cpu_status(tnr_dmd,
&cpu_task_completed);
if (ret)
return ret;
if (cpu_task_completed)
break;
if (ktime_to_ms(ktime_sub(ktime_get(), start)) >
CXD2880_TNRDMD_WAIT_INIT_TIMEOUT)
return -ETIMEDOUT;
usleep_range(CXD2880_TNRDMD_WAIT_INIT_INTVL,
CXD2880_TNRDMD_WAIT_INIT_INTVL + 1000);
}
return cxd2880_tnrdmd_init2(tnr_dmd);
}
int cxd2880_integ_cancel(struct cxd2880_tnrdmd *tnr_dmd)
{
if (!tnr_dmd)
return -EINVAL;
atomic_set(&tnr_dmd->cancel, 1);
return 0;
}
int cxd2880_integ_check_cancellation(struct cxd2880_tnrdmd *tnr_dmd)
{
if (!tnr_dmd)
return -EINVAL;
if (atomic_read(&tnr_dmd->cancel) != 0)
return -ECANCELED;
return 0;
}
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_integ.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* integration layer common interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_INTEG_H
#define CXD2880_INTEG_H
#include "cxd2880_tnrdmd.h"
#define CXD2880_TNRDMD_WAIT_INIT_TIMEOUT 500
#define CXD2880_TNRDMD_WAIT_INIT_INTVL 10
#define CXD2880_TNRDMD_WAIT_AGC_STABLE 100
int cxd2880_integ_init(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_integ_cancel(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_integ_check_cancellation(struct cxd2880_tnrdmd
*tnr_dmd);
#endif
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_io.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* register I/O interface functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_io.h"
int cxd2880_io_common_write_one_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data)
{
if (!io)
return -EINVAL;
return io->write_regs(io, tgt, sub_address, &data, 1);
}
int cxd2880_io_set_reg_bits(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data, u8 mask)
{
int ret;
if (!io)
return -EINVAL;
if (mask == 0x00)
return 0;
if (mask != 0xff) {
u8 rdata = 0x00;
ret = io->read_regs(io, tgt, sub_address, &rdata, 1);
if (ret)
return ret;
data = (data & mask) | (rdata & (mask ^ 0xff));
}
return io->write_reg(io, tgt, sub_address, data);
}
int cxd2880_io_write_multi_regs(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
const struct cxd2880_reg_value reg_value[],
u8 size)
{
int ret;
int i;
if (!io)
return -EINVAL;
for (i = 0; i < size ; i++) {
ret = io->write_reg(io, tgt, reg_value[i].addr,
reg_value[i].value);
if (ret)
return ret;
}
return 0;
}
@@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_io.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* register I/O interface definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_IO_H
#define CXD2880_IO_H
#include "cxd2880_common.h"
enum cxd2880_io_tgt {
CXD2880_IO_TGT_SYS,
CXD2880_IO_TGT_DMD
};
struct cxd2880_reg_value {
u8 addr;
u8 value;
};
struct cxd2880_io {
int (*read_regs)(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt, u8 sub_address,
u8 *data, u32 size);
int (*write_regs)(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt, u8 sub_address,
const u8 *data, u32 size);
int (*write_reg)(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt, u8 sub_address,
u8 data);
void *if_object;
u8 i2c_address_sys;
u8 i2c_address_demod;
u8 slave_select;
void *user;
};
int cxd2880_io_common_write_one_reg(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data);
int cxd2880_io_set_reg_bits(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
u8 sub_address, u8 data, u8 mask);
int cxd2880_io_write_multi_regs(struct cxd2880_io *io,
enum cxd2880_io_tgt tgt,
const struct cxd2880_reg_value reg_value[],
u8 size);
#endif
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_spi.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* SPI access definitions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_SPI_H
#define CXD2880_SPI_H
#include "cxd2880_common.h"
enum cxd2880_spi_mode {
CXD2880_SPI_MODE_0,
CXD2880_SPI_MODE_1,
CXD2880_SPI_MODE_2,
CXD2880_SPI_MODE_3
};
struct cxd2880_spi {
int (*read)(struct cxd2880_spi *spi, u8 *data,
u32 size);
int (*write)(struct cxd2880_spi *spi, const u8 *data,
u32 size);
int (*write_read)(struct cxd2880_spi *spi,
const u8 *tx_data, u32 tx_size,
u8 *rx_data, u32 rx_size);
u32 flags;
void *user;
};
#endif
@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_spi_device.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* SPI access functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include <linux/spi/spi.h>
#include "cxd2880_spi_device.h"
static int cxd2880_spi_device_write(struct cxd2880_spi *spi,
const u8 *data, u32 size)
{
struct cxd2880_spi_device *spi_device = NULL;
struct spi_message msg;
struct spi_transfer tx;
int result = 0;
if (!spi || !spi->user || !data || size == 0)
return -EINVAL;
spi_device = spi->user;
memset(&tx, 0, sizeof(tx));
tx.tx_buf = data;
tx.len = size;
spi_message_init(&msg);
spi_message_add_tail(&tx, &msg);
result = spi_sync(spi_device->spi, &msg);
if (result < 0)
return -EIO;
return 0;
}
static int cxd2880_spi_device_write_read(struct cxd2880_spi *spi,
const u8 *tx_data,
u32 tx_size,
u8 *rx_data,
u32 rx_size)
{
struct cxd2880_spi_device *spi_device = NULL;
int result = 0;
if (!spi || !spi->user || !tx_data ||
!tx_size || !rx_data || !rx_size)
return -EINVAL;
spi_device = spi->user;
result = spi_write_then_read(spi_device->spi, tx_data,
tx_size, rx_data, rx_size);
if (result < 0)
return -EIO;
return 0;
}
int
cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device,
enum cxd2880_spi_mode mode,
u32 speed_hz)
{
int result = 0;
struct spi_device *spi = spi_device->spi;
switch (mode) {
case CXD2880_SPI_MODE_0:
spi->mode = SPI_MODE_0;
break;
case CXD2880_SPI_MODE_1:
spi->mode = SPI_MODE_1;
break;
case CXD2880_SPI_MODE_2:
spi->mode = SPI_MODE_2;
break;
case CXD2880_SPI_MODE_3:
spi->mode = SPI_MODE_3;
break;
default:
return -EINVAL;
}
spi->max_speed_hz = speed_hz;
spi->bits_per_word = 8;
result = spi_setup(spi);
if (result != 0) {
pr_err("spi_setup failed %d\n", result);
return -EINVAL;
}
return 0;
}
int cxd2880_spi_device_create_spi(struct cxd2880_spi *spi,
struct cxd2880_spi_device *spi_device)
{
if (!spi || !spi_device)
return -EINVAL;
spi->read = NULL;
spi->write = cxd2880_spi_device_write;
spi->write_read = cxd2880_spi_device_write_read;
spi->flags = 0;
spi->user = spi_device;
return 0;
}
@@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_spi_device.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* SPI access interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_SPI_DEVICE_H
#define CXD2880_SPI_DEVICE_H
#include "cxd2880_spi.h"
struct cxd2880_spi_device {
struct spi_device *spi;
};
int cxd2880_spi_device_initialize(struct cxd2880_spi_device *spi_device,
enum cxd2880_spi_mode mode,
u32 speedHz);
int cxd2880_spi_device_create_spi(struct cxd2880_spi *spi,
struct cxd2880_spi_device *spi_device);
#endif /* CXD2880_SPI_DEVICE_H */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,365 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common control interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_H
#define CXD2880_TNRDMD_H
#include <linux/atomic.h>
#include "cxd2880_common.h"
#include "cxd2880_io.h"
#include "cxd2880_dtv.h"
#include "cxd2880_dvbt.h"
#include "cxd2880_dvbt2.h"
#define CXD2880_TNRDMD_MAX_CFG_MEM_COUNT 100
#define slvt_unfreeze_reg(tnr_dmd) ((void)((tnr_dmd)->io->write_reg\
((tnr_dmd)->io, CXD2880_IO_TGT_DMD, 0x01, 0x00)))
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_UNDERFLOW 0x0001
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_OVERFLOW 0x0002
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_ALMOST_EMPTY 0x0004
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_ALMOST_FULL 0x0008
#define CXD2880_TNRDMD_INTERRUPT_TYPE_BUF_RRDY 0x0010
#define CXD2880_TNRDMD_INTERRUPT_TYPE_ILLEGAL_COMMAND 0x0020
#define CXD2880_TNRDMD_INTERRUPT_TYPE_ILLEGAL_ACCESS 0x0040
#define CXD2880_TNRDMD_INTERRUPT_TYPE_CPU_ERROR 0x0100
#define CXD2880_TNRDMD_INTERRUPT_TYPE_LOCK 0x0200
#define CXD2880_TNRDMD_INTERRUPT_TYPE_INV_LOCK 0x0400
#define CXD2880_TNRDMD_INTERRUPT_TYPE_NOOFDM 0x0800
#define CXD2880_TNRDMD_INTERRUPT_TYPE_EWS 0x1000
#define CXD2880_TNRDMD_INTERRUPT_TYPE_EEW 0x2000
#define CXD2880_TNRDMD_INTERRUPT_TYPE_FEC_FAIL 0x4000
#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_L1POST_OK 0x01
#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_DMD_LOCK 0x02
#define CXD2880_TNRDMD_INTERRUPT_LOCK_SEL_TS_LOCK 0x04
enum cxd2880_tnrdmd_chip_id {
CXD2880_TNRDMD_CHIP_ID_UNKNOWN = 0x00,
CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X = 0x62,
CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11 = 0x6a
};
#define CXD2880_TNRDMD_CHIP_ID_VALID(chip_id) \
(((chip_id) == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_0X) || \
((chip_id) == CXD2880_TNRDMD_CHIP_ID_CXD2880_ES1_11))
enum cxd2880_tnrdmd_state {
CXD2880_TNRDMD_STATE_UNKNOWN,
CXD2880_TNRDMD_STATE_SLEEP,
CXD2880_TNRDMD_STATE_ACTIVE,
CXD2880_TNRDMD_STATE_INVALID
};
enum cxd2880_tnrdmd_divermode {
CXD2880_TNRDMD_DIVERMODE_SINGLE,
CXD2880_TNRDMD_DIVERMODE_MAIN,
CXD2880_TNRDMD_DIVERMODE_SUB
};
enum cxd2880_tnrdmd_clockmode {
CXD2880_TNRDMD_CLOCKMODE_UNKNOWN,
CXD2880_TNRDMD_CLOCKMODE_A,
CXD2880_TNRDMD_CLOCKMODE_B,
CXD2880_TNRDMD_CLOCKMODE_C
};
enum cxd2880_tnrdmd_tsout_if {
CXD2880_TNRDMD_TSOUT_IF_TS,
CXD2880_TNRDMD_TSOUT_IF_SPI,
CXD2880_TNRDMD_TSOUT_IF_SDIO
};
enum cxd2880_tnrdmd_xtal_share {
CXD2880_TNRDMD_XTAL_SHARE_NONE,
CXD2880_TNRDMD_XTAL_SHARE_EXTREF,
CXD2880_TNRDMD_XTAL_SHARE_MASTER,
CXD2880_TNRDMD_XTAL_SHARE_SLAVE
};
enum cxd2880_tnrdmd_spectrum_sense {
CXD2880_TNRDMD_SPECTRUM_NORMAL,
CXD2880_TNRDMD_SPECTRUM_INV
};
enum cxd2880_tnrdmd_cfg_id {
CXD2880_TNRDMD_CFG_OUTPUT_SEL_MSB,
CXD2880_TNRDMD_CFG_TSVALID_ACTIVE_HI,
CXD2880_TNRDMD_CFG_TSSYNC_ACTIVE_HI,
CXD2880_TNRDMD_CFG_TSERR_ACTIVE_HI,
CXD2880_TNRDMD_CFG_LATCH_ON_POSEDGE,
CXD2880_TNRDMD_CFG_TSCLK_CONT,
CXD2880_TNRDMD_CFG_TSCLK_MASK,
CXD2880_TNRDMD_CFG_TSVALID_MASK,
CXD2880_TNRDMD_CFG_TSERR_MASK,
CXD2880_TNRDMD_CFG_TSERR_VALID_DIS,
CXD2880_TNRDMD_CFG_TSPIN_CURRENT,
CXD2880_TNRDMD_CFG_TSPIN_PULLUP_MANUAL,
CXD2880_TNRDMD_CFG_TSPIN_PULLUP,
CXD2880_TNRDMD_CFG_TSCLK_FREQ,
CXD2880_TNRDMD_CFG_TSBYTECLK_MANUAL,
CXD2880_TNRDMD_CFG_TS_PACKET_GAP,
CXD2880_TNRDMD_CFG_TS_BACKWARDS_COMPATIBLE,
CXD2880_TNRDMD_CFG_PWM_VALUE,
CXD2880_TNRDMD_CFG_INTERRUPT,
CXD2880_TNRDMD_CFG_INTERRUPT_LOCK_SEL,
CXD2880_TNRDMD_CFG_INTERRUPT_INV_LOCK_SEL,
CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_EMPTY_THRS,
CXD2880_TNRDMD_CFG_TS_BUF_ALMOST_FULL_THRS,
CXD2880_TNRDMD_CFG_TS_BUF_RRDY_THRS,
CXD2880_TNRDMD_CFG_FIXED_CLOCKMODE,
CXD2880_TNRDMD_CFG_CABLE_INPUT,
CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_BASE,
CXD2880_TNRDMD_CFG_DVBT2_FEF_INTERMITTENT_LITE,
CXD2880_TNRDMD_CFG_BLINDTUNE_DVBT2_FIRST,
CXD2880_TNRDMD_CFG_DVBT_BERN_PERIOD,
CXD2880_TNRDMD_CFG_DVBT_VBER_PERIOD,
CXD2880_TNRDMD_CFG_DVBT_PER_MES,
CXD2880_TNRDMD_CFG_DVBT2_BBER_MES,
CXD2880_TNRDMD_CFG_DVBT2_LBER_MES,
CXD2880_TNRDMD_CFG_DVBT2_PER_MES,
};
enum cxd2880_tnrdmd_lock_result {
CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT,
CXD2880_TNRDMD_LOCK_RESULT_LOCKED,
CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED
};
enum cxd2880_tnrdmd_gpio_mode {
CXD2880_TNRDMD_GPIO_MODE_OUTPUT = 0x00,
CXD2880_TNRDMD_GPIO_MODE_INPUT = 0x01,
CXD2880_TNRDMD_GPIO_MODE_INT = 0x02,
CXD2880_TNRDMD_GPIO_MODE_FEC_FAIL = 0x03,
CXD2880_TNRDMD_GPIO_MODE_PWM = 0x04,
CXD2880_TNRDMD_GPIO_MODE_EWS = 0x05,
CXD2880_TNRDMD_GPIO_MODE_EEW = 0x06
};
enum cxd2880_tnrdmd_serial_ts_clk {
CXD2880_TNRDMD_SERIAL_TS_CLK_FULL,
CXD2880_TNRDMD_SERIAL_TS_CLK_HALF
};
struct cxd2880_tnrdmd_cfg_mem {
enum cxd2880_io_tgt tgt;
u8 bank;
u8 address;
u8 value;
u8 bit_mask;
};
struct cxd2880_tnrdmd_pid_cfg {
u8 is_en;
u16 pid;
};
struct cxd2880_tnrdmd_pid_ftr_cfg {
u8 is_negative;
struct cxd2880_tnrdmd_pid_cfg pid_cfg[32];
};
struct cxd2880_tnrdmd_lna_thrs {
u8 off_on;
u8 on_off;
};
struct cxd2880_tnrdmd_lna_thrs_tbl_air {
struct cxd2880_tnrdmd_lna_thrs thrs[24];
};
struct cxd2880_tnrdmd_lna_thrs_tbl_cable {
struct cxd2880_tnrdmd_lna_thrs thrs[32];
};
struct cxd2880_tnrdmd_create_param {
enum cxd2880_tnrdmd_tsout_if ts_output_if;
u8 en_internal_ldo;
enum cxd2880_tnrdmd_xtal_share xtal_share_type;
u8 xosc_cap;
u8 xosc_i;
u8 is_cxd2881gg;
u8 stationary_use;
};
struct cxd2880_tnrdmd_diver_create_param {
enum cxd2880_tnrdmd_tsout_if ts_output_if;
u8 en_internal_ldo;
u8 xosc_cap_main;
u8 xosc_i_main;
u8 xosc_i_sub;
u8 is_cxd2881gg;
u8 stationary_use;
};
struct cxd2880_tnrdmd {
struct cxd2880_tnrdmd *diver_sub;
struct cxd2880_io *io;
struct cxd2880_tnrdmd_create_param create_param;
enum cxd2880_tnrdmd_divermode diver_mode;
enum cxd2880_tnrdmd_clockmode fixed_clk_mode;
u8 is_cable_input;
u8 en_fef_intmtnt_base;
u8 en_fef_intmtnt_lite;
u8 blind_tune_dvbt2_first;
int (*rf_lvl_cmpstn)(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db);
struct cxd2880_tnrdmd_lna_thrs_tbl_air *lna_thrs_tbl_air;
struct cxd2880_tnrdmd_lna_thrs_tbl_cable *lna_thrs_tbl_cable;
u8 srl_ts_clk_mod_cnts;
enum cxd2880_tnrdmd_serial_ts_clk srl_ts_clk_frq;
u8 ts_byte_clk_manual_setting;
u8 is_ts_backwards_compatible_mode;
struct cxd2880_tnrdmd_cfg_mem cfg_mem[CXD2880_TNRDMD_MAX_CFG_MEM_COUNT];
u8 cfg_mem_last_entry;
struct cxd2880_tnrdmd_pid_ftr_cfg pid_ftr_cfg;
u8 pid_ftr_cfg_en;
void *user;
enum cxd2880_tnrdmd_chip_id chip_id;
enum cxd2880_tnrdmd_state state;
enum cxd2880_tnrdmd_clockmode clk_mode;
u32 frequency_khz;
enum cxd2880_dtv_sys sys;
enum cxd2880_dtv_bandwidth bandwidth;
u8 scan_mode;
atomic_t cancel;
};
int cxd2880_tnrdmd_create(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_io *io,
struct cxd2880_tnrdmd_create_param
*create_param);
int cxd2880_tnrdmd_diver_create(struct cxd2880_tnrdmd
*tnr_dmd_main,
struct cxd2880_io *io_main,
struct cxd2880_tnrdmd *tnr_dmd_sub,
struct cxd2880_io *io_sub,
struct
cxd2880_tnrdmd_diver_create_param
*create_param);
int cxd2880_tnrdmd_init1(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_init2(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_check_internal_cpu_status(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *task_completed);
int cxd2880_tnrdmd_common_tune_setting1(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dtv_sys sys,
u32 frequency_khz,
enum cxd2880_dtv_bandwidth
bandwidth, u8 one_seg_opt,
u8 one_seg_opt_shft_dir);
int cxd2880_tnrdmd_common_tune_setting2(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dtv_sys sys,
u8 en_fef_intmtnt_ctrl);
int cxd2880_tnrdmd_sleep(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_set_cfg(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_tnrdmd_cfg_id id,
int value);
int cxd2880_tnrdmd_gpio_set_cfg(struct cxd2880_tnrdmd *tnr_dmd,
u8 id,
u8 en,
enum cxd2880_tnrdmd_gpio_mode mode,
u8 open_drain, u8 invert);
int cxd2880_tnrdmd_gpio_set_cfg_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 id,
u8 en,
enum cxd2880_tnrdmd_gpio_mode
mode, u8 open_drain,
u8 invert);
int cxd2880_tnrdmd_gpio_read(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 *value);
int cxd2880_tnrdmd_gpio_read_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 *value);
int cxd2880_tnrdmd_gpio_write(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 value);
int cxd2880_tnrdmd_gpio_write_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 id, u8 value);
int cxd2880_tnrdmd_interrupt_read(struct cxd2880_tnrdmd *tnr_dmd,
u16 *value);
int cxd2880_tnrdmd_interrupt_clear(struct cxd2880_tnrdmd *tnr_dmd,
u16 value);
int cxd2880_tnrdmd_ts_buf_clear(struct cxd2880_tnrdmd *tnr_dmd,
u8 clear_overflow_flag,
u8 clear_underflow_flag,
u8 clear_buf);
int cxd2880_tnrdmd_chip_id(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_tnrdmd_chip_id *chip_id);
int cxd2880_tnrdmd_set_and_save_reg_bits(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_io_tgt tgt,
u8 bank, u8 address,
u8 value, u8 bit_mask);
int cxd2880_tnrdmd_set_scan_mode(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_dtv_sys sys,
u8 scan_mode_end);
int cxd2880_tnrdmd_set_pid_ftr(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_tnrdmd_pid_ftr_cfg
*pid_ftr_cfg);
int cxd2880_tnrdmd_set_rf_lvl_cmpstn(struct cxd2880_tnrdmd
*tnr_dmd,
int (*rf_lvl_cmpstn)
(struct cxd2880_tnrdmd *,
int *));
int cxd2880_tnrdmd_set_rf_lvl_cmpstn_sub(struct cxd2880_tnrdmd *tnr_dmd,
int (*rf_lvl_cmpstn)
(struct cxd2880_tnrdmd *,
int *));
int cxd2880_tnrdmd_set_lna_thrs(struct cxd2880_tnrdmd *tnr_dmd,
struct
cxd2880_tnrdmd_lna_thrs_tbl_air
*tbl_air,
struct
cxd2880_tnrdmd_lna_thrs_tbl_cable
*tbl_cable);
int cxd2880_tnrdmd_set_lna_thrs_sub(struct cxd2880_tnrdmd *tnr_dmd,
struct
cxd2880_tnrdmd_lna_thrs_tbl_air
*tbl_air,
struct
cxd2880_tnrdmd_lna_thrs_tbl_cable
*tbl_cable);
int cxd2880_tnrdmd_set_ts_pin_high_low(struct cxd2880_tnrdmd
*tnr_dmd, u8 en, u8 value);
int cxd2880_tnrdmd_set_ts_output(struct cxd2880_tnrdmd *tnr_dmd,
u8 en);
int slvt_freeze_reg(struct cxd2880_tnrdmd *tnr_dmd);
#endif
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_driver_version.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* version information
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#define CXD2880_TNRDMD_DRIVER_VERSION "1.4.1 - 1.0.5"
#define CXD2880_TNRDMD_DRIVER_RELEASE_DATE "2018-04-25"
@@ -0,0 +1,919 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_tnrdmd_dvbt.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* control functions for DVB-T
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include <media/dvb_frontend.h>
#include "cxd2880_tnrdmd_dvbt.h"
#include "cxd2880_tnrdmd_dvbt_mon.h"
static const struct cxd2880_reg_value tune_dmd_setting_seq1[] = {
{0x00, 0x00}, {0x31, 0x01},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq2[] = {
{0x00, 0x04}, {0x5c, 0xfb}, {0x00, 0x10}, {0xa4, 0x03},
{0x00, 0x14}, {0xb0, 0x00}, {0x00, 0x25},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq3[] = {
{0x00, 0x12}, {0x44, 0x00},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq4[] = {
{0x00, 0x11}, {0x87, 0xd2},
};
static const struct cxd2880_reg_value tune_dmd_setting_seq5[] = {
{0x00, 0x00}, {0xfd, 0x01},
};
static const struct cxd2880_reg_value sleep_dmd_setting_seq1[] = {
{0x00, 0x04}, {0x5c, 0xd8}, {0x00, 0x10}, {0xa4, 0x00},
};
static const struct cxd2880_reg_value sleep_dmd_setting_seq2[] = {
{0x00, 0x11}, {0x87, 0x04},
};
static int x_tune_dvbt_demod_setting(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dtv_bandwidth
bandwidth,
enum cxd2880_tnrdmd_clockmode
clk_mode)
{
static const u8 clk_mode_ckffrq_a[2] = { 0x52, 0x49 };
static const u8 clk_mode_ckffrq_b[2] = { 0x5d, 0x55 };
static const u8 clk_mode_ckffrq_c[2] = { 0x60, 0x00 };
static const u8 ratectl_margin[2] = { 0x01, 0xf0 };
static const u8 maxclkcnt_a[3] = { 0x73, 0xca, 0x49 };
static const u8 maxclkcnt_b[3] = { 0xc8, 0x13, 0xaa };
static const u8 maxclkcnt_c[3] = { 0xdc, 0x6c, 0x00 };
static const u8 bw8_nomi_ac[5] = { 0x15, 0x00, 0x00, 0x00, 0x00};
static const u8 bw8_nomi_b[5] = { 0x14, 0x6a, 0xaa, 0xaa, 0xaa};
static const u8 bw8_gtdofst_a[2] = { 0x01, 0x28 };
static const u8 bw8_gtdofst_b[2] = { 0x11, 0x44 };
static const u8 bw8_gtdofst_c[2] = { 0x15, 0x28 };
static const u8 bw8_mrc_a[5] = { 0x30, 0x00, 0x00, 0x90, 0x00 };
static const u8 bw8_mrc_b[5] = { 0x36, 0x71, 0x00, 0xa3, 0x55 };
static const u8 bw8_mrc_c[5] = { 0x38, 0x00, 0x00, 0xa8, 0x00 };
static const u8 bw8_notch[4] = { 0xb3, 0x00, 0x01, 0x02 };
static const u8 bw7_nomi_ac[5] = { 0x18, 0x00, 0x00, 0x00, 0x00};
static const u8 bw7_nomi_b[5] = { 0x17, 0x55, 0x55, 0x55, 0x55};
static const u8 bw7_gtdofst_a[2] = { 0x12, 0x4c };
static const u8 bw7_gtdofst_b[2] = { 0x1f, 0x15 };
static const u8 bw7_gtdofst_c[2] = { 0x1f, 0xf8 };
static const u8 bw7_mrc_a[5] = { 0x36, 0xdb, 0x00, 0xa4, 0x92 };
static const u8 bw7_mrc_b[5] = { 0x3e, 0x38, 0x00, 0xba, 0xaa };
static const u8 bw7_mrc_c[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };
static const u8 bw7_notch[4] = { 0xb8, 0x00, 0x00, 0x03 };
static const u8 bw6_nomi_ac[5] = { 0x1c, 0x00, 0x00, 0x00, 0x00};
static const u8 bw6_nomi_b[5] = { 0x1b, 0x38, 0xe3, 0x8e, 0x38};
static const u8 bw6_gtdofst_a[2] = { 0x1f, 0xf8 };
static const u8 bw6_gtdofst_b[2] = { 0x24, 0x43 };
static const u8 bw6_gtdofst_c[2] = { 0x25, 0x4c };
static const u8 bw6_mrc_a[5] = { 0x40, 0x00, 0x00, 0xc0, 0x00 };
static const u8 bw6_mrc_b[5] = { 0x48, 0x97, 0x00, 0xd9, 0xc7 };
static const u8 bw6_mrc_c[5] = { 0x4a, 0xaa, 0x00, 0xdf, 0xff };
static const u8 bw6_notch[4] = { 0xbe, 0xab, 0x00, 0x03 };
static const u8 bw5_nomi_ac[5] = { 0x21, 0x99, 0x99, 0x99, 0x99};
static const u8 bw5_nomi_b[5] = { 0x20, 0xaa, 0xaa, 0xaa, 0xaa};
static const u8 bw5_gtdofst_a[2] = { 0x26, 0x5d };
static const u8 bw5_gtdofst_b[2] = { 0x2b, 0x84 };
static const u8 bw5_gtdofst_c[2] = { 0x2c, 0xc2 };
static const u8 bw5_mrc_a[5] = { 0x4c, 0xcc, 0x00, 0xe6, 0x66 };
static const u8 bw5_mrc_b[5] = { 0x57, 0x1c, 0x01, 0x05, 0x55 };
static const u8 bw5_mrc_c[5] = { 0x59, 0x99, 0x01, 0x0c, 0xcc };
static const u8 bw5_notch[4] = { 0xc8, 0x01, 0x00, 0x03 };
const u8 *data = NULL;
u8 sst_data;
int ret;
if (!tnr_dmd)
return -EINVAL;
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
tune_dmd_setting_seq1,
ARRAY_SIZE(tune_dmd_setting_seq1));
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = clk_mode_ckffrq_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = clk_mode_ckffrq_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = clk_mode_ckffrq_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x65, data, 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x5d, 0x07);
if (ret)
return ret;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
u8 data[2] = { 0x01, 0x01 };
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x00);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0xce, data, 2);
if (ret)
return ret;
}
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq2,
ARRAY_SIZE(tune_dmd_setting_seq2));
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0xf0, ratectl_margin, 2);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN ||
tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq3,
ARRAY_SIZE(tune_dmd_setting_seq3));
if (ret)
return ret;
}
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB) {
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq4,
ARRAY_SIZE(tune_dmd_setting_seq4));
if (ret)
return ret;
}
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_SUB) {
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = maxclkcnt_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = maxclkcnt_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = maxclkcnt_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x68, data, 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret)
return ret;
switch (bandwidth) {
case CXD2880_DTV_BW_8_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw8_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw8_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x00);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw8_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw8_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw8_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x35;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x34;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw8_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw8_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw8_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw8_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw8_notch[2], 2);
if (ret)
return ret;
break;
case CXD2880_DTV_BW_7_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw7_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw7_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x02);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw7_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw7_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw7_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x2f;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x2e;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw7_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw7_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw7_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw7_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw7_notch[2], 2);
if (ret)
return ret;
break;
case CXD2880_DTV_BW_6_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw6_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw6_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x04);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw6_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw6_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw6_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x29;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x2a;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw6_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw6_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw6_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw6_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw6_notch[2], 2);
if (ret)
return ret;
break;
case CXD2880_DTV_BW_5_MHZ:
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw5_nomi_ac;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw5_nomi_b;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, data, 5);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4a, 0x06);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw5_gtdofst_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw5_gtdofst_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw5_gtdofst_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x7d, data, 2);
if (ret)
return ret;
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
case CXD2880_TNRDMD_CLOCKMODE_B:
sst_data = 0x24;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
sst_data = 0x23;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x71, sst_data);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
switch (clk_mode) {
case CXD2880_TNRDMD_CLOCKMODE_A:
data = bw5_mrc_a;
break;
case CXD2880_TNRDMD_CLOCKMODE_B:
data = bw5_mrc_b;
break;
case CXD2880_TNRDMD_CLOCKMODE_C:
data = bw5_mrc_c;
break;
default:
return -EINVAL;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x4b, &data[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x51, &data[2], 3);
if (ret)
return ret;
}
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x72, &bw5_notch[0], 2);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x6b, &bw5_notch[2], 2);
if (ret)
return ret;
break;
default:
return -EINVAL;
}
return cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
tune_dmd_setting_seq5,
ARRAY_SIZE(tune_dmd_setting_seq5));
}
static int x_sleep_dvbt_demod_setting(struct cxd2880_tnrdmd
*tnr_dmd)
{
int ret;
if (!tnr_dmd)
return -EINVAL;
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
sleep_dmd_setting_seq1,
ARRAY_SIZE(sleep_dmd_setting_seq1));
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
ret = cxd2880_io_write_multi_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
sleep_dmd_setting_seq2,
ARRAY_SIZE(sleep_dmd_setting_seq2));
return ret;
}
static int dvbt_set_profile(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_dvbt_profile profile)
{
int ret;
if (!tnr_dmd)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x10);
if (ret)
return ret;
return tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x67,
(profile == CXD2880_DVBT_PROFILE_HP)
? 0x00 : 0x01);
}
int cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param)
{
int ret;
if (!tnr_dmd || !tune_param)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_common_tune_setting1(tnr_dmd, CXD2880_DTV_SYS_DVBT,
tune_param->center_freq_khz,
tune_param->bandwidth, 0, 0);
if (ret)
return ret;
ret =
x_tune_dvbt_demod_setting(tnr_dmd, tune_param->bandwidth,
tnr_dmd->clk_mode);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
ret =
x_tune_dvbt_demod_setting(tnr_dmd->diver_sub,
tune_param->bandwidth,
tnr_dmd->diver_sub->clk_mode);
if (ret)
return ret;
}
return dvbt_set_profile(tnr_dmd, tune_param->profile);
}
int cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param)
{
int ret;
if (!tnr_dmd || !tune_param)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_common_tune_setting2(tnr_dmd, CXD2880_DTV_SYS_DVBT,
0);
if (ret)
return ret;
tnr_dmd->state = CXD2880_TNRDMD_STATE_ACTIVE;
tnr_dmd->frequency_khz = tune_param->center_freq_khz;
tnr_dmd->sys = CXD2880_DTV_SYS_DVBT;
tnr_dmd->bandwidth = tune_param->bandwidth;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN) {
tnr_dmd->diver_sub->state = CXD2880_TNRDMD_STATE_ACTIVE;
tnr_dmd->diver_sub->frequency_khz = tune_param->center_freq_khz;
tnr_dmd->diver_sub->sys = CXD2880_DTV_SYS_DVBT;
tnr_dmd->diver_sub->bandwidth = tune_param->bandwidth;
}
return 0;
}
int cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd *tnr_dmd)
{
int ret;
if (!tnr_dmd)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_SLEEP &&
tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret = x_sleep_dvbt_demod_setting(tnr_dmd);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret = x_sleep_dvbt_demod_setting(tnr_dmd->diver_sub);
return ret;
}
int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock)
{
int ret;
u8 sync_stat = 0;
u8 ts_lock = 0;
u8 unlock_detected = 0;
u8 unlock_detected_sub = 0;
if (!tnr_dmd || !lock)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
&unlock_detected);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
if (sync_stat == 6)
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
else if (unlock_detected)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return 0;
}
if (sync_stat == 6) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return 0;
}
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
&unlock_detected_sub);
if (ret)
return ret;
if (sync_stat == 6)
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
else if (unlock_detected && unlock_detected_sub)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return 0;
}
int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock)
{
int ret;
u8 sync_stat = 0;
u8 ts_lock = 0;
u8 unlock_detected = 0;
u8 unlock_detected_sub = 0;
if (!tnr_dmd || !lock)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync_stat, &ts_lock,
&unlock_detected);
if (ret)
return ret;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
if (ts_lock)
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
else if (unlock_detected)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return 0;
}
if (ts_lock) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return 0;
} else if (!unlock_detected) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return 0;
}
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(tnr_dmd, &sync_stat,
&unlock_detected_sub);
if (ret)
return ret;
if (unlock_detected && unlock_detected_sub)
*lock = CXD2880_TNRDMD_LOCK_RESULT_UNLOCKED;
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return 0;
}
@@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* control interface for DVB-T
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT_H
#define CXD2880_TNRDMD_DVBT_H
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd.h"
struct cxd2880_dvbt_tune_param {
u32 center_freq_khz;
enum cxd2880_dtv_bandwidth bandwidth;
enum cxd2880_dvbt_profile profile;
};
int cxd2880_tnrdmd_dvbt_tune1(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt_tune2(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt_sleep_setting(struct cxd2880_tnrdmd
*tnr_dmd);
int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,65 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt2.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* control interface for DVB-T2
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT2_H
#define CXD2880_TNRDMD_DVBT2_H
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd.h"
enum cxd2880_tnrdmd_dvbt2_tune_info {
CXD2880_TNRDMD_DVBT2_TUNE_INFO_OK,
CXD2880_TNRDMD_DVBT2_TUNE_INFO_INVALID_PLP_ID
};
struct cxd2880_dvbt2_tune_param {
u32 center_freq_khz;
enum cxd2880_dtv_bandwidth bandwidth;
u16 data_plp_id;
enum cxd2880_dvbt2_profile profile;
enum cxd2880_tnrdmd_dvbt2_tune_info tune_info;
};
#define CXD2880_DVBT2_TUNE_PARAM_PLPID_AUTO 0xffff
int cxd2880_tnrdmd_dvbt2_tune1(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt2_tune2(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_tune_param
*tune_param);
int cxd2880_tnrdmd_dvbt2_sleep_setting(struct cxd2880_tnrdmd
*tnr_dmd);
int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_lock_result
*lock);
int cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd
*tnr_dmd, u8 auto_plp,
u8 plp_id);
int cxd2880_tnrdmd_dvbt2_diver_fef_setting(struct cxd2880_tnrdmd
*tnr_dmd);
int cxd2880_tnrdmd_dvbt2_check_l1post_valid(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *l1_post_valid);
#endif
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,135 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt2_mon.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T2 monitor interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT2_MON_H
#define CXD2880_TNRDMD_DVBT2_MON_H
#include "cxd2880_tnrdmd.h"
#include "cxd2880_dvbt2.h"
int cxd2880_tnrdmd_dvbt2_mon_sync_stat(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *ts_lock_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt2_mon_sync_stat_sub(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *sync_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt2_mon_carrier_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *offset);
int cxd2880_tnrdmd_dvbt2_mon_carrier_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *offset);
int cxd2880_tnrdmd_dvbt2_mon_l1_pre(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_l1pre
*l1_pre);
int cxd2880_tnrdmd_dvbt2_mon_version(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_version
*ver);
int cxd2880_tnrdmd_dvbt2_mon_ofdm(struct cxd2880_tnrdmd *tnr_dmd,
struct cxd2880_dvbt2_ofdm *ofdm);
int cxd2880_tnrdmd_dvbt2_mon_data_plps(struct cxd2880_tnrdmd
*tnr_dmd, u8 *plp_ids,
u8 *num_plps);
int cxd2880_tnrdmd_dvbt2_mon_active_plp(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_dvbt2_plp_btype
type,
struct cxd2880_dvbt2_plp
*plp_info);
int cxd2880_tnrdmd_dvbt2_mon_data_plp_error(struct cxd2880_tnrdmd
*tnr_dmd,
u8 *plp_error);
int cxd2880_tnrdmd_dvbt2_mon_l1_change(struct cxd2880_tnrdmd
*tnr_dmd, u8 *l1_change);
int cxd2880_tnrdmd_dvbt2_mon_l1_post(struct cxd2880_tnrdmd
*tnr_dmd,
struct cxd2880_dvbt2_l1post
*l1_post);
int cxd2880_tnrdmd_dvbt2_mon_bbheader(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_plp_btype
type,
struct cxd2880_dvbt2_bbheader
*bbheader);
int cxd2880_tnrdmd_dvbt2_mon_in_bandb_ts_rate(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_dvbt2_plp_btype
type,
u32 *ts_rate_bps);
int cxd2880_tnrdmd_dvbt2_mon_spectrum_sense(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_spectrum_sense
*sense);
int cxd2880_tnrdmd_dvbt2_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
int *snr);
int cxd2880_tnrdmd_dvbt2_mon_snr_diver(struct cxd2880_tnrdmd
*tnr_dmd, int *snr,
int *snr_main,
int *snr_sub);
int cxd2880_tnrdmd_dvbt2_mon_packet_error_number(struct
cxd2880_tnrdmd
*tnr_dmd,
u32 *pen);
int cxd2880_tnrdmd_dvbt2_mon_sampling_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *ppm);
int cxd2880_tnrdmd_dvbt2_mon_sampling_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *ppm);
int cxd2880_tnrdmd_dvbt2_mon_qam(struct cxd2880_tnrdmd *tnr_dmd,
enum cxd2880_dvbt2_plp_btype type,
enum cxd2880_dvbt2_plp_constell
*qam);
int cxd2880_tnrdmd_dvbt2_mon_code_rate(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_plp_btype
type,
enum
cxd2880_dvbt2_plp_code_rate
*code_rate);
int cxd2880_tnrdmd_dvbt2_mon_profile(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt2_profile
*profile);
int cxd2880_tnrdmd_dvbt2_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi);
int cxd2880_tnrdmd_dvbt2_mon_ssi_sub(struct cxd2880_tnrdmd
*tnr_dmd, u8 *ssi);
#endif
@@ -0,0 +1,775 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_tnrdmd_dvbt_mon.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T monitor functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_tnrdmd_mon.h"
#include "cxd2880_tnrdmd_dvbt.h"
#include "cxd2880_tnrdmd_dvbt_mon.h"
#include <linux/int_log.h>
static const int ref_dbm_1000[3][5] = {
{-93000, -91000, -90000, -89000, -88000},
{-87000, -85000, -84000, -83000, -82000},
{-82000, -80000, -78000, -77000, -76000},
};
static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd);
int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *ts_lock_stat,
u8 *unlock_detected)
{
u8 rdata = 0x00;
int ret;
if (!tnr_dmd || !sync_stat || !ts_lock_stat || !unlock_detected)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x10, &rdata, 1);
if (ret)
return ret;
*unlock_detected = (rdata & 0x10) ? 1 : 0;
*sync_stat = rdata & 0x07;
*ts_lock_stat = (rdata & 0x20) ? 1 : 0;
if (*sync_stat == 0x07)
return -EAGAIN;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *unlock_detected)
{
u8 ts_lock_stat = 0;
if (!tnr_dmd || !sync_stat || !unlock_detected)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd->diver_sub,
sync_stat,
&ts_lock_stat,
unlock_detected);
}
int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt_mode
*mode,
enum cxd2880_dvbt_guard
*guard)
{
u8 rdata = 0x00;
int ret;
if (!tnr_dmd || !mode || !guard)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret =
cxd2880_tnrdmd_dvbt_mon_mode_guard(tnr_dmd->diver_sub,
mode, guard);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x1b, &rdata, 1);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
*mode = (enum cxd2880_dvbt_mode)((rdata >> 2) & 0x03);
*guard = (enum cxd2880_dvbt_guard)(rdata & 0x03);
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *offset)
{
u8 rdata[4];
u32 ctl_val = 0;
int ret;
if (!tnr_dmd || !offset)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x1d, rdata, 4);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
ctl_val =
((rdata[0] & 0x1f) << 24) | (rdata[1] << 16) | (rdata[2] << 8) |
(rdata[3]);
*offset = cxd2880_convert2s_complement(ctl_val, 29);
*offset = -1 * ((*offset) * tnr_dmd->bandwidth / 235);
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *offset)
{
if (!tnr_dmd || !offset)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_dvbt_mon_carrier_offset(tnr_dmd->diver_sub,
offset);
}
int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd
*tnr_dmd,
struct cxd2880_dvbt_tpsinfo
*info)
{
u8 rdata[7];
u8 cell_id_ok = 0;
int ret;
if (!tnr_dmd || !info)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret =
cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd->diver_sub,
info);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x29, rdata, 7);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x11);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0xd5, &cell_id_ok, 1);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
info->constellation =
(enum cxd2880_dvbt_constellation)((rdata[0] >> 6) & 0x03);
info->hierarchy = (enum cxd2880_dvbt_hierarchy)((rdata[0] >> 3) & 0x07);
info->rate_hp = (enum cxd2880_dvbt_coderate)(rdata[0] & 0x07);
info->rate_lp = (enum cxd2880_dvbt_coderate)((rdata[1] >> 5) & 0x07);
info->guard = (enum cxd2880_dvbt_guard)((rdata[1] >> 3) & 0x03);
info->mode = (enum cxd2880_dvbt_mode)((rdata[1] >> 1) & 0x03);
info->fnum = (rdata[2] >> 6) & 0x03;
info->length_indicator = rdata[2] & 0x3f;
info->cell_id = (rdata[3] << 8) | rdata[4];
info->reserved_even = rdata[5] & 0x3f;
info->reserved_odd = rdata[6] & 0x3f;
info->cell_id_ok = cell_id_ok & 0x01;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct
cxd2880_tnrdmd
*tnr_dmd,
u32 *pen)
{
u8 rdata[3];
int ret;
if (!tnr_dmd || !pen)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x26, rdata, 3);
if (ret)
return ret;
if (!(rdata[0] & 0x01))
return -EAGAIN;
*pen = (rdata[1] << 8) | rdata[2];
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_spectrum_sense
*sense)
{
u8 data = 0;
int ret;
if (!tnr_dmd || !sense)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_MAIN)
ret = cxd2880_tnrdmd_dvbt_mon_spectrum_sense(tnr_dmd->diver_sub,
sense);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x1c, &data, sizeof(data));
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
*sense =
(data & 0x01) ? CXD2880_TNRDMD_SPECTRUM_INV :
CXD2880_TNRDMD_SPECTRUM_NORMAL;
return ret;
}
static int dvbt_read_snr_reg(struct cxd2880_tnrdmd *tnr_dmd,
u16 *reg_value)
{
u8 rdata[2];
int ret;
if (!tnr_dmd || !reg_value)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x13, rdata, 2);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
*reg_value = (rdata[0] << 8) | rdata[1];
return ret;
}
static int dvbt_calc_snr(struct cxd2880_tnrdmd *tnr_dmd,
u32 reg_value, int *snr)
{
if (!tnr_dmd || !snr)
return -EINVAL;
if (reg_value == 0)
return -EAGAIN;
if (reg_value > 4996)
reg_value = 4996;
*snr = intlog10(reg_value) - intlog10(5350 - reg_value);
*snr = (*snr + 839) / 1678 + 28500;
return 0;
}
int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
int *snr)
{
u16 reg_value = 0;
int ret;
if (!tnr_dmd || !snr)
return -EINVAL;
*snr = -1000 * 1000;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SINGLE) {
ret = dvbt_read_snr_reg(tnr_dmd, &reg_value);
if (ret)
return ret;
ret = dvbt_calc_snr(tnr_dmd, reg_value, snr);
} else {
int snr_main = 0;
int snr_sub = 0;
ret =
cxd2880_tnrdmd_dvbt_mon_snr_diver(tnr_dmd, snr, &snr_main,
&snr_sub);
}
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd
*tnr_dmd, int *snr,
int *snr_main, int *snr_sub)
{
u16 reg_value = 0;
u32 reg_value_sum = 0;
int ret;
if (!tnr_dmd || !snr || !snr_main || !snr_sub)
return -EINVAL;
*snr = -1000 * 1000;
*snr_main = -1000 * 1000;
*snr_sub = -1000 * 1000;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = dvbt_read_snr_reg(tnr_dmd, &reg_value);
if (!ret) {
ret = dvbt_calc_snr(tnr_dmd, reg_value, snr_main);
if (ret)
reg_value = 0;
} else if (ret == -EAGAIN) {
reg_value = 0;
} else {
return ret;
}
reg_value_sum += reg_value;
ret = dvbt_read_snr_reg(tnr_dmd->diver_sub, &reg_value);
if (!ret) {
ret = dvbt_calc_snr(tnr_dmd->diver_sub, reg_value, snr_sub);
if (ret)
reg_value = 0;
} else if (ret == -EAGAIN) {
reg_value = 0;
} else {
return ret;
}
reg_value_sum += reg_value;
return dvbt_calc_snr(tnr_dmd, reg_value_sum, snr);
}
int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *ppm)
{
u8 ctl_val_reg[5];
u8 nominal_rate_reg[5];
u32 trl_ctl_val = 0;
u32 trcg_nominal_rate = 0;
int num;
int den;
s8 diff_upper = 0;
int ret;
if (!tnr_dmd || !ppm)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = slvt_freeze_reg(tnr_dmd);
if (ret)
return ret;
ret = is_tps_locked(tnr_dmd);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x0d);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x21, ctl_val_reg,
sizeof(ctl_val_reg));
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x04);
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x60, nominal_rate_reg,
sizeof(nominal_rate_reg));
if (ret) {
slvt_unfreeze_reg(tnr_dmd);
return ret;
}
slvt_unfreeze_reg(tnr_dmd);
diff_upper =
(ctl_val_reg[0] & 0x7f) - (nominal_rate_reg[0] & 0x7f);
if (diff_upper < -1 || diff_upper > 1)
return -EAGAIN;
trl_ctl_val = ctl_val_reg[1] << 24;
trl_ctl_val |= ctl_val_reg[2] << 16;
trl_ctl_val |= ctl_val_reg[3] << 8;
trl_ctl_val |= ctl_val_reg[4];
trcg_nominal_rate = nominal_rate_reg[1] << 24;
trcg_nominal_rate |= nominal_rate_reg[2] << 16;
trcg_nominal_rate |= nominal_rate_reg[3] << 8;
trcg_nominal_rate |= nominal_rate_reg[4];
trl_ctl_val >>= 1;
trcg_nominal_rate >>= 1;
if (diff_upper == 1)
num =
(int)((trl_ctl_val + 0x80000000u) -
trcg_nominal_rate);
else if (diff_upper == -1)
num =
-(int)((trcg_nominal_rate + 0x80000000u) -
trl_ctl_val);
else
num = (int)(trl_ctl_val - trcg_nominal_rate);
den = (nominal_rate_reg[0] & 0x7f) << 24;
den |= nominal_rate_reg[1] << 16;
den |= nominal_rate_reg[2] << 8;
den |= nominal_rate_reg[3];
den = (den + (390625 / 2)) / 390625;
den >>= 1;
if (num >= 0)
*ppm = (num + (den / 2)) / den;
else
*ppm = (num - (den / 2)) / den;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd, int *ppm)
{
if (!tnr_dmd || !ppm)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_dvbt_mon_sampling_offset(tnr_dmd->diver_sub, ppm);
}
static int dvbt_calc_ssi(struct cxd2880_tnrdmd *tnr_dmd,
int rf_lvl, u8 *ssi)
{
struct cxd2880_dvbt_tpsinfo tps;
int prel;
int temp_ssi = 0;
int ret;
if (!tnr_dmd || !ssi)
return -EINVAL;
ret = cxd2880_tnrdmd_dvbt_mon_tps_info(tnr_dmd, &tps);
if (ret)
return ret;
if (tps.constellation >= CXD2880_DVBT_CONSTELLATION_RESERVED_3 ||
tps.rate_hp >= CXD2880_DVBT_CODERATE_RESERVED_5)
return -EINVAL;
prel = rf_lvl - ref_dbm_1000[tps.constellation][tps.rate_hp];
if (prel < -15000)
temp_ssi = 0;
else if (prel < 0)
temp_ssi = ((2 * (prel + 15000)) + 1500) / 3000;
else if (prel < 20000)
temp_ssi = (((4 * prel) + 500) / 1000) + 10;
else if (prel < 35000)
temp_ssi = (((2 * (prel - 20000)) + 1500) / 3000) + 90;
else
temp_ssi = 100;
*ssi = (temp_ssi > 100) ? 100 : (u8)temp_ssi;
return ret;
}
int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi)
{
int rf_lvl = 0;
int ret;
if (!tnr_dmd || !ssi)
return -EINVAL;
if (tnr_dmd->diver_mode == CXD2880_TNRDMD_DIVERMODE_SUB)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd, &rf_lvl);
if (ret)
return ret;
return dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi);
}
int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi)
{
int rf_lvl = 0;
int ret;
if (!tnr_dmd || !ssi)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
if (tnr_dmd->sys != CXD2880_DTV_SYS_DVBT)
return -EINVAL;
ret = cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, &rf_lvl);
if (ret)
return ret;
return dvbt_calc_ssi(tnr_dmd, rf_lvl, ssi);
}
static int is_tps_locked(struct cxd2880_tnrdmd *tnr_dmd)
{
u8 sync = 0;
u8 tslock = 0;
u8 early_unlock = 0;
int ret;
if (!tnr_dmd)
return -EINVAL;
ret =
cxd2880_tnrdmd_dvbt_mon_sync_stat(tnr_dmd, &sync, &tslock,
&early_unlock);
if (ret)
return ret;
if (sync != 6)
return -EAGAIN;
return 0;
}
@@ -0,0 +1,77 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_dvbt_mon.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* DVB-T monitor interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_DVBT_MON_H
#define CXD2880_TNRDMD_DVBT_MON_H
#include "cxd2880_tnrdmd.h"
#include "cxd2880_dvbt.h"
int cxd2880_tnrdmd_dvbt_mon_sync_stat(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *ts_lock_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt_mon_sync_stat_sub(struct cxd2880_tnrdmd
*tnr_dmd, u8 *sync_stat,
u8 *unlock_detected);
int cxd2880_tnrdmd_dvbt_mon_mode_guard(struct cxd2880_tnrdmd
*tnr_dmd,
enum cxd2880_dvbt_mode
*mode,
enum cxd2880_dvbt_guard
*guard);
int cxd2880_tnrdmd_dvbt_mon_carrier_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *offset);
int cxd2880_tnrdmd_dvbt_mon_carrier_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *offset);
int cxd2880_tnrdmd_dvbt_mon_tps_info(struct cxd2880_tnrdmd
*tnr_dmd,
struct cxd2880_dvbt_tpsinfo
*info);
int cxd2880_tnrdmd_dvbt_mon_packet_error_number(struct
cxd2880_tnrdmd
*tnr_dmd,
u32 *pen);
int cxd2880_tnrdmd_dvbt_mon_spectrum_sense(struct cxd2880_tnrdmd
*tnr_dmd,
enum
cxd2880_tnrdmd_spectrum_sense
*sense);
int cxd2880_tnrdmd_dvbt_mon_snr(struct cxd2880_tnrdmd *tnr_dmd,
int *snr);
int cxd2880_tnrdmd_dvbt_mon_snr_diver(struct cxd2880_tnrdmd
*tnr_dmd, int *snr,
int *snr_main, int *snr_sub);
int cxd2880_tnrdmd_dvbt_mon_sampling_offset(struct cxd2880_tnrdmd
*tnr_dmd, int *ppm);
int cxd2880_tnrdmd_dvbt_mon_sampling_offset_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
int *ppm);
int cxd2880_tnrdmd_dvbt_mon_ssi(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi);
int cxd2880_tnrdmd_dvbt_mon_ssi_sub(struct cxd2880_tnrdmd *tnr_dmd,
u8 *ssi);
#endif
@@ -0,0 +1,150 @@
// SPDX-License-Identifier: GPL-2.0
/*
* cxd2880_tnrdmd_mon.c
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common monitor functions
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd_mon.h"
static const u8 rf_lvl_seq[2] = {
0x80, 0x00,
};
int cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db)
{
u8 rdata[2];
int ret;
if (!tnr_dmd || !rf_lvl_db)
return -EINVAL;
if (tnr_dmd->state != CXD2880_TNRDMD_STATE_ACTIVE)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x00);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x10, 0x01);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x00, 0x10);
if (ret)
return ret;
ret = tnr_dmd->io->write_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x5b, rf_lvl_seq, 2);
if (ret)
return ret;
usleep_range(2000, 3000);
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x00, 0x1a);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x15, rdata, 2);
if (ret)
return ret;
if (rdata[0] || rdata[1])
return -EINVAL;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x11, rdata, 2);
if (ret)
return ret;
*rf_lvl_db =
cxd2880_convert2s_complement((rdata[0] << 3) |
((rdata[1] & 0xe0) >> 5), 11);
*rf_lvl_db *= 125;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x00, 0x00);
if (ret)
return ret;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_DMD,
0x10, 0x00);
if (ret)
return ret;
if (tnr_dmd->rf_lvl_cmpstn)
ret = tnr_dmd->rf_lvl_cmpstn(tnr_dmd, rf_lvl_db);
return ret;
}
int cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db)
{
if (!tnr_dmd || !rf_lvl_db)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_mon_rf_lvl(tnr_dmd->diver_sub, rf_lvl_db);
}
int cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd
*tnr_dmd, u16 *status)
{
u8 data[2] = { 0 };
int ret;
if (!tnr_dmd || !status)
return -EINVAL;
ret = tnr_dmd->io->write_reg(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x00, 0x1a);
if (ret)
return ret;
ret = tnr_dmd->io->read_regs(tnr_dmd->io,
CXD2880_IO_TGT_SYS,
0x15, data, 2);
if (ret)
return ret;
*status = (data[0] << 8) | data[1];
return 0;
}
int cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
u16 *status)
{
if (!tnr_dmd || !status)
return -EINVAL;
if (tnr_dmd->diver_mode != CXD2880_TNRDMD_DIVERMODE_MAIN)
return -EINVAL;
return cxd2880_tnrdmd_mon_internal_cpu_status(tnr_dmd->diver_sub,
status);
}
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* cxd2880_tnrdmd_mon.h
* Sony CXD2880 DVB-T2/T tuner + demodulator driver
* common monitor interface
*
* Copyright (C) 2016, 2017, 2018 Sony Semiconductor Solutions Corporation
*/
#ifndef CXD2880_TNRDMD_MON_H
#define CXD2880_TNRDMD_MON_H
#include "cxd2880_common.h"
#include "cxd2880_tnrdmd.h"
int cxd2880_tnrdmd_mon_rf_lvl(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db);
int cxd2880_tnrdmd_mon_rf_lvl_sub(struct cxd2880_tnrdmd *tnr_dmd,
int *rf_lvl_db);
int cxd2880_tnrdmd_mon_internal_cpu_status(struct cxd2880_tnrdmd
*tnr_dmd, u16 *status);
int cxd2880_tnrdmd_mon_internal_cpu_status_sub(struct
cxd2880_tnrdmd
*tnr_dmd,
u16 *status);
#endif
File diff suppressed because it is too large Load Diff